diff options
Diffstat (limited to 'core/math')
-rw-r--r-- | core/math/geometry.cpp | 131 | ||||
-rw-r--r-- | core/math/geometry.h | 57 | ||||
-rw-r--r-- | core/math/math_funcs.cpp | 2 | ||||
-rw-r--r-- | core/math/quick_hull.cpp | 3 |
4 files changed, 190 insertions, 3 deletions
diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index cb76b9ed0f..2d525dd1ce 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -1004,3 +1004,134 @@ DVector<Plane> Geometry::build_capsule_planes(float p_radius, float p_height, in } + +struct _AtlasWorkRect { + + Size2i s; + Point2i p; + int idx; + _FORCE_INLINE_ bool operator<(const _AtlasWorkRect& p_r) const { return s.width > p_r.s.width; }; +}; + +struct _AtlasWorkRectResult { + + Vector<_AtlasWorkRect> result; + int max_w; + int max_h; +}; + +void Geometry::make_atlas(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size) { + + //super simple, almost brute force scanline stacking fitter + //it's pretty basic for now, but it tries to make sure that the aspect ratio of the + //resulting atlas is somehow square. This is necesary because video cards have limits + //on texture size (usually 2048 or 4096), so the more square a texture, the more chances + //it will work in every hardware. + // for example, it will prioritize a 1024x1024 atlas (works everywhere) instead of a + // 256x8192 atlas (won't work anywhere). + + ERR_FAIL_COND(p_rects.size()==0); + + Vector<_AtlasWorkRect> wrects; + wrects.resize(p_rects.size()); + for(int i=0;i<p_rects.size();i++) { + wrects[i].s=p_rects[i]; + wrects[i].idx=i; + } + wrects.sort(); + int widest = wrects[0].s.width; + + Vector<_AtlasWorkRectResult> results; + + for(int i=0;i<=12;i++) { + + int w = 1<<i; + int max_h=0; + int max_w=0; + if ( w < widest ) + continue; + + Vector<int> hmax; + hmax.resize(w); + for(int j=0;j<w;j++) + hmax[j]=0; + + //place them + int ofs=0; + int limit_h=0; + for(int j=0;j<wrects.size();j++) { + + + if (ofs+wrects[j].s.width > w) { + + ofs=0; + } + + int from_y=0; + for(int k=0;k<wrects[j].s.width;k++) { + + if (hmax[ofs+k] > from_y) + from_y=hmax[ofs+k]; + } + + wrects[j].p.x=ofs; + wrects[j].p.y=from_y; + int end_h = from_y+wrects[j].s.height; + int end_w = ofs+wrects[j].s.width; + if (ofs==0) + limit_h=end_h; + + for(int k=0;k<wrects[j].s.width;k++) { + + hmax[ofs+k]=end_h; + } + + if (end_h > max_h) + max_h=end_h; + + if (end_w > max_w) + max_w=end_w; + + if (ofs==0 || end_h>limit_h ) //while h limit not reched, keep stacking + ofs+=wrects[j].s.width; + + } + + _AtlasWorkRectResult result; + result.result=wrects; + result.max_h=max_h; + result.max_w=max_w; + results.push_back(result); + + } + + //find the result with the best aspect ratio + + int best=-1; + float best_aspect=1e20; + + for(int i=0;i<results.size();i++) { + + float h = nearest_power_of_2(results[i].max_h); + float w = nearest_power_of_2(results[i].max_w); + float aspect = h>w ? h/w : w/h; + if (aspect < best_aspect) { + best=i; + best_aspect=aspect; + } + } + + r_result.resize(p_rects.size()); + + for(int i=0;i<p_rects.size();i++) { + + r_result[ results[best].result[i].idx ]=results[best].result[i].p; + } + + r_size=Size2(results[best].max_w,results[best].max_h ); + +} + + + + diff --git a/core/math/geometry.h b/core/math/geometry.h index 5b21c25bec..81530e30c0 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -821,12 +821,67 @@ public: }; + + _FORCE_INLINE_ static int get_uv84_normal_bit(const Vector3& p_vector) { + + int lat = Math::fast_ftoi(Math::floor(Math::acos(p_vector.dot(Vector3(0,1,0)))*4.0/Math_PI+0.5)); + + if (lat==0) { + return 24; + } else if (lat==4) { + return 25; + } + + int lon = Math::fast_ftoi(Math::floor( (Math_PI+Math::atan2(p_vector.x,p_vector.z))*8.0/(Math_PI*2.0) + 0.5))%8; + + return lon+(lat-1)*8; + } + + _FORCE_INLINE_ static int get_uv84_normal_bit_neighbors(int p_idx) { + + if (p_idx==24) { + return 1|2|4|8; + } else if (p_idx==25) { + return (1<<23)|(1<<22)|(1<<21)|(1<<20); + } else { + + int ret = 0; + if ((p_idx%8) == 0) + ret|=(1<<(p_idx+7)); + else + ret|=(1<<(p_idx-1)); + if ((p_idx%8) == 7) + ret|=(1<<(p_idx-7)); + else + ret|=(1<<(p_idx+1)); + + int mask = ret|(1<<p_idx); + if (p_idx<8) + ret|=24; + else + ret|=mask>>8; + + if (p_idx>=16) + ret|=25; + else + ret|=mask<<8; + + return ret; + } + + } + + + + static MeshData build_convex_mesh(const DVector<Plane> &p_planes); static DVector<Plane> build_sphere_planes(float p_radius, int p_lats, int p_lons, Vector3::Axis p_axis=Vector3::AXIS_Z); static DVector<Plane> build_box_planes(const Vector3& p_extents); static DVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis=Vector3::AXIS_Z); static DVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis=Vector3::AXIS_Z); - + + static void make_atlas(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size); + }; diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 92236a374f..ad48ceaac0 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -76,7 +76,7 @@ void Math::seed(uint32_t x) { void Math::randomize() { OS::Time time = OS::get_singleton()->get_time(); - seed(OS::get_singleton()->get_ticks_usec()*time.hour*time.min*time.sec*rand()); /* *OS::get_singleton()->get_time().sec); // windows doesn't have get_time(), returns always 0 */ + seed(OS::get_singleton()->get_ticks_usec()*(time.hour+1)*(time.min+1)*(time.sec+1)*rand()); /* *OS::get_singleton()->get_time().sec); // windows doesn't have get_time(), returns always 0 */ } uint32_t Math::rand() { diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index ed30de6915..a417cdaddf 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -63,7 +63,7 @@ Error QuickHull::build(const Vector<Vector3>& p_points, Geometry::MeshData &r_me Vector3 sp = p_points[i].snapped(0.0001); if (valid_cache.has(sp)) { valid_points[i]=false; - print_line("INVALIDATED: "+itos(i)); + //print_line("INVALIDATED: "+itos(i)); }else { valid_points[i]=true; valid_cache.insert(sp); @@ -428,6 +428,7 @@ Error QuickHull::build(const Vector<Vector3>& p_points, Geometry::MeshData &r_me List<Geometry::MeshData::Face>::Element *O = F->get().left == E ? F->get().right : F->get().left; ERR_CONTINUE(O==E); + ERR_CONTINUE(O==NULL); if (O->get().plane.is_almost_like(f.plane)) { //merge and delete edge and contiguous face, while repointing edges (uuugh!) |