diff options
Diffstat (limited to 'core/math')
35 files changed, 1125 insertions, 714 deletions
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index 198d9f6076..0d6997183f 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -295,10 +295,10 @@ bool AStar::_solve(Point* begin_point, Point* end_point) { } -DVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { +PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { - ERR_FAIL_COND_V(!points.has(p_from_id),DVector<Vector3>()); - ERR_FAIL_COND_V(!points.has(p_to_id),DVector<Vector3>()); + ERR_FAIL_COND_V(!points.has(p_from_id),PoolVector<Vector3>()); + ERR_FAIL_COND_V(!points.has(p_to_id),PoolVector<Vector3>()); pass++; @@ -307,7 +307,7 @@ DVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { Point* b = points[p_to_id]; if (a==b) { - DVector<Vector3> ret; + PoolVector<Vector3> ret; ret.push_back(a->pos); return ret; } @@ -319,7 +319,7 @@ DVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { bool found_route=_solve(begin_point,end_point); if (!found_route) - return DVector<Vector3>(); + return PoolVector<Vector3>(); //midpoints Point *p=end_point; @@ -329,11 +329,11 @@ DVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { p=p->prev_point; } - DVector<Vector3> path; + PoolVector<Vector3> path; path.resize(pc); { - DVector<Vector3>::Write w = path.write(); + PoolVector<Vector3>::Write w = path.write(); Point *p=end_point; int idx=pc-1; @@ -351,10 +351,10 @@ DVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { } -DVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { +PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { - ERR_FAIL_COND_V(!points.has(p_from_id),DVector<int>()); - ERR_FAIL_COND_V(!points.has(p_to_id),DVector<int>()); + ERR_FAIL_COND_V(!points.has(p_from_id),PoolVector<int>()); + ERR_FAIL_COND_V(!points.has(p_to_id),PoolVector<int>()); pass++; @@ -363,7 +363,7 @@ DVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { Point* b = points[p_to_id]; if (a==b) { - DVector<int> ret; + PoolVector<int> ret; ret.push_back(a->id); return ret; } @@ -375,7 +375,7 @@ DVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { bool found_route=_solve(begin_point,end_point); if (!found_route) - return DVector<int>(); + return PoolVector<int>(); //midpoints Point *p=end_point; @@ -385,11 +385,11 @@ DVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { p=p->prev_point; } - DVector<int> path; + PoolVector<int> path; path.resize(pc); { - DVector<int>::Write w = path.write(); + PoolVector<int>::Write w = path.write(); p=end_point; int idx=pc-1; @@ -407,23 +407,23 @@ DVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { void AStar::_bind_methods() { - ObjectTypeDB::bind_method(_MD("get_available_point_id"),&AStar::get_available_point_id); - ObjectTypeDB::bind_method(_MD("add_point","id","pos","weight_scale"),&AStar::add_point,DEFVAL(1.0)); - ObjectTypeDB::bind_method(_MD("get_point_pos","id"),&AStar::get_point_pos); - ObjectTypeDB::bind_method(_MD("get_point_weight_scale","id"),&AStar::get_point_weight_scale); - ObjectTypeDB::bind_method(_MD("remove_point","id"),&AStar::remove_point); + ClassDB::bind_method(_MD("get_available_point_id"),&AStar::get_available_point_id); + ClassDB::bind_method(_MD("add_point","id","pos","weight_scale"),&AStar::add_point,DEFVAL(1.0)); + ClassDB::bind_method(_MD("get_point_pos","id"),&AStar::get_point_pos); + ClassDB::bind_method(_MD("get_point_weight_scale","id"),&AStar::get_point_weight_scale); + ClassDB::bind_method(_MD("remove_point","id"),&AStar::remove_point); - ObjectTypeDB::bind_method(_MD("connect_points","id","to_id"),&AStar::connect_points); - ObjectTypeDB::bind_method(_MD("disconnect_points","id","to_id"),&AStar::disconnect_points); - ObjectTypeDB::bind_method(_MD("are_points_connected","id","to_id"),&AStar::are_points_connected); + ClassDB::bind_method(_MD("connect_points","id","to_id"),&AStar::connect_points); + ClassDB::bind_method(_MD("disconnect_points","id","to_id"),&AStar::disconnect_points); + ClassDB::bind_method(_MD("are_points_connected","id","to_id"),&AStar::are_points_connected); - ObjectTypeDB::bind_method(_MD("clear"),&AStar::clear); + ClassDB::bind_method(_MD("clear"),&AStar::clear); - ObjectTypeDB::bind_method(_MD("get_closest_point","to_pos"),&AStar::get_closest_point); - ObjectTypeDB::bind_method(_MD("get_closest_pos_in_segment","to_pos"),&AStar::get_closest_pos_in_segment); + ClassDB::bind_method(_MD("get_closest_point","to_pos"),&AStar::get_closest_point); + ClassDB::bind_method(_MD("get_closest_pos_in_segment","to_pos"),&AStar::get_closest_pos_in_segment); - ObjectTypeDB::bind_method(_MD("get_point_path","from_id","to_id"),&AStar::get_point_path); - ObjectTypeDB::bind_method(_MD("get_id_path","from_id","to_id"),&AStar::get_id_path); + ClassDB::bind_method(_MD("get_point_path","from_id","to_id"),&AStar::get_point_path); + ClassDB::bind_method(_MD("get_id_path","from_id","to_id"),&AStar::get_id_path); } diff --git a/core/math/a_star.h b/core/math/a_star.h index 26f3a85046..35e6ead226 100644 --- a/core/math/a_star.h +++ b/core/math/a_star.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,7 +37,7 @@ class AStar: public Reference { - OBJ_TYPE(AStar,Reference) + GDCLASS(AStar,Reference) uint64_t pass; @@ -113,8 +113,8 @@ public: int get_closest_point(const Vector3& p_point) const; Vector3 get_closest_pos_in_segment(const Vector3& p_point) const; - DVector<Vector3> get_point_path(int p_from_id, int p_to_id); - DVector<int> get_id_path(int p_from_id, int p_to_id); + PoolVector<Vector3> get_point_path(int p_from_id, int p_to_id); + PoolVector<int> get_id_path(int p_from_id, int p_to_id); AStar(); ~AStar(); diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp index 6d8a5a72f0..3518eea7ac 100644 --- a/core/math/aabb.cpp +++ b/core/math/aabb.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,24 +30,24 @@ #include "print_string.h" -float AABB::get_area() const { +float Rect3::get_area() const { return size.x*size.y*size.z; } -bool AABB::operator==(const AABB& p_rval) const { +bool Rect3::operator==(const Rect3& p_rval) const { return ((pos==p_rval.pos) && (size==p_rval.size)); } -bool AABB::operator!=(const AABB& p_rval) const { +bool Rect3::operator!=(const Rect3& p_rval) const { return ((pos!=p_rval.pos) || (size!=p_rval.size)); } -void AABB::merge_with(const AABB& p_aabb) { +void Rect3::merge_with(const Rect3& p_aabb) { Vector3 beg_1,beg_2; Vector3 end_1,end_2; @@ -70,7 +70,7 @@ void AABB::merge_with(const AABB& p_aabb) { size=max-min; } -AABB AABB::intersection(const AABB& p_aabb) const { +Rect3 Rect3::intersection(const Rect3& p_aabb) const { Vector3 src_min=pos; Vector3 src_max=pos+size; @@ -80,7 +80,7 @@ AABB AABB::intersection(const AABB& p_aabb) const { Vector3 min,max; if (src_min.x > dst_max.x || src_max.x < dst_min.x ) - return AABB(); + return Rect3(); else { min.x= ( src_min.x > dst_min.x ) ? src_min.x :dst_min.x; @@ -89,7 +89,7 @@ AABB AABB::intersection(const AABB& p_aabb) const { } if (src_min.y > dst_max.y || src_max.y < dst_min.y ) - return AABB(); + return Rect3(); else { min.y= ( src_min.y > dst_min.y ) ? src_min.y :dst_min.y; @@ -98,7 +98,7 @@ AABB AABB::intersection(const AABB& p_aabb) const { } if (src_min.z > dst_max.z || src_max.z < dst_min.z ) - return AABB(); + return Rect3(); else { min.z= ( src_min.z > dst_min.z ) ? src_min.z :dst_min.z; @@ -107,10 +107,10 @@ AABB AABB::intersection(const AABB& p_aabb) const { } - return AABB( min, max-min ); + return Rect3( min, max-min ); } -bool AABB::intersects_ray(const Vector3& p_from, const Vector3& p_dir,Vector3* r_clip,Vector3* r_normal) const { +bool Rect3::intersects_ray(const Vector3& p_from, const Vector3& p_dir,Vector3* r_clip,Vector3* r_normal) const { Vector3 c1, c2; Vector3 end = pos+size; @@ -155,7 +155,7 @@ bool AABB::intersects_ray(const Vector3& p_from, const Vector3& p_dir,Vector3* r } -bool AABB::intersects_segment(const Vector3& p_from, const Vector3& p_to,Vector3* r_clip,Vector3* r_normal) const { +bool Rect3::intersects_segment(const Vector3& p_from, const Vector3& p_to,Vector3* r_clip,Vector3* r_normal) const { real_t min=0,max=1; int axis=0; @@ -216,7 +216,7 @@ bool AABB::intersects_segment(const Vector3& p_from, const Vector3& p_to,Vector3 } -bool AABB::intersects_plane(const Plane &p_plane) const { +bool Rect3::intersects_plane(const Plane &p_plane) const { Vector3 points[8] = { Vector3( pos.x , pos.y , pos.z ), @@ -246,7 +246,7 @@ bool AABB::intersects_plane(const Plane &p_plane) const { -Vector3 AABB::get_longest_axis() const { +Vector3 Rect3::get_longest_axis() const { Vector3 axis(1,0,0); real_t max_size=size.x; @@ -263,7 +263,7 @@ Vector3 AABB::get_longest_axis() const { return axis; } -int AABB::get_longest_axis_index() const { +int Rect3::get_longest_axis_index() const { int axis=0; real_t max_size=size.x; @@ -282,7 +282,7 @@ int AABB::get_longest_axis_index() const { } -Vector3 AABB::get_shortest_axis() const { +Vector3 Rect3::get_shortest_axis() const { Vector3 axis(1,0,0); real_t max_size=size.x; @@ -299,7 +299,7 @@ Vector3 AABB::get_shortest_axis() const { return axis; } -int AABB::get_shortest_axis_index() const { +int Rect3::get_shortest_axis_index() const { int axis=0; real_t max_size=size.x; @@ -317,26 +317,26 @@ int AABB::get_shortest_axis_index() const { return axis; } -AABB AABB::merge(const AABB& p_with) const { +Rect3 Rect3::merge(const Rect3& p_with) const { - AABB aabb=*this; + Rect3 aabb=*this; aabb.merge_with(p_with); return aabb; } -AABB AABB::expand(const Vector3& p_vector) const { - AABB aabb=*this; +Rect3 Rect3::expand(const Vector3& p_vector) const { + Rect3 aabb=*this; aabb.expand_to(p_vector); return aabb; } -AABB AABB::grow(real_t p_by) const { +Rect3 Rect3::grow(real_t p_by) const { - AABB aabb=*this; + Rect3 aabb=*this; aabb.grow_by(p_by); return aabb; } -void AABB::get_edge(int p_edge,Vector3& r_from,Vector3& r_to) const { +void Rect3::get_edge(int p_edge,Vector3& r_from,Vector3& r_to) const { ERR_FAIL_INDEX(p_edge,12); switch(p_edge) { @@ -412,7 +412,7 @@ void AABB::get_edge(int p_edge,Vector3& r_from,Vector3& r_to) const { } -AABB::operator String() const { +Rect3::operator String() const { return String()+pos +" - "+ size; } diff --git a/core/math/aabb.h b/core/math/aabb.h index 57fe1b32f5..2816d1f012 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -40,7 +40,7 @@ -class AABB { +class Rect3 { public: Vector3 pos; Vector3 size; @@ -62,16 +62,16 @@ public: void set_size(const Vector3& p_size) { size=p_size; } - bool operator==(const AABB& p_rval) const; - bool operator!=(const AABB& p_rval) const; + bool operator==(const Rect3& p_rval) const; + bool operator!=(const Rect3& p_rval) const; - _FORCE_INLINE_ bool intersects(const AABB& p_aabb) const; /// Both AABBs overlap - _FORCE_INLINE_ bool intersects_inclusive(const AABB& p_aabb) const; /// Both AABBs (or their faces) overlap - _FORCE_INLINE_ bool encloses(const AABB & p_aabb) const; /// p_aabb is completely inside this + _FORCE_INLINE_ bool intersects(const Rect3& p_aabb) const; /// Both AABBs overlap + _FORCE_INLINE_ bool intersects_inclusive(const Rect3& p_aabb) const; /// Both AABBs (or their faces) overlap + _FORCE_INLINE_ bool encloses(const Rect3 & p_aabb) const; /// p_aabb is completely inside this - AABB merge(const AABB& p_with) const; - void merge_with(const AABB& p_aabb); ///merge with another AABB - AABB intersection(const AABB& p_aabb) const; ///get box where two intersect, empty if no intersection occurs + Rect3 merge(const Rect3& p_with) const; + void merge_with(const Rect3& p_aabb); ///merge with another AABB + Rect3 intersection(const Rect3& p_aabb) const; ///get box where two intersect, empty if no intersection occurs bool intersects_segment(const Vector3& p_from, const Vector3& p_to,Vector3* r_clip=NULL,Vector3* r_normal=NULL) const; bool intersects_ray(const Vector3& p_from, const Vector3& p_dir,Vector3* r_clip=NULL,Vector3* r_normal=NULL) const; _FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &from,const Vector3& p_dir, float t0, float t1) const; @@ -91,25 +91,25 @@ public: int get_shortest_axis_index() const; _FORCE_INLINE_ real_t get_shortest_axis_size() const; - AABB grow(real_t p_by) const; + Rect3 grow(real_t p_by) const; _FORCE_INLINE_ void grow_by(real_t p_amount); void get_edge(int p_edge,Vector3& r_from,Vector3& r_to) const; _FORCE_INLINE_ Vector3 get_endpoint(int p_point) const; - AABB expand(const Vector3& p_vector) const; + Rect3 expand(const Vector3& p_vector) const; _FORCE_INLINE_ void project_range_in_plane(const Plane& p_plane,float &r_min,float& r_max) const; _FORCE_INLINE_ void expand_to(const Vector3& p_vector); /** expand to contain a point if necesary */ operator String() const; - _FORCE_INLINE_ AABB() {} - inline AABB(const Vector3 &p_pos,const Vector3& p_size) { pos=p_pos; size=p_size; } + _FORCE_INLINE_ Rect3() {} + inline Rect3(const Vector3 &p_pos,const Vector3& p_size) { pos=p_pos; size=p_size; } }; -inline bool AABB::intersects(const AABB& p_aabb) const { +inline bool Rect3::intersects(const Rect3& p_aabb) const { if ( pos.x >= (p_aabb.pos.x + p_aabb.size.x) ) return false; @@ -127,7 +127,7 @@ inline bool AABB::intersects(const AABB& p_aabb) const { return true; } -inline bool AABB::intersects_inclusive(const AABB& p_aabb) const { +inline bool Rect3::intersects_inclusive(const Rect3& p_aabb) const { if ( pos.x > (p_aabb.pos.x + p_aabb.size.x) ) return false; @@ -145,7 +145,7 @@ inline bool AABB::intersects_inclusive(const AABB& p_aabb) const { return true; } -inline bool AABB::encloses(const AABB & p_aabb) const { +inline bool Rect3::encloses(const Rect3 & p_aabb) const { Vector3 src_min=pos; Vector3 src_max=pos+size; @@ -162,7 +162,7 @@ inline bool AABB::encloses(const AABB & p_aabb) const { } -Vector3 AABB::get_support(const Vector3& p_normal) const { +Vector3 Rect3::get_support(const Vector3& p_normal) const { Vector3 half_extents = size * 0.5; Vector3 ofs = pos + half_extents; @@ -175,7 +175,7 @@ Vector3 AABB::get_support(const Vector3& p_normal) const { } -Vector3 AABB::get_endpoint(int p_point) const { +Vector3 Rect3::get_endpoint(int p_point) const { switch(p_point) { case 0: return Vector3( pos.x , pos.y , pos.z ); @@ -191,7 +191,7 @@ Vector3 AABB::get_endpoint(int p_point) const { ERR_FAIL_V(Vector3()); } -bool AABB::intersects_convex_shape(const Plane *p_planes, int p_plane_count) const { +bool Rect3::intersects_convex_shape(const Plane *p_planes, int p_plane_count) const { #if 1 @@ -251,7 +251,7 @@ bool AABB::intersects_convex_shape(const Plane *p_planes, int p_plane_count) con #endif } -bool AABB::has_point(const Vector3& p_point) const { +bool Rect3::has_point(const Vector3& p_point) const { if (p_point.x<pos.x) return false; @@ -270,7 +270,7 @@ bool AABB::has_point(const Vector3& p_point) const { } -inline void AABB::expand_to(const Vector3& p_vector) { +inline void Rect3::expand_to(const Vector3& p_vector) { Vector3 begin=pos; Vector3 end=pos+size; @@ -293,7 +293,7 @@ inline void AABB::expand_to(const Vector3& p_vector) { size=end-begin; } -void AABB::project_range_in_plane(const Plane& p_plane,float &r_min,float& r_max) const { +void Rect3::project_range_in_plane(const Plane& p_plane,float &r_min,float& r_max) const { Vector3 half_extents( size.x * 0.5, size.y * 0.5, size.z * 0.5 ); Vector3 center( pos.x + half_extents.x, pos.y + half_extents.y, pos.z + half_extents.z ); @@ -304,7 +304,7 @@ void AABB::project_range_in_plane(const Plane& p_plane,float &r_min,float& r_max r_max = distance + length; } -inline real_t AABB::get_longest_axis_size() const { +inline real_t Rect3::get_longest_axis_size() const { real_t max_size=size.x; @@ -319,7 +319,7 @@ inline real_t AABB::get_longest_axis_size() const { return max_size; } -inline real_t AABB::get_shortest_axis_size() const { +inline real_t Rect3::get_shortest_axis_size() const { real_t max_size=size.x; @@ -334,7 +334,7 @@ inline real_t AABB::get_shortest_axis_size() const { return max_size; } -bool AABB::smits_intersect_ray(const Vector3 &from,const Vector3& dir, float t0, float t1) const { +bool Rect3::smits_intersect_ray(const Vector3 &from,const Vector3& dir, float t0, float t1) const { float divx=1.0/dir.x; float divy=1.0/dir.y; @@ -381,7 +381,7 @@ bool AABB::smits_intersect_ray(const Vector3 &from,const Vector3& dir, float t0, return ( (tmin < t1) && (tmax > t0) ); } -void AABB::grow_by(real_t p_amount) { +void Rect3::grow_by(real_t p_amount) { pos.x-=p_amount; pos.y-=p_amount; @@ -391,6 +391,5 @@ void AABB::grow_by(real_t p_amount) { size.z+=2.0*p_amount; } -typedef AABB Rect3; #endif // AABB_H diff --git a/core/math/bsp_tree.cpp b/core/math/bsp_tree.cpp index d16495217c..e2526f5134 100644 --- a/core/math/bsp_tree.cpp +++ b/core/math/bsp_tree.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #include "print_string.h" -void BSP_Tree::from_aabb(const AABB& p_aabb) { +void BSP_Tree::from_aabb(const Rect3& p_aabb) { planes.clear(); @@ -67,7 +67,7 @@ Vector<Plane> BSP_Tree::get_planes() const { return planes; } -AABB BSP_Tree::get_aabb() const { +Rect3 BSP_Tree::get_aabb() const { return aabb; } @@ -390,8 +390,10 @@ static int _bsp_create_node(const Face3 *p_faces,const Vector<int>& p_indices,Ve const Face3& f=p_faces[ indices[i] ]; - //if (f.get_plane().is_almost_like(divisor_plane)) - // continue; + /* + if (f.get_plane().is_almost_like(divisor_plane)) + continue; + */ int over_count=0; int under_count=0; @@ -484,7 +486,7 @@ BSP_Tree::operator Variant() const { d["planes"]=plane_values; - DVector<int> dst_nodes; + PoolVector<int> dst_nodes; dst_nodes.resize(nodes.size()*3); for(int i=0;i<nodes.size();i++) { @@ -514,19 +516,19 @@ BSP_Tree::BSP_Tree(const Variant& p_variant) { ERR_FAIL_COND(!d.has("aabb")); ERR_FAIL_COND(!d.has("error_radius")); - DVector<int> src_nodes = d["nodes"]; + PoolVector<int> src_nodes = d["nodes"]; ERR_FAIL_COND(src_nodes.size()%3); - if (d["planes"].get_type()==Variant::REAL_ARRAY) { + if (d["planes"].get_type()==Variant::POOL_REAL_ARRAY) { - DVector<float> src_planes=d["planes"]; + PoolVector<float> src_planes=d["planes"]; int plane_count=src_planes.size(); ERR_FAIL_COND(plane_count%4); planes.resize(plane_count/4); if (plane_count) { - DVector<float>::Read r = src_planes.read(); + PoolVector<float>::Read r = src_planes.read(); for(int i=0;i<plane_count/4;i++) { planes[i].normal.x=r[i*4+0]; @@ -546,10 +548,10 @@ BSP_Tree::BSP_Tree(const Variant& p_variant) { error_radius = d["error"]; aabb = d["aabb"]; -// int node_count = src_nodes.size(); + //int node_count = src_nodes.size(); nodes.resize(src_nodes.size()/3); - DVector<int>::Read r = src_nodes.read(); + PoolVector<int>::Read r = src_nodes.read(); for(int i=0;i<nodes.size();i++) { @@ -560,12 +562,12 @@ BSP_Tree::BSP_Tree(const Variant& p_variant) { } -BSP_Tree::BSP_Tree(const DVector<Face3>& p_faces,float p_error_radius) { +BSP_Tree::BSP_Tree(const PoolVector<Face3>& p_faces,float p_error_radius) { // compute aabb int face_count=p_faces.size(); - DVector<Face3>::Read faces_r=p_faces.read(); + PoolVector<Face3>::Read faces_r=p_faces.read(); const Face3 *facesptr = faces_r.ptr(); @@ -613,7 +615,7 @@ BSP_Tree::BSP_Tree(const DVector<Face3>& p_faces,float p_error_radius) { error_radius=p_error_radius; } -BSP_Tree::BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const AABB& p_aabb,float p_error_radius) { +BSP_Tree::BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const Rect3& p_aabb,float p_error_radius) { nodes=p_nodes; planes=p_planes; diff --git a/core/math/bsp_tree.h b/core/math/bsp_tree.h index 6c36d80e3e..e01df96555 100644 --- a/core/math/bsp_tree.h +++ b/core/math/bsp_tree.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -65,7 +65,7 @@ private: Vector<Node> nodes; Vector<Plane> planes; - AABB aabb; + Rect3 aabb; float error_radius; int _get_points_inside(int p_node,const Vector3* p_points,int *p_indices, const Vector3& p_center,const Vector3& p_half_extents,int p_indices_count) const; @@ -78,7 +78,7 @@ public: bool is_empty() const { return nodes.size()==0; } Vector<Node> get_nodes() const; Vector<Plane> get_planes() const; - AABB get_aabb() const; + Rect3 get_aabb() const; bool point_is_inside(const Vector3& p_point) const; int get_points_inside(const Vector3* p_points, int p_point_count) const; @@ -87,12 +87,12 @@ public: operator Variant() const; - void from_aabb(const AABB& p_aabb); + void from_aabb(const Rect3& p_aabb); BSP_Tree(); BSP_Tree(const Variant& p_variant); - BSP_Tree(const DVector<Face3>& p_faces,float p_error_radius=0); - BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const AABB& p_aabb,float p_error_radius=0); + BSP_Tree(const PoolVector<Face3>& p_faces,float p_error_radius=0); + BSP_Tree(const Vector<Node> &p_nodes, const Vector<Plane> &p_planes, const Rect3& p_aabb,float p_error_radius=0); ~BSP_Tree(); }; diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index f7dd8839b8..c44ff4682a 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -54,7 +54,7 @@ void CameraMatrix::set_zero() { } -Plane CameraMatrix::xform4(const Plane& p_vec4) { +Plane CameraMatrix::xform4(const Plane& p_vec4) const { Plane ret; @@ -495,6 +495,28 @@ void CameraMatrix::set_light_bias() { } +void CameraMatrix::set_light_atlas_rect(const Rect2& p_rect) { + + float *m=&matrix[0][0]; + + m[0]=p_rect.size.width, + m[1]=0.0, + m[2]=0.0, + m[3]=0.0, + m[4]=0.0, + m[5]=p_rect.size.height, + m[6]=0.0, + m[7]=0.0, + m[8]=0.0, + m[9]=0.0, + m[10]=1.0, + m[11]=0.0, + m[12]=p_rect.pos.x, + m[13]=p_rect.pos.y, + m[14]=0.0, + m[15]=1.0; +} + CameraMatrix::operator String() const { String str; @@ -512,6 +534,15 @@ float CameraMatrix::get_aspect() const { return w/h; } +int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const { + + + Vector3 result = xform(Vector3(1,0,-1)); + + return int((result.x * 0.5 + 0.5) * p_for_pixel_width); + +} + float CameraMatrix::get_fov() const { const float * matrix = (const float*)this->matrix; @@ -533,7 +564,7 @@ void CameraMatrix::make_scale(const Vector3 &p_scale) { } -void CameraMatrix::scale_translate_to_fit(const AABB& p_aabb) { +void CameraMatrix::scale_translate_to_fit(const Rect3& p_aabb) { Vector3 min = p_aabb.pos; Vector3 max = p_aabb.pos+p_aabb.size; diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index d192b1fef1..952f1e8fb2 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,6 +30,7 @@ #define CAMERA_MATRIX_H #include "transform.h" +#include "math_2d.h" /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -53,6 +54,7 @@ struct CameraMatrix { void set_identity(); void set_zero(); void set_light_bias(); + void set_light_atlas_rect(const Rect2& p_rect); void set_perspective(float p_fovy_degrees, float p_aspect, float p_z_near, float p_z_far,bool p_flip_fov=false); void set_orthogonal(float p_left, float p_right, float p_bottom, float p_top, float p_znear, float p_zfar); void set_orthogonal(float p_size, float p_aspect, float p_znear, float p_zfar,bool p_flip_fov=false); @@ -78,13 +80,14 @@ struct CameraMatrix { CameraMatrix operator*(const CameraMatrix& p_matrix) const; - Plane xform4(const Plane& p_vec4); + Plane xform4(const Plane& p_vec4) const; _FORCE_INLINE_ Vector3 xform(const Vector3& p_vec3) const; operator String() const; - void scale_translate_to_fit(const AABB& p_aabb); + void scale_translate_to_fit(const Rect3& p_aabb); void make_scale(const Vector3 &p_scale); + int get_pixels_per_meter(int p_for_pixel_width) const; operator Transform() const; CameraMatrix(); diff --git a/core/math/face3.cpp b/core/math/face3.cpp index e1af91f28e..faf124593e 100644 --- a/core/math/face3.cpp +++ b/core/math/face3.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -205,7 +205,7 @@ ClockDirection Face3::get_clock_dir() const { } -bool Face3::intersects_aabb(const AABB& p_aabb) const { +bool Face3::intersects_aabb(const Rect3& p_aabb) const { /** TEST PLANE **/ if (!p_aabb.intersects_plane( get_plane() )) diff --git a/core/math/face3.h b/core/math/face3.h index 3a81da74db..f08eb227b1 100644 --- a/core/math/face3.h +++ b/core/math/face3.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -78,16 +78,16 @@ public: void get_support(const Vector3& p_normal,const Transform& p_transform,Vector3 *p_vertices,int* p_count,int p_max) const; void project_range(const Vector3& p_normal,const Transform& p_transform,float& r_min, float& r_max) const; - AABB get_aabb() const { + Rect3 get_aabb() const { - AABB aabb( vertex[0], Vector3() ); + Rect3 aabb( vertex[0], Vector3() ); aabb.expand_to( vertex[1] ); aabb.expand_to( vertex[2] ); return aabb; } - bool intersects_aabb(const AABB& p_aabb) const; - _FORCE_INLINE_ bool intersects_aabb2(const AABB& p_aabb) const; + bool intersects_aabb(const Rect3& p_aabb) const; + _FORCE_INLINE_ bool intersects_aabb2(const Rect3& p_aabb) const; operator String() const; inline Face3() {} @@ -96,7 +96,7 @@ public: }; -bool Face3::intersects_aabb2(const AABB& p_aabb) const { +bool Face3::intersects_aabb2(const Rect3& p_aabb) const { Vector3 perp = (vertex[0]-vertex[2]).cross(vertex[0]-vertex[1]); diff --git a/core/math/geometry.cpp b/core/math/geometry.cpp index 790903eff5..bf3364a052 100644 --- a/core/math/geometry.cpp +++ b/core/math/geometry.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -204,21 +204,21 @@ static bool _group_face(_FaceClassify *p_faces, int len, int p_index,int p_group } -DVector< DVector< Face3 > > Geometry::separate_objects( DVector< Face3 > p_array ) { +PoolVector< PoolVector< Face3 > > Geometry::separate_objects( PoolVector< Face3 > p_array ) { - DVector< DVector< Face3 > > objects; + PoolVector< PoolVector< Face3 > > objects; int len = p_array.size(); - DVector<Face3>::Read r=p_array.read(); + PoolVector<Face3>::Read r=p_array.read(); const Face3* arrayptr = r.ptr(); - DVector< _FaceClassify> fc; + PoolVector< _FaceClassify> fc; fc.resize( len ); - DVector< _FaceClassify >::Write fcw=fc.write(); + PoolVector< _FaceClassify >::Write fcw=fc.write(); _FaceClassify * _fcptr = fcw.ptr(); @@ -231,7 +231,7 @@ DVector< DVector< Face3 > > Geometry::separate_objects( DVector< Face3 > p_array if (error) { - ERR_FAIL_COND_V(error, DVector< DVector< Face3 > >() ); // invalid geometry + ERR_FAIL_COND_V(error, PoolVector< PoolVector< Face3 > >() ); // invalid geometry } /* group connected faces in separate objects */ @@ -257,8 +257,8 @@ DVector< DVector< Face3 > > Geometry::separate_objects( DVector< Face3 > p_array if (group>=0) { objects.resize(group); - DVector< DVector<Face3> >::Write obw=objects.write(); - DVector< Face3 > *group_faces = obw.ptr(); + PoolVector< PoolVector<Face3> >::Write obw=objects.write(); + PoolVector< Face3 > *group_faces = obw.ptr(); for (int i=0;i<len;i++) { if (!_fcptr[i].valid) @@ -304,7 +304,7 @@ enum _CellFlags { static inline void _plot_face(uint8_t*** p_cell_status,int x,int y,int z,int len_x,int len_y,int len_z,const Vector3& voxelsize,const Face3& p_face) { - AABB aabb( Vector3(x,y,z),Vector3(len_x,len_y,len_z)); + Rect3 aabb( Vector3(x,y,z),Vector3(len_x,len_y,len_z)); aabb.pos=aabb.pos*voxelsize; aabb.size=aabb.size*voxelsize; @@ -487,7 +487,7 @@ static inline void _mark_outside(uint8_t*** p_cell_status,int x,int y,int z,int } } -static inline void _build_faces(uint8_t*** p_cell_status,int x,int y,int z,int len_x,int len_y,int len_z,DVector<Face3>& p_faces) { +static inline void _build_faces(uint8_t*** p_cell_status,int x,int y,int z,int len_x,int len_y,int len_z,PoolVector<Face3>& p_faces) { ERR_FAIL_INDEX(x,len_x); ERR_FAIL_INDEX(y,len_y); @@ -580,16 +580,16 @@ static inline void _build_faces(uint8_t*** p_cell_status,int x,int y,int z,int l } -DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_error ) { +PoolVector< Face3 > Geometry::wrap_geometry( PoolVector< Face3 > p_array,float *p_error ) { #define _MIN_SIZE 1.0 #define _MAX_LENGTH 20 int face_count=p_array.size(); - DVector<Face3>::Read facesr=p_array.read(); + PoolVector<Face3>::Read facesr=p_array.read(); const Face3 *faces = facesr.ptr(); - AABB global_aabb; + Rect3 global_aabb; for(int i=0;i<face_count;i++) { @@ -696,7 +696,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro //print_line("Wrapper (3/6): Building Faces"); - DVector<Face3> wrapped_faces; + PoolVector<Face3> wrapped_faces; for (int i=0;i<div_x;i++) { @@ -714,7 +714,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro // transform face vertices to global coords int wrapped_faces_count=wrapped_faces.size(); - DVector<Face3>::Write wrapped_facesw=wrapped_faces.write(); + PoolVector<Face3>::Write wrapped_facesw=wrapped_faces.write(); Face3* wrapped_faces_ptr=wrapped_facesw.ptr(); for(int i=0;i<wrapped_faces_count;i++) { @@ -748,7 +748,7 @@ DVector< Face3 > Geometry::wrap_geometry( DVector< Face3 > p_array,float *p_erro return wrapped_faces; } -Geometry::MeshData Geometry::build_convex_mesh(const DVector<Plane> &p_planes) { +Geometry::MeshData Geometry::build_convex_mesh(const PoolVector<Plane> &p_planes) { MeshData mesh; @@ -896,9 +896,9 @@ Geometry::MeshData Geometry::build_convex_mesh(const DVector<Plane> &p_planes) { } -DVector<Plane> Geometry::build_box_planes(const Vector3& p_extents) { +PoolVector<Plane> Geometry::build_box_planes(const Vector3& p_extents) { - DVector<Plane> planes; + PoolVector<Plane> planes; planes.push_back( Plane( Vector3(1,0,0), p_extents.x ) ); planes.push_back( Plane( Vector3(-1,0,0), p_extents.x ) ); @@ -910,9 +910,9 @@ DVector<Plane> Geometry::build_box_planes(const Vector3& p_extents) { return planes; } -DVector<Plane> Geometry::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) { +PoolVector<Plane> Geometry::build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis) { - DVector<Plane> planes; + PoolVector<Plane> planes; for (int i=0;i<p_sides;i++) { @@ -933,10 +933,10 @@ DVector<Plane> Geometry::build_cylinder_planes(float p_radius, float p_height, i } -DVector<Plane> Geometry::build_sphere_planes(float p_radius, int p_lats,int p_lons, Vector3::Axis p_axis) { +PoolVector<Plane> Geometry::build_sphere_planes(float p_radius, int p_lats,int p_lons, Vector3::Axis p_axis) { - DVector<Plane> planes; + PoolVector<Plane> planes; Vector3 axis; axis[p_axis]=1.0; @@ -969,9 +969,9 @@ DVector<Plane> Geometry::build_sphere_planes(float p_radius, int p_lats,int p_lo } -DVector<Plane> Geometry::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) { +PoolVector<Plane> Geometry::build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis) { - DVector<Plane> planes; + PoolVector<Plane> planes; Vector3 axis; axis[p_axis]=1.0; diff --git a/core/math/geometry.h b/core/math/geometry.h index b353423851..d5b3a3068c 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -750,9 +750,7 @@ public: return Vector<Vector3>(); //empty } -// long count = 0; long previous = polygon.size() - 1; - Vector<Vector3> clipped; for (int index = 0; index < polygon.size(); index++) { @@ -808,9 +806,9 @@ public: } - static DVector< DVector< Face3 > > separate_objects( DVector< Face3 > p_array ); + static PoolVector< PoolVector< Face3 > > separate_objects( PoolVector< Face3 > p_array ); - static DVector< Face3 > wrap_geometry( DVector< Face3 > p_array, float *p_error=NULL ); ///< create a "wrap" that encloses the given geometry + static PoolVector< Face3 > wrap_geometry( PoolVector< Face3 > p_array, float *p_error=NULL ); ///< create a "wrap" that encloses the given geometry struct MeshData { @@ -919,11 +917,11 @@ public: return H; } - 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 MeshData build_convex_mesh(const PoolVector<Plane> &p_planes); + static PoolVector<Plane> build_sphere_planes(float p_radius, int p_lats, int p_lons, Vector3::Axis p_axis=Vector3::AXIS_Z); + static PoolVector<Plane> build_box_planes(const Vector3& p_extents); + static PoolVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis=Vector3::AXIS_Z); + static PoolVector<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_2d.cpp b/core/math/math_2d.cpp index e616f05914..c6860ba2e8 100644 --- a/core/math/math_2d.cpp +++ b/core/math/math_2d.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,22 +31,22 @@ real_t Vector2::angle() const { - return Math::atan2(x,y); + return Math::atan2(y,x); } -float Vector2::length() const { +real_t Vector2::length() const { return Math::sqrt( x*x + y*y ); } -float Vector2::length_squared() const { +real_t Vector2::length_squared() const { return x*x + y*y; } void Vector2::normalize() { - float l = x*x + y*y; + real_t l = x*x + y*y; if (l!=0) { l=Math::sqrt(l); @@ -62,32 +62,32 @@ Vector2 Vector2::normalized() const { return v; } -float Vector2::distance_to(const Vector2& p_vector2) const { +real_t Vector2::distance_to(const Vector2& p_vector2) const { return Math::sqrt( (x-p_vector2.x)*(x-p_vector2.x) + (y-p_vector2.y)*(y-p_vector2.y)); } -float Vector2::distance_squared_to(const Vector2& p_vector2) const { +real_t Vector2::distance_squared_to(const Vector2& p_vector2) const { return (x-p_vector2.x)*(x-p_vector2.x) + (y-p_vector2.y)*(y-p_vector2.y); } -float Vector2::angle_to(const Vector2& p_vector2) const { +real_t Vector2::angle_to(const Vector2& p_vector2) const { - return Math::atan2( tangent().dot(p_vector2), dot(p_vector2) ); + return Math::atan2( cross(p_vector2), dot(p_vector2) ); } -float Vector2::angle_to_point(const Vector2& p_vector2) const { +real_t Vector2::angle_to_point(const Vector2& p_vector2) const { - return Math::atan2( x-p_vector2.x, y - p_vector2.y ); + return Math::atan2( y - p_vector2.y, x-p_vector2.x ); } -float Vector2::dot(const Vector2& p_other) const { +real_t Vector2::dot(const Vector2& p_other) const { return x*p_other.x + y*p_other.y; } -float Vector2::cross(const Vector2& p_other) const { +real_t Vector2::cross(const Vector2& p_other) const { return x*p_other.y - y*p_other.x; } @@ -120,11 +120,11 @@ Vector2 Vector2::operator*(const Vector2 &p_v1) const { return Vector2(x * p_v1.x, y * p_v1.y); }; -Vector2 Vector2::operator*(const float &rvalue) const { +Vector2 Vector2::operator*(const real_t &rvalue) const { return Vector2(x * rvalue, y * rvalue); }; -void Vector2::operator*=(const float &rvalue) { +void Vector2::operator*=(const real_t &rvalue) { x *= rvalue; y *= rvalue; }; @@ -134,12 +134,12 @@ Vector2 Vector2::operator/(const Vector2 &p_v1) const { return Vector2(x / p_v1.x, y / p_v1.y); }; -Vector2 Vector2::operator/(const float &rvalue) const { +Vector2 Vector2::operator/(const real_t &rvalue) const { return Vector2(x / rvalue, y / rvalue); }; -void Vector2::operator/=(const float &rvalue) { +void Vector2::operator/=(const real_t &rvalue) { x /= rvalue; y /= rvalue; }; @@ -162,7 +162,7 @@ Vector2 Vector2::floor() const { return Vector2( Math::floor(x), Math::floor(y) ); } -Vector2 Vector2::rotated(float p_by) const { +Vector2 Vector2::rotated(real_t p_by) const { Vector2 v; v.set_rotation(angle()+p_by); @@ -198,7 +198,7 @@ Vector2 Vector2::clamped(real_t p_len) const { return v; } -Vector2 Vector2::cubic_interpolate_soft(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,float p_t) const { +Vector2 Vector2::cubic_interpolate_soft(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,real_t p_t) const { #if 0 k[0] = ((*this) (vi[0] + 1, vi[1], vi[2])) - ((*this) (vi[0], vi[1],vi[2])); //fk = a0 @@ -219,13 +219,13 @@ Vector2 Vector2::cubic_interpolate_soft(const Vector2& p_b,const Vector2& p_pre_ //dk = (fk+1 - fk-1)*0.5 //Dk = (fk+1 - fk) - float dk = + real_t dk = #endif return Vector2(); } -Vector2 Vector2::cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,float p_t) const { +Vector2 Vector2::cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,real_t p_t) const { @@ -234,9 +234,9 @@ Vector2 Vector2::cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, co Vector2 p2=p_b; Vector2 p3=p_post_b; - float t = p_t; - float t2 = t * t; - float t3 = t2 * t; + real_t t = p_t; + real_t t2 = t * t; + real_t t3 = t2 * t; Vector2 out; out = 0.5f * ( ( p1 * 2.0f) + @@ -246,8 +246,8 @@ Vector2 Vector2::cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, co return out; /* - float mu = p_t; - float mu2 = mu*mu; + real_t mu = p_t; + real_t mu2 = mu*mu; Vector2 a0 = p_post_b - p_b - p_pre_a + *this; Vector2 a1 = p_pre_a - *this - a0; @@ -257,7 +257,7 @@ Vector2 Vector2::cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, co return ( a0*mu*mu2 + a1*mu2 + a2*mu + a3 ); */ /* - float t = p_t; + real_t t = p_t; real_t t2 = t*t; real_t t3 = t2*t; @@ -291,7 +291,7 @@ bool Rect2::intersects_segment(const Point2& p_from, const Point2& p_to, Point2* real_t min=0,max=1; int axis=0; - float sign=0; + real_t sign=0; for(int i=0;i<2;i++) { real_t seg_from=p_from[i]; @@ -299,7 +299,7 @@ bool Rect2::intersects_segment(const Point2& p_from, const Point2& p_to, Point2* real_t box_begin=pos[i]; real_t box_end=box_begin+size[i]; real_t cmin,cmax; - float csign; + real_t csign; if (seg_from < seg_to) { @@ -408,25 +408,26 @@ bool Point2i::operator!=(const Point2i& p_vec2) const { return x!=p_vec2.x || y!=p_vec2.y; } -void Matrix32::invert() { - +void Transform2D::invert() { + // FIXME: this function assumes the basis is a rotation matrix, with no scaling. + // Transform2D::affine_inverse can handle matrices with scaling, so GDScript should eventually use that. SWAP(elements[0][1],elements[1][0]); elements[2] = basis_xform(-elements[2]); } -Matrix32 Matrix32::inverse() const { +Transform2D Transform2D::inverse() const { - Matrix32 inv=*this; + Transform2D inv=*this; inv.invert(); return inv; } -void Matrix32::affine_invert() { +void Transform2D::affine_invert() { - float det = basis_determinant(); + real_t det = basis_determinant(); ERR_FAIL_COND(det==0); - float idet = 1.0 / det; + real_t idet = 1.0 / det; SWAP( elements[0][0],elements[1][1] ); elements[0]*=Vector2(idet,-idet); @@ -436,72 +437,74 @@ void Matrix32::affine_invert() { } -Matrix32 Matrix32::affine_inverse() const { +Transform2D Transform2D::affine_inverse() const { - Matrix32 inv=*this; + Transform2D inv=*this; inv.affine_invert(); return inv; } -void Matrix32::rotate(real_t p_phi) { - - Matrix32 rot(p_phi,Vector2()); - *this *= rot; +void Transform2D::rotate(real_t p_phi) { + *this = Transform2D(p_phi,Vector2()) * (*this); } -real_t Matrix32::get_rotation() const { - - return Math::atan2(elements[1].x,elements[1].y); +real_t Transform2D::get_rotation() const { + real_t det = basis_determinant(); + Transform2D m = orthonormalized(); + if (det < 0) { + m.scale_basis(Size2(-1,-1)); + } + return Math::atan2(m[0].y,m[0].x); } -void Matrix32::set_rotation(real_t p_rot) { +void Transform2D::set_rotation(real_t p_rot) { real_t cr = Math::cos(p_rot); real_t sr = Math::sin(p_rot); elements[0][0]=cr; + elements[0][1]=sr; + elements[1][0]=-sr; elements[1][1]=cr; - elements[0][1]=-sr; - elements[1][0]=sr; } -Matrix32::Matrix32(real_t p_rot, const Vector2& p_pos) { +Transform2D::Transform2D(real_t p_rot, const Vector2& p_pos) { real_t cr = Math::cos(p_rot); real_t sr = Math::sin(p_rot); elements[0][0]=cr; + elements[0][1]=sr; + elements[1][0]=-sr; elements[1][1]=cr; - elements[0][1]=-sr; - elements[1][0]=sr; elements[2]=p_pos; } -Size2 Matrix32::get_scale() const { - - return Size2( elements[0].length(), elements[1].length() ); +Size2 Transform2D::get_scale() const { + real_t det_sign = basis_determinant() > 0 ? 1 : -1; + return det_sign * Size2( elements[0].length(), elements[1].length() ); } -void Matrix32::scale(const Size2& p_scale) { - - elements[0]*=p_scale; - elements[1]*=p_scale; +void Transform2D::scale(const Size2& p_scale) { + scale_basis(p_scale); elements[2]*=p_scale; } -void Matrix32::scale_basis(const Size2& p_scale) { +void Transform2D::scale_basis(const Size2& p_scale) { - elements[0]*=p_scale; - elements[1]*=p_scale; + elements[0][0]*=p_scale.x; + elements[0][1]*=p_scale.y; + elements[1][0]*=p_scale.x; + elements[1][1]*=p_scale.y; } -void Matrix32::translate( real_t p_tx, real_t p_ty) { +void Transform2D::translate( real_t p_tx, real_t p_ty) { translate(Vector2(p_tx,p_ty)); } -void Matrix32::translate( const Vector2& p_translation ) { +void Transform2D::translate( const Vector2& p_translation ) { elements[2]+=basis_xform(p_translation); } -void Matrix32::orthonormalize() { +void Transform2D::orthonormalize() { // Gram-Schmidt Process @@ -515,15 +518,15 @@ void Matrix32::orthonormalize() { elements[0]=x; elements[1]=y; } -Matrix32 Matrix32::orthonormalized() const { +Transform2D Transform2D::orthonormalized() const { - Matrix32 on=*this; + Transform2D on=*this; on.orthonormalize(); return on; } -bool Matrix32::operator==(const Matrix32& p_transform) const { +bool Transform2D::operator==(const Transform2D& p_transform) const { for(int i=0;i<3;i++) { if (elements[i]!=p_transform.elements[i]) @@ -533,7 +536,7 @@ bool Matrix32::operator==(const Matrix32& p_transform) const { return true; } -bool Matrix32::operator!=(const Matrix32& p_transform) const { +bool Transform2D::operator!=(const Transform2D& p_transform) const { for(int i=0;i<3;i++) { if (elements[i]!=p_transform.elements[i]) @@ -544,11 +547,11 @@ bool Matrix32::operator!=(const Matrix32& p_transform) const { } -void Matrix32::operator*=(const Matrix32& p_transform) { +void Transform2D::operator*=(const Transform2D& p_transform) { elements[2] = xform(p_transform.elements[2]); - float x0,x1,y0,y1; + real_t x0,x1,y0,y1; x0 = tdotx(p_transform.elements[0]); x1 = tdoty(p_transform.elements[0]); @@ -562,59 +565,59 @@ void Matrix32::operator*=(const Matrix32& p_transform) { } -Matrix32 Matrix32::operator*(const Matrix32& p_transform) const { +Transform2D Transform2D::operator*(const Transform2D& p_transform) const { - Matrix32 t = *this; + Transform2D t = *this; t*=p_transform; return t; } -Matrix32 Matrix32::scaled(const Size2& p_scale) const { +Transform2D Transform2D::scaled(const Size2& p_scale) const { - Matrix32 copy=*this; + Transform2D copy=*this; copy.scale(p_scale); return copy; } -Matrix32 Matrix32::basis_scaled(const Size2& p_scale) const { +Transform2D Transform2D::basis_scaled(const Size2& p_scale) const { - Matrix32 copy=*this; + Transform2D copy=*this; copy.scale_basis(p_scale); return copy; } -Matrix32 Matrix32::untranslated() const { +Transform2D Transform2D::untranslated() const { - Matrix32 copy=*this; + Transform2D copy=*this; copy.elements[2]=Vector2(); return copy; } -Matrix32 Matrix32::translated(const Vector2& p_offset) const { +Transform2D Transform2D::translated(const Vector2& p_offset) const { - Matrix32 copy=*this; + Transform2D copy=*this; copy.translate(p_offset); return copy; } -Matrix32 Matrix32::rotated(float p_phi) const { +Transform2D Transform2D::rotated(real_t p_phi) const { - Matrix32 copy=*this; + Transform2D copy=*this; copy.rotate(p_phi); return copy; } -float Matrix32::basis_determinant() const { +real_t Transform2D::basis_determinant() const { return elements[0].x * elements[1].y - elements[0].y * elements[1].x; } -Matrix32 Matrix32::interpolate_with(const Matrix32& p_transform, float p_c) const { +Transform2D Transform2D::interpolate_with(const Transform2D& p_transform, real_t p_c) const { //extract parameters Vector2 p1 = get_origin(); @@ -645,12 +648,12 @@ Matrix32 Matrix32::interpolate_with(const Matrix32& p_transform, float p_c) cons } //construct matrix - Matrix32 res(Math::atan2(v.y, v.x), Vector2::linear_interpolate(p1, p2, p_c)); + Transform2D res(Math::atan2(v.y, v.x), Vector2::linear_interpolate(p1, p2, p_c)); res.scale_basis(Vector2::linear_interpolate(s1, s2, p_c)); return res; } -Matrix32::operator String() const { +Transform2D::operator String() const { return String(String()+elements[0]+", "+elements[1]+", "+elements[2]); } diff --git a/core/math/math_2d.h b/core/math/math_2d.h index 38c1ac9656..a24c4266ee 100644 --- a/core/math/math_2d.h +++ b/core/math/math_2d.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -65,35 +65,35 @@ enum VAlign { struct Vector2 { union { - float x; - float width; + real_t x; + real_t width; }; union { - float y; - float height; + real_t y; + real_t height; }; - _FORCE_INLINE_ float& operator[](int p_idx) { + _FORCE_INLINE_ real_t& operator[](int p_idx) { return p_idx?y:x; } - _FORCE_INLINE_ const float& operator[](int p_idx) const { + _FORCE_INLINE_ const real_t& operator[](int p_idx) const { return p_idx?y:x; } void normalize(); Vector2 normalized() const; - float length() const; - float length_squared() const; + real_t length() const; + real_t length_squared() const; - float distance_to(const Vector2& p_vector2) const; - float distance_squared_to(const Vector2& p_vector2) const; - float angle_to(const Vector2& p_vector2) const; - float angle_to_point(const Vector2& p_vector2) const; + real_t distance_to(const Vector2& p_vector2) const; + real_t distance_squared_to(const Vector2& p_vector2) const; + real_t angle_to(const Vector2& p_vector2) const; + real_t angle_to_point(const Vector2& p_vector2) const; - float dot(const Vector2& p_other) const; - float cross(const Vector2& p_other) const; + real_t dot(const Vector2& p_other) const; + real_t cross(const Vector2& p_other) const; Vector2 cross(real_t p_other) const; Vector2 project(const Vector2& p_vec) const; @@ -101,10 +101,10 @@ struct Vector2 { Vector2 clamped(real_t p_len) const; - _FORCE_INLINE_ static Vector2 linear_interpolate(const Vector2& p_a, const Vector2& p_b,float p_t); - _FORCE_INLINE_ Vector2 linear_interpolate(const Vector2& p_b,float p_t) const; - Vector2 cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,float p_t) const; - Vector2 cubic_interpolate_soft(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,float p_t) const; + _FORCE_INLINE_ static Vector2 linear_interpolate(const Vector2& p_a, const Vector2& p_b,real_t p_t); + _FORCE_INLINE_ Vector2 linear_interpolate(const Vector2& p_b,real_t p_t) const; + Vector2 cubic_interpolate(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,real_t p_t) const; + Vector2 cubic_interpolate_soft(const Vector2& p_b,const Vector2& p_pre_a, const Vector2& p_post_b,real_t p_t) const; Vector2 slide(const Vector2& p_vec) const; Vector2 reflect(const Vector2& p_vec) const; @@ -115,15 +115,15 @@ struct Vector2 { void operator-=(const Vector2& p_v); Vector2 operator*(const Vector2 &p_v1) const; - Vector2 operator*(const float &rvalue) const; - void operator*=(const float &rvalue); + Vector2 operator*(const real_t &rvalue) const; + void operator*=(const real_t &rvalue); void operator*=(const Vector2 &rvalue) { *this = *this * rvalue; } Vector2 operator/(const Vector2 &p_v1) const; - Vector2 operator/(const float &rvalue) const; + Vector2 operator/(const real_t &rvalue) const; - void operator/=(const float &rvalue); + void operator/=(const real_t &rvalue); Vector2 operator-() const; @@ -135,10 +135,10 @@ struct Vector2 { real_t angle() const; - void set_rotation(float p_radians) { + void set_rotation(real_t p_radians) { - x=Math::sin(p_radians); - y=Math::cos(p_radians); + x=Math::cos(p_radians); + y=Math::sin(p_radians); } _FORCE_INLINE_ Vector2 abs() const { @@ -146,7 +146,7 @@ struct Vector2 { return Vector2( Math::abs(x), Math::abs(y) ); } - Vector2 rotated(float p_by) const; + Vector2 rotated(real_t p_by) const; Vector2 tangent() const { return Vector2(y,-x); @@ -154,12 +154,12 @@ struct Vector2 { Vector2 floor() const; Vector2 snapped(const Vector2& p_by) const; - float get_aspect() const { return width/height; } + real_t aspect() const { return width/height; } operator String() const { return String::num(x)+", "+String::num(y); } - _FORCE_INLINE_ Vector2(float p_x,float p_y) { x=p_x; y=p_y; } + _FORCE_INLINE_ Vector2(real_t p_x,real_t p_y) { x=p_x; y=p_y; } _FORCE_INLINE_ Vector2() { x=0; y=0; } }; @@ -169,12 +169,12 @@ _FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2& p_vec) } -_FORCE_INLINE_ Vector2 operator*(float p_scalar, const Vector2& p_vec) { +_FORCE_INLINE_ Vector2 operator*(real_t p_scalar, const Vector2& p_vec) { return p_vec*p_scalar; } -Vector2 Vector2::linear_interpolate(const Vector2& p_b,float p_t) const { +Vector2 Vector2::linear_interpolate(const Vector2& p_b,real_t p_t) const { Vector2 res=*this; @@ -185,7 +185,7 @@ Vector2 Vector2::linear_interpolate(const Vector2& p_b,float p_t) const { } -Vector2 Vector2::linear_interpolate(const Vector2& p_a, const Vector2& p_b,float p_t) { +Vector2 Vector2::linear_interpolate(const Vector2& p_a, const Vector2& p_b,real_t p_t) { Vector2 res=p_a; @@ -198,7 +198,7 @@ Vector2 Vector2::linear_interpolate(const Vector2& p_a, const Vector2& p_b,float typedef Vector2 Size2; typedef Vector2 Point2; -struct Matrix32; +struct Transform2D; struct Rect2 { @@ -211,7 +211,7 @@ struct Rect2 { const Vector2& get_size() const { return size; } void set_size(const Vector2& p_size) { size=p_size; } - float get_area() const { return size.width*size.height; } + real_t get_area() const { return size.width*size.height; } inline bool intersects(const Rect2& p_rect) const { if ( pos.x >= (p_rect.pos.x + p_rect.size.width) ) @@ -226,9 +226,9 @@ struct Rect2 { return true; } - inline float distance_to(const Vector2& p_point) const { + inline real_t distance_to(const Vector2& p_point) const { - float dist = 1e20; + real_t dist = 1e20; if (p_point.x < pos.x) { dist=MIN(dist,pos.x-p_point.x); @@ -249,7 +249,7 @@ struct Rect2 { return dist; } - _FORCE_INLINE_ bool intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) const; + _FORCE_INLINE_ bool intersects_transformed(const Transform2D& p_xform, const Rect2& p_rect) const; bool intersects_segment(const Point2& p_from, const Point2& p_to, Point2* r_pos=NULL, Point2* r_normal=NULL) const; @@ -359,7 +359,7 @@ struct Rect2 { operator String() const { return String(pos)+", "+String(size); } Rect2() {} - Rect2( float p_x, float p_y, float p_width, float p_height) { pos=Point2(p_x,p_y); size=Size2( p_width, p_height ); } + Rect2( real_t p_x, real_t p_y, real_t p_width, real_t p_height) { pos=Point2(p_x,p_y); size=Size2( p_width, p_height ); } Rect2( const Point2& p_pos, const Size2& p_size ) { pos=p_pos; size=p_size; } }; @@ -407,7 +407,7 @@ struct Point2i { bool operator==(const Point2i& p_vec2) const; bool operator!=(const Point2i& p_vec2) const; - float get_aspect() const { return width/(float)height; } + real_t get_aspect() const { return width/(real_t)height; } operator String() const { return String::num(x)+", "+String::num(y); } @@ -551,12 +551,22 @@ struct Rect2i { -struct Matrix32 { +struct Transform2D { + // Warning #1: basis of Transform2D is stored differently from Basis. In terms of elements array, the basis matrix looks like "on paper": + // M = (elements[0][0] elements[1][0]) + // (elements[0][1] elements[1][1]) + // This is such that the columns, which can be interpreted as basis vectors of the coordinate system "painted" on the object, can be accessed as elements[i]. + // Note that this is the opposite of the indices in mathematical texts, meaning: $M_{12}$ in a math book corresponds to elements[1][0] here. + // This requires additional care when working with explicit indices. + // See https://en.wikipedia.org/wiki/Row-_and_column-major_order for further reading. + + // Warning #2: 2D be aware that unlike 3D code, 2D code uses a left-handed coordinate system: Y-axis points down, + // and angle is measure from +X to +Y in a clockwise-fashion. Vector2 elements[3]; - _FORCE_INLINE_ float tdotx(const Vector2& v) const { return elements[0][0] * v.x + elements[1][0] * v.y; } - _FORCE_INLINE_ float tdoty(const Vector2& v) const { return elements[0][1] * v.x + elements[1][1] * v.y; } + _FORCE_INLINE_ real_t tdotx(const Vector2& v) const { return elements[0][0] * v.x + elements[1][0] * v.y; } + _FORCE_INLINE_ real_t tdoty(const Vector2& v) const { return elements[0][1] * v.x + elements[1][1] * v.y; } const Vector2& operator[](int p_idx) const { return elements[p_idx]; } Vector2& operator[](int p_idx) { return elements[p_idx]; } @@ -565,10 +575,10 @@ struct Matrix32 { _FORCE_INLINE_ void set_axis(int p_axis,const Vector2& p_vec) { ERR_FAIL_INDEX(p_axis,3); elements[p_axis]=p_vec; } void invert(); - Matrix32 inverse() const; + Transform2D inverse() const; void affine_invert(); - Matrix32 affine_inverse() const; + Transform2D affine_inverse() const; void set_rotation(real_t p_phi); real_t get_rotation() const; @@ -580,30 +590,30 @@ struct Matrix32 { void translate( real_t p_tx, real_t p_ty); void translate( const Vector2& p_translation ); - float basis_determinant() const; + real_t basis_determinant() const; Size2 get_scale() const; _FORCE_INLINE_ const Vector2& get_origin() const { return elements[2]; } _FORCE_INLINE_ void set_origin(const Vector2& p_origin) { elements[2]=p_origin; } - Matrix32 scaled(const Size2& p_scale) const; - Matrix32 basis_scaled(const Size2& p_scale) const; - Matrix32 translated(const Vector2& p_offset) const; - Matrix32 rotated(float p_phi) const; + Transform2D scaled(const Size2& p_scale) const; + Transform2D basis_scaled(const Size2& p_scale) const; + Transform2D translated(const Vector2& p_offset) const; + Transform2D rotated(real_t p_phi) const; - Matrix32 untranslated() const; + Transform2D untranslated() const; void orthonormalize(); - Matrix32 orthonormalized() const; + Transform2D orthonormalized() const; - bool operator==(const Matrix32& p_transform) const; - bool operator!=(const Matrix32& p_transform) const; + bool operator==(const Transform2D& p_transform) const; + bool operator!=(const Transform2D& p_transform) const; - void operator*=(const Matrix32& p_transform); - Matrix32 operator*(const Matrix32& p_transform) const; + void operator*=(const Transform2D& p_transform); + Transform2D operator*(const Transform2D& p_transform) const; - Matrix32 interpolate_with(const Matrix32& p_transform, float p_c) const; + Transform2D interpolate_with(const Transform2D& p_transform, real_t p_c) const; _FORCE_INLINE_ Vector2 basis_xform(const Vector2& p_vec) const; _FORCE_INLINE_ Vector2 basis_xform_inv(const Vector2& p_vec) const; @@ -614,7 +624,7 @@ struct Matrix32 { operator String() const; - Matrix32(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) { + Transform2D(real_t xx, real_t xy, real_t yx, real_t yy, real_t ox, real_t oy) { elements[0][0] = xx; elements[0][1] = xy; @@ -624,11 +634,11 @@ struct Matrix32 { elements[2][1] = oy; } - Matrix32(real_t p_rot, const Vector2& p_pos); - Matrix32() { elements[0][0]=1.0; elements[1][1]=1.0; } + Transform2D(real_t p_rot, const Vector2& p_pos); + Transform2D() { elements[0][0]=1.0; elements[1][1]=1.0; } }; -bool Rect2::intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) const { +bool Rect2::intersects_transformed(const Transform2D& p_xform, const Rect2& p_rect) const { //SAT intersection between local and transformed rect2 @@ -783,7 +793,7 @@ bool Rect2::intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) } -Vector2 Matrix32::basis_xform(const Vector2& v) const { +Vector2 Transform2D::basis_xform(const Vector2& v) const { return Vector2( tdotx(v), @@ -791,7 +801,7 @@ Vector2 Matrix32::basis_xform(const Vector2& v) const { ); } -Vector2 Matrix32::basis_xform_inv(const Vector2& v) const{ +Vector2 Transform2D::basis_xform_inv(const Vector2& v) const{ return Vector2( elements[0].dot(v), @@ -799,14 +809,14 @@ Vector2 Matrix32::basis_xform_inv(const Vector2& v) const{ ); } -Vector2 Matrix32::xform(const Vector2& v) const { +Vector2 Transform2D::xform(const Vector2& v) const { return Vector2( tdotx(v), tdoty(v) ) + elements[2]; } -Vector2 Matrix32::xform_inv(const Vector2& p_vec) const { +Vector2 Transform2D::xform_inv(const Vector2& p_vec) const { Vector2 v = p_vec - elements[2]; @@ -816,7 +826,7 @@ Vector2 Matrix32::xform_inv(const Vector2& p_vec) const { ); } -Rect2 Matrix32::xform(const Rect2& p_rect) const { +Rect2 Transform2D::xform(const Rect2& p_rect) const { Vector2 x=elements[0]*p_rect.size.x; Vector2 y=elements[1]*p_rect.size.y; @@ -830,16 +840,16 @@ Rect2 Matrix32::xform(const Rect2& p_rect) const { return new_rect; } -void Matrix32::set_rotation_and_scale(real_t p_rot,const Size2& p_scale) { +void Transform2D::set_rotation_and_scale(real_t p_rot,const Size2& p_scale) { elements[0][0]=Math::cos(p_rot)*p_scale.x; elements[1][1]=Math::cos(p_rot)*p_scale.y; - elements[0][1]=-Math::sin(p_rot)*p_scale.x; - elements[1][0]=Math::sin(p_rot)*p_scale.y; + elements[1][0]=-Math::sin(p_rot)*p_scale.y; + elements[0][1]=Math::sin(p_rot)*p_scale.x; } -Rect2 Matrix32::xform_inv(const Rect2& p_rect) const { +Rect2 Transform2D::xform_inv(const Rect2& p_rect) const { Vector2 ends[4]={ xform_inv( p_rect.pos ), diff --git a/core/math/math_defs.h b/core/math/math_defs.h index e6a56c5e45..feaff38a44 100644 --- a/core/math/math_defs.h +++ b/core/math/math_defs.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 46c0218707..8353aa0ebe 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,7 @@ #include "math_funcs.h" #include "core/os/os.h" -#include <math.h> + #include "float.h" uint32_t Math::default_seed=1; @@ -69,48 +69,6 @@ double Math::randf() { return (double)rand() / (double)Math::RANDOM_MAX; } -double Math::sin(double p_x) { - - return ::sin(p_x); - -} - -double Math::cos(double p_x) { - - return ::cos(p_x); - -} - -double Math::tan(double p_x) { - - return ::tan(p_x); - -} -double Math::sinh(double p_x) { - - return ::sinh(p_x); -} - -double Math::cosh(double p_x) { - - return ::cosh(p_x); -} - -double Math::tanh(double p_x) { - - return ::tanh(p_x); -} - - -double Math::deg2rad(double p_y) { - - return p_y*Math_PI/180.0; -} - -double Math::rad2deg(double p_y) { - - return p_y*180.0/Math_PI; -} double Math::round(double p_val) { @@ -122,22 +80,6 @@ double Math::round(double p_val) { } } -double Math::asin(double p_x) { - - return ::asin(p_x); - -} - -double Math::acos(double p_x) { - - return ::acos(p_x); -} - -double Math::atan(double p_x) { - - return ::atan(p_x); -} - double Math::dectime(double p_value,double p_amount, double p_step) { float sgn = p_value < 0 ? -1.0 : 1.0; @@ -148,42 +90,6 @@ double Math::dectime(double p_value,double p_amount, double p_step) { return val*sgn; } -double Math::atan2(double p_y, double p_x) { - - return ::atan2(p_y,p_x); - -} -double Math::sqrt(double p_x) { - - return ::sqrt(p_x); -} - -double Math::fmod(double p_x,double p_y) { - - return ::fmod(p_x,p_y); -} - -double Math::fposmod(double p_x,double p_y) { - - if (p_x>=0) { - - return Math::fmod(p_x,p_y); - - } else { - - return p_y-Math::fmod(-p_x,p_y); - } - -} -double Math::floor(double p_x) { - - return ::floor(p_x); -} - -double Math::ceil(double p_x) { - - return ::ceil(p_x); -} int Math::step_decimals(double p_step) { @@ -244,20 +150,7 @@ double Math::stepify(double p_value,double p_step) { return p_value; } -bool Math::is_nan(double p_val) { - - return (p_val!=p_val); -} - -bool Math::is_inf(double p_val) { - -#ifdef _MSC_VER - return !_finite(p_val); -#else - return isinf(p_val); -#endif -} uint32_t Math::larger_prime(uint32_t p_val) { diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index fc76d96b2e..8ce59224ff 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,38 +33,125 @@ #include "math_defs.h" #ifndef NO_MATH_H -#include "math.h" +#include <math.h> #endif +#define Math_PI 3.14159265358979323846 +#define Math_SQRT12 0.7071067811865475244008443621048490 + class Math { static uint32_t default_seed; public: - Math() {}; // useless to instance + Math() {} // useless to instance enum { RANDOM_MAX=2147483647L }; - static double sin(double p_x); - static double cos(double p_x); - static double tan(double p_x); - static double sinh(double p_x); - static double cosh(double p_x); - static double tanh(double p_x); - static double asin(double p_x); - static double acos(double p_x); - static double atan(double p_x); - static double atan2(double p_y, double p_x); - static double deg2rad(double p_y); - static double rad2deg(double p_y); - static double sqrt(double p_x); - static double fmod(double p_x,double p_y); - static double fposmod(double p_x,double p_y); + + static _ALWAYS_INLINE_ double sin(double p_x) { + + return ::sin(p_x); + + } + + static _ALWAYS_INLINE_ double cos(double p_x) { + + return ::cos(p_x); + + } + + static _ALWAYS_INLINE_ double tan(double p_x) { + + return ::tan(p_x); + + } + static _ALWAYS_INLINE_ double sinh(double p_x) { + + return ::sinh(p_x); + } + + static _ALWAYS_INLINE_ double cosh(double p_x) { + + return ::cosh(p_x); + } + + static _ALWAYS_INLINE_ double tanh(double p_x) { + + return ::tanh(p_x); + } + + + static _ALWAYS_INLINE_ double asin(double p_x) { + + return ::asin(p_x); + + } + + static _ALWAYS_INLINE_ double acos(double p_x) { + + return ::acos(p_x); + } + + static _ALWAYS_INLINE_ double atan(double p_x) { + + return ::atan(p_x); + } + + static _ALWAYS_INLINE_ double atan2(double p_y, double p_x) { + + return ::atan2(p_y,p_x); + + } + + static _ALWAYS_INLINE_ double deg2rad(double p_y) { + + return p_y*Math_PI/180.0; + } + + static _ALWAYS_INLINE_ double rad2deg(double p_y) { + + return p_y*180.0/Math_PI; + } + + + static _ALWAYS_INLINE_ double sqrt(double p_x) { + + return ::sqrt(p_x); + } + + static _ALWAYS_INLINE_ double fmod(double p_x,double p_y) { + + return ::fmod(p_x,p_y); + } + + static _ALWAYS_INLINE_ double fposmod(double p_x,double p_y) { + + if (p_x>=0) { + + return fmod(p_x,p_y); + + } else { + + return p_y-fmod(-p_x,p_y); + } + + } + static _ALWAYS_INLINE_ double floor(double p_x) { + + return ::floor(p_x); + } + + static _ALWAYS_INLINE_ double ceil(double p_x) { + + return ::ceil(p_x); + } + + static uint32_t rand_from_seed(uint32_t *seed); - static double floor(double p_x); - static double ceil(double p_x); + static double ease(double p_x, double p_c); static int step_decimals(double p_step); static double stepify(double p_value,double p_step); @@ -84,10 +171,20 @@ public: return Math::exp( p_db * 0.11512925464970228420089957273422 ); } - static bool is_nan(double p_val); - static bool is_inf(double p_val); + static _ALWAYS_INLINE_ bool is_nan(double p_val) { + return (p_val!=p_val); + } + + static _ALWAYS_INLINE_ bool is_inf(double p_val) { + + #ifdef _MSC_VER + return !_finite(p_val); + #else + return isinf(p_val); + #endif + } static uint32_t rand(); static double randf(); @@ -96,6 +193,15 @@ public: static double random(double from, double to); + static _FORCE_INLINE_ bool isequal_approx(real_t a, real_t b) { + // TODO: Comparing floats for approximate-equality is non-trivial. + // Using epsilon should cover the typical cases in Godot (where a == b is used to compare two reals), such as matrix and vector comparison operators. + // A proper implementation in terms of ULPs should eventually replace the contents of this function. + // See https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ for details. + + return abs(a-b) < CMP_EPSILON; + } + static _FORCE_INLINE_ real_t abs(real_t g) { @@ -175,10 +281,110 @@ public: static double log(double x); static double exp(double x); + + static _FORCE_INLINE_ uint32_t halfbits_to_floatbits(uint16_t h) + { + uint16_t h_exp, h_sig; + uint32_t f_sgn, f_exp, f_sig; + + h_exp = (h&0x7c00u); + f_sgn = ((uint32_t)h&0x8000u) << 16; + switch (h_exp) { + case 0x0000u: /* 0 or subnormal */ + h_sig = (h&0x03ffu); + /* Signed zero */ + if (h_sig == 0) { + return f_sgn; + } + /* Subnormal */ + h_sig <<= 1; + while ((h_sig&0x0400u) == 0) { + h_sig <<= 1; + h_exp++; + } + f_exp = ((uint32_t)(127 - 15 - h_exp)) << 23; + f_sig = ((uint32_t)(h_sig&0x03ffu)) << 13; + return f_sgn + f_exp + f_sig; + case 0x7c00u: /* inf or NaN */ + /* All-ones exponent and a copy of the significand */ + return f_sgn + 0x7f800000u + (((uint32_t)(h&0x03ffu)) << 13); + default: /* normalized */ + /* Just need to adjust the exponent and shift */ + return f_sgn + (((uint32_t)(h&0x7fffu) + 0x1c000u) << 13); + } + } + + static _FORCE_INLINE_ float halfptr_to_float(const uint16_t *h) { + + union { + uint32_t u32; + float f32; + } u; + + u.u32=halfbits_to_floatbits(*h); + return u.f32; + } + + static _FORCE_INLINE_ uint16_t make_half_float(float f) { + + union { + float fv; + uint32_t ui; + } ci; + ci.fv=f; + + uint32_t x = ci.ui; + uint32_t sign = (unsigned short)(x >> 31); + uint32_t mantissa; + uint32_t exp; + uint16_t hf; + + // get mantissa + mantissa = x & ((1 << 23) - 1); + // get exponent bits + exp = x & (0xFF << 23); + if (exp >= 0x47800000) + { + // check if the original single precision float number is a NaN + if (mantissa && (exp == (0xFF << 23))) + { + // we have a single precision NaN + mantissa = (1 << 23) - 1; + } + else + { + // 16-bit half-float representation stores number as Inf + mantissa = 0; + } + hf = (((uint16_t)sign) << 15) | (uint16_t)((0x1F << 10)) | + (uint16_t)(mantissa >> 13); + } + // check if exponent is <= -15 + else if (exp <= 0x38000000) + { + + /*// store a denorm half-float value or zero + exp = (0x38000000 - exp) >> 23; + mantissa >>= (14 + exp); + + hf = (((uint16_t)sign) << 15) | (uint16_t)(mantissa); + */ + hf=0; //denormals do not work for 3D, convert to zero + } + else + { + hf = (((uint16_t)sign) << 15) | + (uint16_t)((exp - 0x38000000) >> 13) | + (uint16_t)(mantissa >> 13); + } + + return hf; + } + + + }; -#define Math_PI 3.14159265358979323846 -#define Math_SQRT12 0.7071067811865475244008443621048490 #endif // MATH_FUNCS_H diff --git a/core/math/matrix3.cpp b/core/math/matrix3.cpp index 71e6b62212..e9c3442582 100644 --- a/core/math/matrix3.cpp +++ b/core/math/matrix3.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,7 @@ #define cofac(row1,col1, row2, col2)\ (elements[row1][col1] * elements[row2][col2] - elements[row1][col2] * elements[row2][col1]) -void Matrix3::from_z(const Vector3& p_z) { +void Basis::from_z(const Vector3& p_z) { if (Math::abs(p_z.z) > Math_SQRT12 ) { @@ -53,7 +53,7 @@ void Matrix3::from_z(const Vector3& p_z) { elements[2]=p_z; } -void Matrix3::invert() { +void Basis::invert() { real_t co[3]={ @@ -72,7 +72,8 @@ void Matrix3::invert() { } -void Matrix3::orthonormalize() { +void Basis::orthonormalize() { + ERR_FAIL_COND(determinant() == 0); // Gram-Schmidt Process @@ -92,100 +93,230 @@ void Matrix3::orthonormalize() { } -Matrix3 Matrix3::orthonormalized() const { +Basis Basis::orthonormalized() const { - Matrix3 c = *this; + Basis c = *this; c.orthonormalize(); return c; } +bool Basis::is_orthogonal() const { + Basis id; + Basis m = (*this)*transposed(); -Matrix3 Matrix3::inverse() const { + return isequal_approx(id,m); +} + +bool Basis::is_rotation() const { + return Math::isequal_approx(determinant(), 1) && is_orthogonal(); +} + + +bool Basis::is_symmetric() const { + + if (Math::abs(elements[0][1] - elements[1][0]) > CMP_EPSILON) + return false; + if (Math::abs(elements[0][2] - elements[2][0]) > CMP_EPSILON) + return false; + if (Math::abs(elements[1][2] - elements[2][1]) > CMP_EPSILON) + return false; + + return true; +} + + +Basis Basis::diagonalize() { + + //NOTE: only implemented for symmetric matrices + //with the Jacobi iterative method method + + ERR_FAIL_COND_V(!is_symmetric(), Basis()); + + const int ite_max = 1024; + + real_t off_matrix_norm_2 = elements[0][1] * elements[0][1] + elements[0][2] * elements[0][2] + elements[1][2] * elements[1][2]; + + int ite = 0; + Basis acc_rot; + while (off_matrix_norm_2 > CMP_EPSILON2 && ite++ < ite_max ) { + real_t el01_2 = elements[0][1] * elements[0][1]; + real_t el02_2 = elements[0][2] * elements[0][2]; + real_t el12_2 = elements[1][2] * elements[1][2]; + // Find the pivot element + int i, j; + if (el01_2 > el02_2) { + if (el12_2 > el01_2) { + i = 1; + j = 2; + } else { + i = 0; + j = 1; + } + } else { + if (el12_2 > el02_2) { + i = 1; + j = 2; + } else { + i = 0; + j = 2; + } + } + + // Compute the rotation angle + real_t angle; + if (Math::abs(elements[j][j] - elements[i][i]) < CMP_EPSILON) { + angle = Math_PI / 4; + } else { + angle = 0.5 * Math::atan(2 * elements[i][j] / (elements[j][j] - elements[i][i])); + } - Matrix3 inv=*this; + // Compute the rotation matrix + Basis rot; + rot.elements[i][i] = rot.elements[j][j] = Math::cos(angle); + rot.elements[i][j] = - (rot.elements[j][i] = Math::sin(angle)); + + // Update the off matrix norm + off_matrix_norm_2 -= elements[i][j] * elements[i][j]; + + // Apply the rotation + *this = rot * *this * rot.transposed(); + acc_rot = rot * acc_rot; + } + + return acc_rot; +} + +Basis Basis::inverse() const { + + Basis inv=*this; inv.invert(); return inv; } -void Matrix3::transpose() { +void Basis::transpose() { SWAP(elements[0][1],elements[1][0]); SWAP(elements[0][2],elements[2][0]); SWAP(elements[1][2],elements[2][1]); } -Matrix3 Matrix3::transposed() const { +Basis Basis::transposed() const { - Matrix3 tr=*this; + Basis tr=*this; tr.transpose(); return tr; } -void Matrix3::scale(const Vector3& p_scale) { +// Multiplies the matrix from left by the scaling matrix: M -> S.M +// See the comment for Basis::rotated for further explanation. +void Basis::scale(const Vector3& p_scale) { elements[0][0]*=p_scale.x; - elements[1][0]*=p_scale.x; - elements[2][0]*=p_scale.x; - elements[0][1]*=p_scale.y; + elements[0][1]*=p_scale.x; + elements[0][2]*=p_scale.x; + elements[1][0]*=p_scale.y; elements[1][1]*=p_scale.y; - elements[2][1]*=p_scale.y; - elements[0][2]*=p_scale.z; - elements[1][2]*=p_scale.z; + elements[1][2]*=p_scale.y; + elements[2][0]*=p_scale.z; + elements[2][1]*=p_scale.z; elements[2][2]*=p_scale.z; } -Matrix3 Matrix3::scaled( const Vector3& p_scale ) const { +Basis Basis::scaled( const Vector3& p_scale ) const { - Matrix3 m = *this; + Basis m = *this; m.scale(p_scale); return m; } -Vector3 Matrix3::get_scale() const { - - return Vector3( +Vector3 Basis::get_scale() const { + // We are assuming M = R.S, and performing a polar decomposition to extract R and S. + // FIXME: We eventually need a proper polar decomposition. + // As a cheap workaround until then, to ensure that R is a proper rotation matrix with determinant +1 + // (such that it can be represented by a Quat or Euler angles), we absorb the sign flip into the scaling matrix. + // As such, it works in conjuction with get_rotation(). + real_t det_sign = determinant() > 0 ? 1 : -1; + return det_sign*Vector3( Vector3(elements[0][0],elements[1][0],elements[2][0]).length(), Vector3(elements[0][1],elements[1][1],elements[2][1]).length(), Vector3(elements[0][2],elements[1][2],elements[2][2]).length() ); } -void Matrix3::rotate(const Vector3& p_axis, real_t p_phi) { - *this = *this * Matrix3(p_axis, p_phi); +// Multiplies the matrix from left by the rotation matrix: M -> R.M +// Note that this does *not* rotate the matrix itself. +// +// The main use of Basis is as Transform.basis, which is used a the transformation matrix +// of 3D object. Rotate here refers to rotation of the object (which is R * (*this)), +// not the matrix itself (which is R * (*this) * R.transposed()). +Basis Basis::rotated(const Vector3& p_axis, real_t p_phi) const { + return Basis(p_axis, p_phi) * (*this); } -Matrix3 Matrix3::rotated(const Vector3& p_axis, real_t p_phi) const { +void Basis::rotate(const Vector3& p_axis, real_t p_phi) { + *this = rotated(p_axis, p_phi); +} - return *this * Matrix3(p_axis, p_phi); +Basis Basis::rotated(const Vector3& p_euler) const { + return Basis(p_euler) * (*this); +} +void Basis::rotate(const Vector3& p_euler) { + *this = rotated(p_euler); } -Vector3 Matrix3::get_euler() const { +Vector3 Basis::get_rotation() const { + // Assumes that the matrix can be decomposed into a proper rotation and scaling matrix as M = R.S, + // and returns the Euler angles corresponding to the rotation part, complementing get_scale(). + // See the comment in get_scale() for further information. + Basis m = orthonormalized(); + real_t det = m.determinant(); + if (det < 0) { + // Ensure that the determinant is 1, such that result is a proper rotation matrix which can be represented by Euler angles. + m.scale(Vector3(-1,-1,-1)); + } + + return m.get_euler(); +} +// get_euler returns a vector containing the Euler angles in the format +// (a1,a2,a3), where a3 is the angle of the first rotation, and a1 is the last +// (following the convention they are commonly defined in the literature). +// +// The current implementation uses XYZ convention (Z is the first rotation), +// so euler.z is the angle of the (first) rotation around Z axis and so on, +// +// And thus, assuming the matrix is a rotation matrix, this function returns +// the angles in the decomposition R = X(a1).Y(a2).Z(a3) where Z(a) rotates +// around the z-axis by a and so on. +Vector3 Basis::get_euler() const { + + // Euler angles in XYZ convention. + // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix + // // rot = cy*cz -cy*sz sy - // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx - // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy - - Matrix3 m = *this; - m.orthonormalize(); + // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx + // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy Vector3 euler; - euler.y = Math::asin(m[0][2]); + ERR_FAIL_COND_V(is_rotation() == false, euler); + + euler.y = Math::asin(elements[0][2]); if ( euler.y < Math_PI*0.5) { if ( euler.y > -Math_PI*0.5) { - euler.x = Math::atan2(-m[1][2],m[2][2]); - euler.z = Math::atan2(-m[0][1],m[0][0]); + euler.x = Math::atan2(-elements[1][2],elements[2][2]); + euler.z = Math::atan2(-elements[0][1],elements[0][0]); } else { - real_t r = Math::atan2(m[1][0],m[1][1]); + real_t r = Math::atan2(elements[1][0],elements[1][1]); euler.z = 0.0; euler.x = euler.z - r; } } else { - real_t r = Math::atan2(m[0][1],m[1][1]); + real_t r = Math::atan2(elements[0][1],elements[1][1]); euler.z = 0; euler.x = r - euler.z; } @@ -195,43 +326,59 @@ Vector3 Matrix3::get_euler() const { } -void Matrix3::set_euler(const Vector3& p_euler) { +// set_euler expects a vector containing the Euler angles in the format +// (c,b,a), where a is the angle of the first rotation, and c is the last. +// The current implementation uses XYZ convention (Z is the first rotation). +void Basis::set_euler(const Vector3& p_euler) { real_t c, s; c = Math::cos(p_euler.x); s = Math::sin(p_euler.x); - Matrix3 xmat(1.0,0.0,0.0,0.0,c,-s,0.0,s,c); + Basis xmat(1.0,0.0,0.0,0.0,c,-s,0.0,s,c); c = Math::cos(p_euler.y); s = Math::sin(p_euler.y); - Matrix3 ymat(c,0.0,s,0.0,1.0,0.0,-s,0.0,c); + Basis ymat(c,0.0,s,0.0,1.0,0.0,-s,0.0,c); c = Math::cos(p_euler.z); s = Math::sin(p_euler.z); - Matrix3 zmat(c,-s,0.0,s,c,0.0,0.0,0.0,1.0); + Basis zmat(c,-s,0.0,s,c,0.0,0.0,0.0,1.0); //optimizer will optimize away all this anyway *this = xmat*(ymat*zmat); } -bool Matrix3::operator==(const Matrix3& p_matrix) const { +bool Basis::isequal_approx(const Basis& a, const Basis& b) const { + + for (int i=0;i<3;i++) { + for (int j=0;j<3;j++) { + if (Math::isequal_approx(a.elements[i][j],b.elements[i][j]) == false) + return false; + } + } + + return true; +} + +bool Basis::operator==(const Basis& p_matrix) const { for (int i=0;i<3;i++) { for (int j=0;j<3;j++) { - if (elements[i][j]!=p_matrix.elements[i][j]) + if (elements[i][j] != p_matrix.elements[i][j]) return false; } } return true; } -bool Matrix3::operator!=(const Matrix3& p_matrix) const { + +bool Basis::operator!=(const Basis& p_matrix) const { return (!(*this==p_matrix)); } -Matrix3::operator String() const { +Basis::operator String() const { String mtx; for (int i=0;i<3;i++) { @@ -248,12 +395,10 @@ Matrix3::operator String() const { return mtx; } -Matrix3::operator Quat() const { +Basis::operator Quat() const { + ERR_FAIL_COND_V(is_rotation() == false, Quat()); - Matrix3 m=*this; - m.orthonormalize(); - - real_t trace = m.elements[0][0] + m.elements[1][1] + m.elements[2][2]; + real_t trace = elements[0][0] + elements[1][1] + elements[2][2]; real_t temp[4]; if (trace > 0.0) @@ -262,66 +407,66 @@ Matrix3::operator Quat() const { temp[3]=(s * 0.5); s = 0.5 / s; - temp[0]=((m.elements[2][1] - m.elements[1][2]) * s); - temp[1]=((m.elements[0][2] - m.elements[2][0]) * s); - temp[2]=((m.elements[1][0] - m.elements[0][1]) * s); + temp[0]=((elements[2][1] - elements[1][2]) * s); + temp[1]=((elements[0][2] - elements[2][0]) * s); + temp[2]=((elements[1][0] - elements[0][1]) * s); } else { - int i = m.elements[0][0] < m.elements[1][1] ? - (m.elements[1][1] < m.elements[2][2] ? 2 : 1) : - (m.elements[0][0] < m.elements[2][2] ? 2 : 0); + int i = elements[0][0] < elements[1][1] ? + (elements[1][1] < elements[2][2] ? 2 : 1) : + (elements[0][0] < elements[2][2] ? 2 : 0); int j = (i + 1) % 3; int k = (i + 2) % 3; - real_t s = Math::sqrt(m.elements[i][i] - m.elements[j][j] - m.elements[k][k] + 1.0); + real_t s = Math::sqrt(elements[i][i] - elements[j][j] - elements[k][k] + 1.0); temp[i] = s * 0.5; s = 0.5 / s; - temp[3] = (m.elements[k][j] - m.elements[j][k]) * s; - temp[j] = (m.elements[j][i] + m.elements[i][j]) * s; - temp[k] = (m.elements[k][i] + m.elements[i][k]) * s; + temp[3] = (elements[k][j] - elements[j][k]) * s; + temp[j] = (elements[j][i] + elements[i][j]) * s; + temp[k] = (elements[k][i] + elements[i][k]) * s; } return Quat(temp[0],temp[1],temp[2],temp[3]); } -static const Matrix3 _ortho_bases[24]={ - Matrix3(1, 0, 0, 0, 1, 0, 0, 0, 1), - Matrix3(0, -1, 0, 1, 0, 0, 0, 0, 1), - Matrix3(-1, 0, 0, 0, -1, 0, 0, 0, 1), - Matrix3(0, 1, 0, -1, 0, 0, 0, 0, 1), - Matrix3(1, 0, 0, 0, 0, -1, 0, 1, 0), - Matrix3(0, 0, 1, 1, 0, 0, 0, 1, 0), - Matrix3(-1, 0, 0, 0, 0, 1, 0, 1, 0), - Matrix3(0, 0, -1, -1, 0, 0, 0, 1, 0), - Matrix3(1, 0, 0, 0, -1, 0, 0, 0, -1), - Matrix3(0, 1, 0, 1, 0, 0, 0, 0, -1), - Matrix3(-1, 0, 0, 0, 1, 0, 0, 0, -1), - Matrix3(0, -1, 0, -1, 0, 0, 0, 0, -1), - Matrix3(1, 0, 0, 0, 0, 1, 0, -1, 0), - Matrix3(0, 0, -1, 1, 0, 0, 0, -1, 0), - Matrix3(-1, 0, 0, 0, 0, -1, 0, -1, 0), - Matrix3(0, 0, 1, -1, 0, 0, 0, -1, 0), - Matrix3(0, 0, 1, 0, 1, 0, -1, 0, 0), - Matrix3(0, -1, 0, 0, 0, 1, -1, 0, 0), - Matrix3(0, 0, -1, 0, -1, 0, -1, 0, 0), - Matrix3(0, 1, 0, 0, 0, -1, -1, 0, 0), - Matrix3(0, 0, 1, 0, -1, 0, 1, 0, 0), - Matrix3(0, 1, 0, 0, 0, 1, 1, 0, 0), - Matrix3(0, 0, -1, 0, 1, 0, 1, 0, 0), - Matrix3(0, -1, 0, 0, 0, -1, 1, 0, 0) +static const Basis _ortho_bases[24]={ + Basis(1, 0, 0, 0, 1, 0, 0, 0, 1), + Basis(0, -1, 0, 1, 0, 0, 0, 0, 1), + Basis(-1, 0, 0, 0, -1, 0, 0, 0, 1), + Basis(0, 1, 0, -1, 0, 0, 0, 0, 1), + Basis(1, 0, 0, 0, 0, -1, 0, 1, 0), + Basis(0, 0, 1, 1, 0, 0, 0, 1, 0), + Basis(-1, 0, 0, 0, 0, 1, 0, 1, 0), + Basis(0, 0, -1, -1, 0, 0, 0, 1, 0), + Basis(1, 0, 0, 0, -1, 0, 0, 0, -1), + Basis(0, 1, 0, 1, 0, 0, 0, 0, -1), + Basis(-1, 0, 0, 0, 1, 0, 0, 0, -1), + Basis(0, -1, 0, -1, 0, 0, 0, 0, -1), + Basis(1, 0, 0, 0, 0, 1, 0, -1, 0), + Basis(0, 0, -1, 1, 0, 0, 0, -1, 0), + Basis(-1, 0, 0, 0, 0, -1, 0, -1, 0), + Basis(0, 0, 1, -1, 0, 0, 0, -1, 0), + Basis(0, 0, 1, 0, 1, 0, -1, 0, 0), + Basis(0, -1, 0, 0, 0, 1, -1, 0, 0), + Basis(0, 0, -1, 0, -1, 0, -1, 0, 0), + Basis(0, 1, 0, 0, 0, -1, -1, 0, 0), + Basis(0, 0, 1, 0, -1, 0, 1, 0, 0), + Basis(0, 1, 0, 0, 0, 1, 1, 0, 0), + Basis(0, 0, -1, 0, 1, 0, 1, 0, 0), + Basis(0, -1, 0, 0, 0, -1, 1, 0, 0) }; -int Matrix3::get_orthogonal_index() const { +int Basis::get_orthogonal_index() const { //could be sped up if i come up with a way - Matrix3 orth=*this; + Basis orth=*this; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { - float v = orth[i][j]; + real_t v = orth[i][j]; if (v>0.5) v=1.0; else if (v<-0.5) @@ -344,7 +489,7 @@ int Matrix3::get_orthogonal_index() const { return 0; } -void Matrix3::set_orthogonal_index(int p_index){ +void Basis::set_orthogonal_index(int p_index){ //there only exist 24 orthogonal bases in r3 ERR_FAIL_INDEX(p_index,24); @@ -355,7 +500,8 @@ void Matrix3::set_orthogonal_index(int p_index){ } -void Matrix3::get_axis_and_angle(Vector3 &r_axis,real_t& r_angle) const { +void Basis::get_axis_and_angle(Vector3 &r_axis,real_t& r_angle) const { + ERR_FAIL_COND(is_rotation() == false); double angle,x,y,z; // variables for result @@ -423,26 +569,25 @@ void Matrix3::get_axis_and_angle(Vector3 &r_axis,real_t& r_angle) const { // as we have reached here there are no singularities so we can handle normally double s = Math::sqrt((elements[1][2] - elements[2][1])*(elements[1][2] - elements[2][1]) +(elements[2][0] - elements[0][2])*(elements[2][0] - elements[0][2]) - +(elements[0][1] - elements[1][0])*(elements[0][1] - elements[1][0])); // used to normalise - if (Math::abs(s) < 0.001) s=1; - // prevent divide by zero, should not happen if matrix is orthogonal and should be - // caught by singularity test above, but I've left it in just in case + +(elements[0][1] - elements[1][0])*(elements[0][1] - elements[1][0])); // s=|axis||sin(angle)|, used to normalise + angle = Math::acos(( elements[0][0] + elements[1][1] + elements[2][2] - 1)/2); - x = (elements[1][2] - elements[2][1])/s; - y = (elements[2][0] - elements[0][2])/s; - z = (elements[0][1] - elements[1][0])/s; + if (angle < 0) s = -s; + x = (elements[2][1] - elements[1][2])/s; + y = (elements[0][2] - elements[2][0])/s; + z = (elements[1][0] - elements[0][1])/s; r_axis=Vector3(x,y,z); r_angle=angle; } -Matrix3::Matrix3(const Vector3& p_euler) { +Basis::Basis(const Vector3& p_euler) { set_euler( p_euler ); } -Matrix3::Matrix3(const Quat& p_quat) { +Basis::Basis(const Quat& p_quat) { real_t d = p_quat.length_squared(); real_t s = 2.0 / d; @@ -456,7 +601,8 @@ Matrix3::Matrix3(const Quat& p_quat) { } -Matrix3::Matrix3(const Vector3& p_axis, real_t p_phi) { +Basis::Basis(const Vector3& p_axis, real_t p_phi) { + // Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle Vector3 axis_sq(p_axis.x*p_axis.x,p_axis.y*p_axis.y,p_axis.z*p_axis.z); @@ -464,15 +610,15 @@ Matrix3::Matrix3(const Vector3& p_axis, real_t p_phi) { real_t sine= Math::sin(p_phi); elements[0][0] = axis_sq.x + cosine * ( 1.0 - axis_sq.x ); - elements[0][1] = p_axis.x * p_axis.y * ( 1.0 - cosine ) + p_axis.z * sine; - elements[0][2] = p_axis.z * p_axis.x * ( 1.0 - cosine ) - p_axis.y * sine; + elements[0][1] = p_axis.x * p_axis.y * ( 1.0 - cosine ) - p_axis.z * sine; + elements[0][2] = p_axis.z * p_axis.x * ( 1.0 - cosine ) + p_axis.y * sine; - elements[1][0] = p_axis.x * p_axis.y * ( 1.0 - cosine ) - p_axis.z * sine; + elements[1][0] = p_axis.x * p_axis.y * ( 1.0 - cosine ) + p_axis.z * sine; elements[1][1] = axis_sq.y + cosine * ( 1.0 - axis_sq.y ); - elements[1][2] = p_axis.y * p_axis.z * ( 1.0 - cosine ) + p_axis.x * sine; + elements[1][2] = p_axis.y * p_axis.z * ( 1.0 - cosine ) - p_axis.x * sine; - elements[2][0] = p_axis.z * p_axis.x * ( 1.0 - cosine ) + p_axis.y * sine; - elements[2][1] = p_axis.y * p_axis.z * ( 1.0 - cosine ) - p_axis.x * sine; + elements[2][0] = p_axis.z * p_axis.x * ( 1.0 - cosine ) - p_axis.y * sine; + elements[2][1] = p_axis.y * p_axis.z * ( 1.0 - cosine ) + p_axis.x * sine; elements[2][2] = axis_sq.z + cosine * ( 1.0 - axis_sq.z ); } diff --git a/core/math/matrix3.h b/core/math/matrix3.h index e514f490f7..abce1ee45d 100644 --- a/core/math/matrix3.h +++ b/core/math/matrix3.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -26,16 +26,18 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + +#include "vector3.h" + #ifndef MATRIX3_H #define MATRIX3_H -#include "vector3.h" #include "quat.h" /** @author Juan Linietsky <reduzio@gmail.com> */ -class Matrix3 { +class Basis { public: Vector3 elements[3]; @@ -52,10 +54,10 @@ public: void invert(); void transpose(); - Matrix3 inverse() const; - Matrix3 transposed() const; + Basis inverse() const; + Basis transposed() const; - _FORCE_INLINE_ float determinant() const; + _FORCE_INLINE_ real_t determinant() const; void from_z(const Vector3& p_z); @@ -71,10 +73,14 @@ public: } void rotate(const Vector3& p_axis, real_t p_phi); - Matrix3 rotated(const Vector3& p_axis, real_t p_phi) const; + Basis rotated(const Vector3& p_axis, real_t p_phi) const; + + void rotate(const Vector3& p_euler); + Basis rotated(const Vector3& p_euler) const; + Vector3 get_rotation() const; void scale( const Vector3& p_scale ); - Matrix3 scaled( const Vector3& p_scale ) const; + Basis scaled( const Vector3& p_scale ) const; Vector3 get_scale() const; Vector3 get_euler() const; @@ -91,17 +97,28 @@ public: return elements[0][2] * v[0] + elements[1][2] * v[1] + elements[2][2] * v[2]; } - bool operator==(const Matrix3& p_matrix) const; - bool operator!=(const Matrix3& p_matrix) const; + bool isequal_approx(const Basis& a, const Basis& b) const; + + bool operator==(const Basis& p_matrix) const; + bool operator!=(const Basis& p_matrix) const; _FORCE_INLINE_ Vector3 xform(const Vector3& p_vector) const; _FORCE_INLINE_ Vector3 xform_inv(const Vector3& p_vector) const; - _FORCE_INLINE_ void operator*=(const Matrix3& p_matrix); - _FORCE_INLINE_ Matrix3 operator*(const Matrix3& p_matrix) const; + _FORCE_INLINE_ void operator*=(const Basis& p_matrix); + _FORCE_INLINE_ Basis operator*(const Basis& p_matrix) const; + _FORCE_INLINE_ void operator+=(const Basis& p_matrix); + _FORCE_INLINE_ Basis operator+(const Basis& p_matrix) const; + _FORCE_INLINE_ void operator-=(const Basis& p_matrix); + _FORCE_INLINE_ Basis operator-(const Basis& p_matrix) const; + _FORCE_INLINE_ void operator*=(real_t p_val); + _FORCE_INLINE_ Basis operator*(real_t p_val) const; int get_orthogonal_index() const; void set_orthogonal_index(int p_index); + bool is_orthogonal() const; + bool is_rotation() const; + operator String() const; void get_axis_and_angle(Vector3 &r_axis,real_t& r_angle) const; @@ -130,6 +147,10 @@ public: return Vector3(elements[i][0],elements[i][1],elements[i][2]); } + _FORCE_INLINE_ Vector3 get_main_diagonal() const { + return Vector3(elements[0][0],elements[1][1],elements[2][2]); + } + _FORCE_INLINE_ void set_row(int i, const Vector3& p_row) { elements[i][0]=p_row.x; elements[i][1]=p_row.y; @@ -142,9 +163,9 @@ public: elements[2].zero(); } - _FORCE_INLINE_ Matrix3 transpose_xform(const Matrix3& m) const + _FORCE_INLINE_ Basis transpose_xform(const Basis& m) const { - return Matrix3( + return Basis( elements[0].x * m[0].x + elements[1].x * m[1].x + elements[2].x * m[2].x, elements[0].x * m[0].y + elements[1].x * m[1].y + elements[2].x * m[2].y, elements[0].x * m[0].z + elements[1].x * m[1].z + elements[2].x * m[2].z, @@ -155,21 +176,31 @@ public: elements[0].z * m[0].y + elements[1].z * m[1].y + elements[2].z * m[2].y, elements[0].z * m[0].z + elements[1].z * m[1].z + elements[2].z * m[2].z); } - Matrix3(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) { + Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) { set(xx, xy, xz, yx, yy, yz, zx, zy, zz); } void orthonormalize(); - Matrix3 orthonormalized() const; + Basis orthonormalized() const; + + bool is_symmetric() const; + Basis diagonalize(); operator Quat() const; - Matrix3(const Quat& p_quat); // euler - Matrix3(const Vector3& p_euler); // euler - Matrix3(const Vector3& p_axis, real_t p_phi); + Basis(const Quat& p_quat); // euler + Basis(const Vector3& p_euler); // euler + Basis(const Vector3& p_axis, real_t p_phi); - _FORCE_INLINE_ Matrix3() { + _FORCE_INLINE_ Basis(const Vector3& row0, const Vector3& row1, const Vector3& row2) + { + elements[0]=row0; + elements[1]=row1; + elements[2]=row2; + } + + _FORCE_INLINE_ Basis() { elements[0][0]=1; elements[0][1]=0; @@ -185,7 +216,7 @@ public: }; -_FORCE_INLINE_ void Matrix3::operator*=(const Matrix3& p_matrix) { +_FORCE_INLINE_ void Basis::operator*=(const Basis& p_matrix) { set( p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]), @@ -194,16 +225,59 @@ _FORCE_INLINE_ void Matrix3::operator*=(const Matrix3& p_matrix) { } -_FORCE_INLINE_ Matrix3 Matrix3::operator*(const Matrix3& p_matrix) const { +_FORCE_INLINE_ Basis Basis::operator*(const Basis& p_matrix) const { - return Matrix3( + return Basis( p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]), p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]), p_matrix.tdotx(elements[2]), p_matrix.tdoty(elements[2]), p_matrix.tdotz(elements[2]) ); } -Vector3 Matrix3::xform(const Vector3& p_vector) const { + +_FORCE_INLINE_ void Basis::operator+=(const Basis& p_matrix) { + + elements[0] += p_matrix.elements[0]; + elements[1] += p_matrix.elements[1]; + elements[2] += p_matrix.elements[2]; +} + +_FORCE_INLINE_ Basis Basis::operator+(const Basis& p_matrix) const { + + Basis ret(*this); + ret += p_matrix; + return ret; +} + +_FORCE_INLINE_ void Basis::operator-=(const Basis& p_matrix) { + + elements[0] -= p_matrix.elements[0]; + elements[1] -= p_matrix.elements[1]; + elements[2] -= p_matrix.elements[2]; +} + +_FORCE_INLINE_ Basis Basis::operator-(const Basis& p_matrix) const { + + Basis ret(*this); + ret -= p_matrix; + return ret; +} + +_FORCE_INLINE_ void Basis::operator*=(real_t p_val) { + + elements[0]*=p_val; + elements[1]*=p_val; + elements[2]*=p_val; +} + +_FORCE_INLINE_ Basis Basis::operator*(real_t p_val) const { + + Basis ret(*this); + ret *= p_val; + return ret; +} + +Vector3 Basis::xform(const Vector3& p_vector) const { return Vector3( elements[0].dot(p_vector), @@ -212,7 +286,7 @@ Vector3 Matrix3::xform(const Vector3& p_vector) const { ); } -Vector3 Matrix3::xform_inv(const Vector3& p_vector) const { +Vector3 Basis::xform_inv(const Vector3& p_vector) const { return Vector3( (elements[0][0]*p_vector.x ) + ( elements[1][0]*p_vector.y ) + ( elements[2][0]*p_vector.z ), @@ -221,7 +295,7 @@ Vector3 Matrix3::xform_inv(const Vector3& p_vector) const { ); } -float Matrix3::determinant() const { +real_t Basis::determinant() const { return elements[0][0]*(elements[1][1]*elements[2][2] - elements[2][1]*elements[1][2]) - elements[1][0]*(elements[0][1]*elements[2][2] - elements[2][1]*elements[0][2]) + diff --git a/core/math/octree.h b/core/math/octree.h index 6080b21680..483ba1d510 100644 --- a/core/math/octree.h +++ b/core/math/octree.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -107,7 +107,7 @@ private: struct Octant { // cached for FAST plane check - AABB aabb; + Rect3 aabb; uint64_t last_pass; Octant *parent; @@ -130,8 +130,10 @@ private: ~Octant() { - //for (int i=0;i<8;i++) - // memdelete_notnull(children[i]); + /* + for (int i=0;i<8;i++) + memdelete_notnull(children[i]); + */ } }; @@ -152,8 +154,8 @@ private: OctreeElementID _id; Octant *common_parent; - AABB aabb; - AABB container_aabb; + Rect3 aabb; + Rect3 container_aabb; List<PairData*,AL> pair_list; @@ -250,8 +252,10 @@ private: E->get().eA=p_A->pair_list.push_back(&E->get()); E->get().eB=p_B->pair_list.push_back(&E->get()); -// if (pair_callback) -// pair_callback(pair_callback_userdata,p_A->userdata,p_B->userdata); + /* + if (pair_callback) + pair_callback(pair_callback_userdata,p_A->userdata,p_B->userdata); + */ } else { E->get().refcount++; @@ -338,7 +342,7 @@ private: void _insert_element(Element *p_element,Octant *p_octant); - void _ensure_valid_root(const AABB& p_aabb); + void _ensure_valid_root(const Rect3& p_aabb); bool _remove_element_from_octant(Element *p_element,Octant *p_octant,Octant *p_limit=NULL); void _remove_element(Element *p_element); void _pair_element(Element *p_element,Octant *p_octant); @@ -356,7 +360,7 @@ private: }; void _cull_convex(Octant *p_octant,_CullConvexData *p_cull); - void _cull_AABB(Octant *p_octant,const AABB& p_aabb, T** p_result_array,int *p_result_idx,int p_result_max,int *p_subindex_array,uint32_t p_mask); + void _cull_AABB(Octant *p_octant,const Rect3& p_aabb, T** p_result_array,int *p_result_idx,int p_result_max,int *p_subindex_array,uint32_t p_mask); void _cull_segment(Octant *p_octant,const Vector3& p_from, const Vector3& p_to,T** p_result_array,int *p_result_idx,int p_result_max,int *p_subindex_array,uint32_t p_mask); void _cull_point(Octant *p_octant,const Vector3& p_point,T** p_result_array,int *p_result_idx,int p_result_max,int *p_subindex_array,uint32_t p_mask); @@ -375,8 +379,8 @@ private: } public: - OctreeElementID create(T* p_userdata, const AABB& p_aabb=AABB(), int p_subindex=0, bool p_pairable=false,uint32_t p_pairable_type=0,uint32_t pairable_mask=1); - void move(OctreeElementID p_id, const AABB& p_aabb); + OctreeElementID create(T* p_userdata, const Rect3& p_aabb=Rect3(), int p_subindex=0, bool p_pairable=false,uint32_t p_pairable_type=0,uint32_t pairable_mask=1); + void move(OctreeElementID p_id, const Rect3& p_aabb); void set_pairable(OctreeElementID p_id,bool p_pairable=false,uint32_t p_pairable_type=0,uint32_t pairable_mask=1); void erase(OctreeElementID p_id); @@ -385,7 +389,7 @@ public: int get_subindex(OctreeElementID p_id) const; int cull_convex(const Vector<Plane>& p_convex,T** p_result_array,int p_result_max,uint32_t p_mask=0xFFFFFFFF); - int cull_AABB(const AABB& p_aabb,T** p_result_array,int p_result_max,int *p_subindex_array=NULL,uint32_t p_mask=0xFFFFFFFF); + int cull_AABB(const Rect3& p_aabb,T** p_result_array,int p_result_max,int *p_subindex_array=NULL,uint32_t p_mask=0xFFFFFFFF); int cull_segment(const Vector3& p_from, const Vector3& p_to,T** p_result_array,int p_result_max,int *p_subindex_array=NULL,uint32_t p_mask=0xFFFFFFFF); int cull_point(const Vector3& p_point,T** p_result_array,int p_result_max,int *p_subindex_array=NULL,uint32_t p_mask=0xFFFFFFFF); @@ -487,7 +491,7 @@ void Octree<T,use_pairs,AL>::_insert_element(Element *p_element,Octant *p_octant } else { /* check againt AABB where child should be */ - AABB aabb=p_octant->aabb; + Rect3 aabb=p_octant->aabb; aabb.size*=0.5; if (i&1) @@ -549,12 +553,12 @@ void Octree<T,use_pairs,AL>::_insert_element(Element *p_element,Octant *p_octant template<class T,bool use_pairs,class AL> -void Octree<T,use_pairs,AL>::_ensure_valid_root(const AABB& p_aabb) { +void Octree<T,use_pairs,AL>::_ensure_valid_root(const Rect3& p_aabb) { if (!root) { // octre is empty - AABB base( Vector3(), Vector3(1.0,1.0,1.0) * unit_size); + Rect3 base( Vector3(), Vector3(1.0,1.0,1.0) * unit_size); while ( !base.encloses(p_aabb) ) { @@ -578,7 +582,7 @@ void Octree<T,use_pairs,AL>::_ensure_valid_root(const AABB& p_aabb) { } else { - AABB base=root->aabb; + Rect3 base=root->aabb; while( !base.encloses( p_aabb ) ) { @@ -814,7 +818,7 @@ void Octree<T,use_pairs,AL>::_remove_element(Element *p_element) { } template<class T,bool use_pairs,class AL> -OctreeElementID Octree<T,use_pairs,AL>::create(T* p_userdata, const AABB& p_aabb, int p_subindex,bool p_pairable,uint32_t p_pairable_type,uint32_t p_pairable_mask) { +OctreeElementID Octree<T,use_pairs,AL>::create(T* p_userdata, const Rect3& p_aabb, int p_subindex,bool p_pairable,uint32_t p_pairable_type,uint32_t p_pairable_mask) { // check for AABB validity #ifdef DEBUG_ENABLED @@ -857,7 +861,7 @@ OctreeElementID Octree<T,use_pairs,AL>::create(T* p_userdata, const AABB& p_aabb template<class T,bool use_pairs,class AL> -void Octree<T,use_pairs,AL>::move(OctreeElementID p_id, const AABB& p_aabb) { +void Octree<T,use_pairs,AL>::move(OctreeElementID p_id, const Rect3& p_aabb) { #ifdef DEBUG_ENABLED // check for AABB validity @@ -906,7 +910,7 @@ void Octree<T,use_pairs,AL>::move(OctreeElementID p_id, const AABB& p_aabb) { if (old_has_surf) { _remove_element(&e); // removing e.common_parent=NULL; - e.aabb=AABB(); + e.aabb=Rect3(); _optimize(); } else { _ensure_valid_root(p_aabb); // inserting @@ -935,7 +939,7 @@ void Octree<T,use_pairs,AL>::move(OctreeElementID p_id, const AABB& p_aabb) { return; } - AABB combined=e.aabb; + Rect3 combined=e.aabb; combined.merge_with(p_aabb); _ensure_valid_root(combined); @@ -970,8 +974,10 @@ void Octree<T,use_pairs,AL>::move(OctreeElementID p_id, const AABB& p_aabb) { Octant *o=E->get().octant; typename List<typename Element::OctantOwner,AL>::Element *N=E->next(); -// if (!use_pairs) -// o->elements.erase( E->get().E ); + /* + if (!use_pairs) + o->elements.erase( E->get().E ); + */ if (use_pairs && e.pairable) o->pairable_elements.erase( E->get().E ); @@ -1129,7 +1135,7 @@ void Octree<T,use_pairs,AL>::_cull_convex(Octant *p_octant,_CullConvexData *p_cu template<class T,bool use_pairs,class AL> -void Octree<T,use_pairs,AL>::_cull_AABB(Octant *p_octant,const AABB& p_aabb, T** p_result_array,int *p_result_idx,int p_result_max,int *p_subindex_array,uint32_t p_mask) { +void Octree<T,use_pairs,AL>::_cull_AABB(Octant *p_octant,const Rect3& p_aabb, T** p_result_array,int *p_result_idx,int p_result_max,int *p_subindex_array,uint32_t p_mask) { if (*p_result_idx==p_result_max) return; //pointless @@ -1376,7 +1382,7 @@ int Octree<T,use_pairs,AL>::cull_convex(const Vector<Plane>& p_convex,T** p_resu template<class T,bool use_pairs,class AL> -int Octree<T,use_pairs,AL>::cull_AABB(const AABB& p_aabb,T** p_result_array,int p_result_max,int *p_subindex_array,uint32_t p_mask) { +int Octree<T,use_pairs,AL>::cull_AABB(const Rect3& p_aabb,T** p_result_array,int p_result_max,int *p_subindex_array,uint32_t p_mask) { if (!root) diff --git a/core/math/plane.cpp b/core/math/plane.cpp index b29350fe3c..2a97932049 100644 --- a/core/math/plane.cpp +++ b/core/math/plane.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/plane.h b/core/math/plane.h index 81a968682e..f746ea2067 100644 --- a/core/math/plane.h +++ b/core/math/plane.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/quat.cpp b/core/math/quat.cpp index 73124e5e8e..055e2b7c35 100644 --- a/core/math/quat.cpp +++ b/core/math/quat.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,22 +27,40 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "quat.h" +#include "matrix3.h" #include "print_string.h" +// set_euler expects a vector containing the Euler angles in the format +// (c,b,a), where a is the angle of the first rotation, and c is the last. +// The current implementation uses XYZ convention (Z is the first rotation). void Quat::set_euler(const Vector3& p_euler) { - real_t half_yaw = p_euler.x * 0.5; - real_t half_pitch = p_euler.y * 0.5; - real_t half_roll = p_euler.z * 0.5; - real_t cos_yaw = Math::cos(half_yaw); - real_t sin_yaw = Math::sin(half_yaw); - real_t cos_pitch = Math::cos(half_pitch); - real_t sin_pitch = Math::sin(half_pitch); - real_t cos_roll = Math::cos(half_roll); - real_t sin_roll = Math::sin(half_roll); - set(cos_roll * sin_pitch * cos_yaw+sin_roll * cos_pitch * sin_yaw, - cos_roll * cos_pitch * sin_yaw - sin_roll * sin_pitch * cos_yaw, - sin_roll * cos_pitch * cos_yaw - cos_roll * sin_pitch * sin_yaw, - cos_roll * cos_pitch * cos_yaw+sin_roll * sin_pitch * sin_yaw); + real_t half_a1 = p_euler.x * 0.5; + real_t half_a2 = p_euler.y * 0.5; + real_t half_a3 = p_euler.z * 0.5; + + // R = X(a1).Y(a2).Z(a3) convention for Euler angles. + // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-2) + // a3 is the angle of the first rotation, following the notation in this reference. + + real_t cos_a1 = Math::cos(half_a1); + real_t sin_a1 = Math::sin(half_a1); + real_t cos_a2 = Math::cos(half_a2); + real_t sin_a2 = Math::sin(half_a2); + real_t cos_a3 = Math::cos(half_a3); + real_t sin_a3 = Math::sin(half_a3); + + set(sin_a1*cos_a2*cos_a3 + sin_a2*sin_a3*cos_a1, + -sin_a1*sin_a3*cos_a2 + sin_a2*cos_a1*cos_a3, + sin_a1*sin_a2*cos_a3 + sin_a3*cos_a1*cos_a2, + -sin_a1*sin_a2*sin_a3 + cos_a1*cos_a2*cos_a3); +} + +// get_euler returns a vector containing the Euler angles in the format +// (a1,a2,a3), where a3 is the angle of the first rotation, and a1 is the last. +// The current implementation uses XYZ convention (Z is the first rotation). +Vector3 Quat::get_euler() const { + Basis m(*this); + return m.get_euler(); } void Quat::operator*=(const Quat& q) { @@ -126,26 +144,25 @@ Quat Quat::slerp(const Quat& q, const real_t& t) const { } #else - real_t to1[4]; + Quat to1; real_t omega, cosom, sinom, scale0, scale1; // calc cosine - cosom = x * q.x + y * q.y + z * q.z - + w * q.w; - + cosom = dot(q); // adjust signs (if necessary) if ( cosom <0.0 ) { - cosom = -cosom; to1[0] = - q.x; - to1[1] = - q.y; - to1[2] = - q.z; - to1[3] = - q.w; + cosom = -cosom; + to1.x = - q.x; + to1.y = - q.y; + to1.z = - q.z; + to1.w = - q.w; } else { - to1[0] = q.x; - to1[1] = q.y; - to1[2] = q.z; - to1[3] = q.w; + to1.x = q.x; + to1.y = q.y; + to1.z = q.z; + to1.w = q.w; } @@ -165,10 +182,10 @@ Quat Quat::slerp(const Quat& q, const real_t& t) const { } // calculate final values return Quat( - scale0 * x + scale1 * to1[0], - scale0 * y + scale1 * to1[1], - scale0 * z + scale1 * to1[2], - scale0 * w + scale1 * to1[3] + scale0 * x + scale1 * to1.x, + scale0 * y + scale1 * to1.y, + scale0 * z + scale1 * to1.z, + scale0 * w + scale1 * to1.w ); #endif } @@ -186,10 +203,10 @@ Quat Quat::slerpni(const Quat& q, const real_t& t) const { newFactor = Math::sin(t * theta) * sinT, invFactor = Math::sin((1.0f - t) * theta) * sinT; - return Quat( invFactor * from.x + newFactor * q.x, - invFactor * from.y + newFactor * q.y, - invFactor * from.z + newFactor * q.z, - invFactor * from.w + newFactor * q.w ); + return Quat(invFactor * from.x + newFactor * q.x, + invFactor * from.y + newFactor * q.y, + invFactor * from.z + newFactor * q.z, + invFactor * from.w + newFactor * q.w); #if 0 real_t to1[4]; @@ -203,7 +220,7 @@ Quat Quat::slerpni(const Quat& q, const real_t& t) const { // adjust signs (if necessary) if ( cosom <0.0 && false) { - cosom = -cosom; to1[0] = - q.x; + cosom = -cosom;to1[0] = - q.x; to1[1] = - q.y; to1[2] = - q.z; to1[3] = - q.w; @@ -260,8 +277,10 @@ Quat::Quat(const Vector3& axis, const real_t& angle) { if (d==0) set(0,0,0,0); else { - real_t s = Math::sin(-angle * 0.5) / d; + real_t sin_angle = Math::sin(angle * 0.5); + real_t cos_angle = Math::cos(angle * 0.5); + real_t s = sin_angle / d; set(axis.x * s, axis.y * s, axis.z * s, - Math::cos(-angle * 0.5)); + cos_angle); } } diff --git a/core/math/quat.h b/core/math/quat.h index 0d206bb3b7..43c2cab9e6 100644 --- a/core/math/quat.h +++ b/core/math/quat.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -26,13 +26,15 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ + +#include "vector3.h" + #ifndef QUAT_H #define QUAT_H #include "math_defs.h" #include "math_funcs.h" #include "ustring.h" -#include "vector3.h" /** @author Juan Linietsky <reduzio@gmail.com> @@ -49,15 +51,16 @@ public: Quat inverse() const; _FORCE_INLINE_ real_t dot(const Quat& q) const; void set_euler(const Vector3& p_euler); + Vector3 get_euler() const; Quat slerp(const Quat& q, const real_t& t) const; Quat slerpni(const Quat& q, const real_t& t) const; Quat cubic_slerp(const Quat& q, const Quat& prep, const Quat& postq,const real_t& t) const; _FORCE_INLINE_ void get_axis_and_angle(Vector3& r_axis, real_t &r_angle) const { r_angle = 2 * Math::acos(w); - r_axis.x = -x / Math::sqrt(1-w*w); - r_axis.y = -y / Math::sqrt(1-w*w); - r_axis.z = -z / Math::sqrt(1-w*w); + r_axis.x = x / Math::sqrt(1-w*w); + r_axis.y = y / Math::sqrt(1-w*w); + r_axis.z = z / Math::sqrt(1-w*w); } void operator*=(const Quat& q); @@ -183,12 +186,10 @@ Quat Quat::operator/(const real_t& s) const { bool Quat::operator==(const Quat& p_quat) const { - return x==p_quat.x && y==p_quat.y && z==p_quat.z && w==p_quat.w; } bool Quat::operator!=(const Quat& p_quat) const { - return x!=p_quat.x || y!=p_quat.y || z!=p_quat.z || w!=p_quat.w; } diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp index 956824d3d0..756e48d0b4 100644 --- a/core/math/quick_hull.cpp +++ b/core/math/quick_hull.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,7 +38,7 @@ Error QuickHull::build(const Vector<Vector3>& p_points, Geometry::MeshData &r_me /* CREATE AABB VOLUME */ - AABB aabb; + Rect3 aabb; for(int i=0;i<p_points.size();i++) { if (i==0) { @@ -483,7 +483,7 @@ Error QuickHull::build(const Vector<Vector3>& p_points, Geometry::MeshData &r_me //fill mesh r_mesh.faces.clear(); r_mesh.faces.resize(ret_faces.size()); -// print_line("FACECOUNT: "+itos(r_mesh.faces.size())); + //print_line("FACECOUNT: "+itos(r_mesh.faces.size())); int idx=0; for (List<Geometry::MeshData::Face>::Element *E=ret_faces.front();E;E=E->next()) { diff --git a/core/math/quick_hull.h b/core/math/quick_hull.h index 8c009b907d..04d25fef18 100644 --- a/core/math/quick_hull.h +++ b/core/math/quick_hull.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/transform.cpp b/core/math/transform.cpp index 22eb6c4fdd..6d9324c176 100644 --- a/core/math/transform.cpp +++ b/core/math/transform.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -54,7 +54,8 @@ void Transform::invert() { } Transform Transform::inverse() const { - + // FIXME: this function assumes the basis is a rotation matrix, with no scaling. + // Transform::affine_inverse can handle matrices with scaling, so GDScript should eventually use that. Transform ret=*this; ret.invert(); return ret; @@ -63,12 +64,12 @@ Transform Transform::inverse() const { void Transform::rotate(const Vector3& p_axis,real_t p_phi) { - *this = *this * Transform( Matrix3( p_axis, p_phi ), Vector3() ); + *this = rotated(p_axis, p_phi); } Transform Transform::rotated(const Vector3& p_axis,real_t p_phi) const{ - return *this * Transform( Matrix3( p_axis, p_phi ), Vector3() ); + return Transform(Basis( p_axis, p_phi ), Vector3()) * (*this); } void Transform::rotate_basis(const Vector3& p_axis,real_t p_phi) { @@ -113,7 +114,7 @@ void Transform::set_look_at( const Vector3& p_eye, const Vector3& p_target, cons } -Transform Transform::interpolate_with(const Transform& p_transform, float p_c) const { +Transform Transform::interpolate_with(const Transform& p_transform, real_t p_c) const { /* not sure if very "efficient" but good enough? */ @@ -209,7 +210,7 @@ Transform::operator String() const { } -Transform::Transform(const Matrix3& p_basis, const Vector3& p_origin) { +Transform::Transform(const Basis& p_basis, const Vector3& p_origin) { basis=p_basis; origin=p_origin; diff --git a/core/math/transform.h b/core/math/transform.h index f948a4c919..d65e87cc6a 100644 --- a/core/math/transform.h +++ b/core/math/transform.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,7 +38,7 @@ class Transform { public: - Matrix3 basis; + Basis basis; Vector3 origin; void invert(); @@ -62,8 +62,8 @@ public: void translate( const Vector3& p_translation ); Transform translated( const Vector3& p_translation ) const; - const Matrix3& get_basis() const { return basis; } - void set_basis(const Matrix3& p_basis) { basis=p_basis; } + const Basis& get_basis() const { return basis; } + void set_basis(const Basis& p_basis) { basis=p_basis; } const Vector3& get_origin() const { return origin; } void set_origin(const Vector3& p_origin) { origin=p_origin; } @@ -80,13 +80,13 @@ public: _FORCE_INLINE_ Plane xform(const Plane& p_plane) const; _FORCE_INLINE_ Plane xform_inv(const Plane& p_plane) const; - _FORCE_INLINE_ AABB xform(const AABB& p_aabb) const; - _FORCE_INLINE_ AABB xform_inv(const AABB& p_aabb) const; + _FORCE_INLINE_ Rect3 xform(const Rect3& p_aabb) const; + _FORCE_INLINE_ Rect3 xform_inv(const Rect3& p_aabb) const; void operator*=(const Transform& p_transform); Transform operator*(const Transform& p_transform) const; - Transform interpolate_with(const Transform& p_transform, float p_c) const; + Transform interpolate_with(const Transform& p_transform, real_t p_c) const; _FORCE_INLINE_ Transform inverse_xform(const Transform& t) const { @@ -113,7 +113,7 @@ public: operator String() const; - Transform(const Matrix3& p_basis, const Vector3& p_origin=Vector3()); + Transform(const Basis& p_basis, const Vector3& p_origin=Vector3()); Transform() {} }; @@ -168,7 +168,7 @@ _FORCE_INLINE_ Plane Transform::xform_inv(const Plane& p_plane) const { } -_FORCE_INLINE_ AABB Transform::xform(const AABB& p_aabb) const { +_FORCE_INLINE_ Rect3 Transform::xform(const Rect3& p_aabb) const { /* define vertices */ #if 1 Vector3 x=basis.get_axis(0)*p_aabb.size.x; @@ -176,7 +176,7 @@ _FORCE_INLINE_ AABB Transform::xform(const AABB& p_aabb) const { Vector3 z=basis.get_axis(2)*p_aabb.size.z; Vector3 pos = xform( p_aabb.pos ); //could be even further optimized - AABB new_aabb; + Rect3 new_aabb; new_aabb.pos=pos; new_aabb.expand_to( pos+x ); new_aabb.expand_to( pos+y ); @@ -214,7 +214,7 @@ _FORCE_INLINE_ AABB Transform::xform(const AABB& p_aabb) const { #endif } -_FORCE_INLINE_ AABB Transform::xform_inv(const AABB& p_aabb) const { +_FORCE_INLINE_ Rect3 Transform::xform_inv(const Rect3& p_aabb) const { /* define vertices */ Vector3 vertices[8]={ @@ -229,7 +229,7 @@ _FORCE_INLINE_ AABB Transform::xform_inv(const AABB& p_aabb) const { }; - AABB ret; + Rect3 ret; ret.pos=xform_inv(vertices[0]); diff --git a/core/math/triangle_mesh.cpp b/core/math/triangle_mesh.cpp index 7aea32a8a0..74c4656771 100644 --- a/core/math/triangle_mesh.cpp +++ b/core/math/triangle_mesh.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -48,7 +48,7 @@ int TriangleMesh::_create_bvh(BVH*p_bvh,BVH** p_bb,int p_from,int p_size,int p_d } - AABB aabb; + Rect3 aabb; aabb=p_bb[p_from]->aabb; for(int i=1;i<p_size;i++) { @@ -94,7 +94,7 @@ int TriangleMesh::_create_bvh(BVH*p_bvh,BVH** p_bb,int p_from,int p_size,int p_d } -void TriangleMesh::create(const DVector<Vector3>& p_faces) { +void TriangleMesh::create(const PoolVector<Vector3>& p_faces) { valid=false; @@ -104,7 +104,7 @@ void TriangleMesh::create(const DVector<Vector3>& p_faces) { triangles.resize(fc); bvh.resize(fc*3); //will never be larger than this (todo make better) - DVector<BVH>::Write bw = bvh.write(); + PoolVector<BVH>::Write bw = bvh.write(); { @@ -112,8 +112,8 @@ void TriangleMesh::create(const DVector<Vector3>& p_faces) { //except for the Set for repeated triangles, everything //goes in-place. - DVector<Vector3>::Read r = p_faces.read(); - DVector<Triangle>::Write w = triangles.write(); + PoolVector<Vector3>::Read r = p_faces.read(); + PoolVector<Triangle>::Write w = triangles.write(); Map<Vector3,int> db; for(int i=0;i<fc;i++) { @@ -149,16 +149,16 @@ void TriangleMesh::create(const DVector<Vector3>& p_faces) { } vertices.resize(db.size()); - DVector<Vector3>::Write vw = vertices.write(); + PoolVector<Vector3>::Write vw = vertices.write(); for (Map<Vector3,int>::Element *E=db.front();E;E=E->next()) { vw[E->get()]=E->key(); } } - DVector<BVH*> bwptrs; + PoolVector<BVH*> bwptrs; bwptrs.resize(fc); - DVector<BVH*>::Write bwp = bwptrs.write(); + PoolVector<BVH*>::Write bwp = bwptrs.write(); for(int i=0;i<fc;i++) { bwp[i]=&bw[i]; @@ -168,7 +168,7 @@ void TriangleMesh::create(const DVector<Vector3>& p_faces) { int max_alloc=fc; int max=_create_bvh(bw.ptr(),bwp.ptr(),0,fc,1,max_depth,max_alloc); - bw=DVector<BVH>::Write(); //clearup + bw=PoolVector<BVH>::Write(); //clearup bvh.resize(max_alloc); //resize back valid=true; @@ -176,7 +176,7 @@ void TriangleMesh::create(const DVector<Vector3>& p_faces) { } -Vector3 TriangleMesh::get_area_normal(const AABB& p_aabb) const { +Vector3 TriangleMesh::get_area_normal(const Rect3& p_aabb) const { uint32_t* stack = (uint32_t*)alloca(sizeof(int)*max_depth); @@ -197,9 +197,9 @@ Vector3 TriangleMesh::get_area_normal(const AABB& p_aabb) const { int level=0; - DVector<Triangle>::Read trianglesr = triangles.read(); - DVector<Vector3>::Read verticesr=vertices.read(); - DVector<BVH>::Read bvhr=bvh.read(); + PoolVector<Triangle>::Read trianglesr = triangles.read(); + PoolVector<Vector3>::Read verticesr=vertices.read(); + PoolVector<BVH>::Read bvhr=bvh.read(); const Triangle *triangleptr=trianglesr.ptr(); int pos=bvh.size()-1; @@ -299,9 +299,9 @@ bool TriangleMesh::intersect_segment(const Vector3& p_begin,const Vector3& p_end int level=0; - DVector<Triangle>::Read trianglesr = triangles.read(); - DVector<Vector3>::Read verticesr=vertices.read(); - DVector<BVH>::Read bvhr=bvh.read(); + PoolVector<Triangle>::Read trianglesr = triangles.read(); + PoolVector<Vector3>::Read verticesr=vertices.read(); + PoolVector<BVH>::Read bvhr=bvh.read(); const Triangle *triangleptr=trianglesr.ptr(); const Vector3 *vertexptr=verticesr.ptr(); @@ -320,7 +320,7 @@ bool TriangleMesh::intersect_segment(const Vector3& p_begin,const Vector3& p_end bool valid = b.aabb.intersects_segment(p_begin,p_end); -// bool valid = b.aabb.intersects(ray_aabb); + //bool valid = b.aabb.intersects(ray_aabb); if (!valid) { @@ -422,9 +422,9 @@ bool TriangleMesh::intersect_ray(const Vector3& p_begin,const Vector3& p_dir,Vec int level=0; - DVector<Triangle>::Read trianglesr = triangles.read(); - DVector<Vector3>::Read verticesr=vertices.read(); - DVector<BVH>::Read bvhr=bvh.read(); + PoolVector<Triangle>::Read trianglesr = triangles.read(); + PoolVector<Vector3>::Read verticesr=vertices.read(); + PoolVector<BVH>::Read bvhr=bvh.read(); const Triangle *triangleptr=trianglesr.ptr(); const Vector3 *vertexptr=verticesr.ptr(); @@ -524,18 +524,18 @@ bool TriangleMesh::is_valid() const { return valid; } -DVector<Face3> TriangleMesh::get_faces() const { +PoolVector<Face3> TriangleMesh::get_faces() const { if (!valid) - return DVector<Face3>(); + return PoolVector<Face3>(); - DVector<Face3> faces; + PoolVector<Face3> faces; int ts = triangles.size(); faces.resize(triangles.size()); - DVector<Face3>::Write w=faces.write(); - DVector<Triangle>::Read r = triangles.read(); - DVector<Vector3>::Read rv = vertices.read(); + PoolVector<Face3>::Write w=faces.write(); + PoolVector<Triangle>::Read r = triangles.read(); + PoolVector<Vector3>::Read rv = vertices.read(); for(int i=0;i<ts;i++) { for(int j=0;j<3;j++) { @@ -543,7 +543,7 @@ DVector<Face3> TriangleMesh::get_faces() const { } } - w = DVector<Face3>::Write(); + w = PoolVector<Face3>::Write(); return faces; } diff --git a/core/math/triangle_mesh.h b/core/math/triangle_mesh.h index b5e8f79cde..65250c023d 100644 --- a/core/math/triangle_mesh.h +++ b/core/math/triangle_mesh.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,7 @@ #include "face3.h" class TriangleMesh : public Reference { - OBJ_TYPE( TriangleMesh, Reference); + GDCLASS( TriangleMesh, Reference); struct Triangle { @@ -41,12 +41,12 @@ class TriangleMesh : public Reference { int indices[3]; }; - DVector<Triangle> triangles; - DVector<Vector3> vertices; + PoolVector<Triangle> triangles; + PoolVector<Vector3> vertices; struct BVH { - AABB aabb; + Rect3 aabb; Vector3 center; //used for sorting int left; int right; @@ -79,7 +79,7 @@ class TriangleMesh : public Reference { int _create_bvh(BVH*p_bvh,BVH** p_bb,int p_from,int p_size,int p_depth,int&max_depth,int&max_alloc); - DVector<BVH> bvh; + PoolVector<BVH> bvh; int max_depth; bool valid; @@ -88,11 +88,11 @@ public: bool is_valid() const; bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_point, Vector3 &r_normal) const; bool intersect_ray(const Vector3& p_begin,const Vector3& p_dir,Vector3 &r_point, Vector3 &r_normal) const; - Vector3 get_area_normal(const AABB& p_aabb) const; - DVector<Face3> get_faces() const; + Vector3 get_area_normal(const Rect3& p_aabb) const; + PoolVector<Face3> get_faces() const; - void create(const DVector<Vector3>& p_faces); + void create(const PoolVector<Vector3>& p_faces); TriangleMesh(); }; diff --git a/core/math/triangulate.cpp b/core/math/triangulate.cpp index eaf019f200..82b49be7f3 100644 --- a/core/math/triangulate.cpp +++ b/core/math/triangulate.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/triangulate.h b/core/math/triangulate.h index ef622b5005..d22677a8b8 100644 --- a/core/math/triangulate.h +++ b/core/math/triangulate.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/core/math/triangulator.cpp b/core/math/triangulator.cpp index 8f82d76823..75b2b064c4 100644 --- a/core/math/triangulator.cpp +++ b/core/math/triangulator.cpp @@ -1128,7 +1128,7 @@ int TriangulatorPartition::MonotonePartition(List<TriangulatorPoly> *inpolys, Li //this makes deleting existing edges much faster Set<ScanLineEdge>::Element **edgeTreeIterators,*edgeIter; edgeTreeIterators = new Set<ScanLineEdge>::Element*[maxnumvertices]; -// Pair<Set<ScanLineEdge>::Element*,bool> edgeTreeRet; + //Pair<Set<ScanLineEdge>::Element*,bool> edgeTreeRet; for(i = 0; i<numvertices; i++) edgeTreeIterators[i] = NULL; //for each vertex diff --git a/core/math/vector3.cpp b/core/math/vector3.cpp index fae3831dd6..3eb978333d 100644 --- a/core/math/vector3.cpp +++ b/core/math/vector3.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,7 +32,7 @@ void Vector3::rotate(const Vector3& p_axis,float p_phi) { - *this=Matrix3(p_axis,p_phi).xform(*this); + *this=Basis(p_axis,p_phi).xform(*this); } Vector3 Vector3::rotated(const Vector3& p_axis,float p_phi) const { diff --git a/core/math/vector3.h b/core/math/vector3.h index 06840be5e7..9ae9b69dfa 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,6 +34,7 @@ #include "math_funcs.h" #include "ustring.h" +class Basis; struct Vector3 { @@ -92,6 +93,8 @@ struct Vector3 { _FORCE_INLINE_ Vector3 cross(const Vector3& p_b) const; _FORCE_INLINE_ real_t dot(const Vector3& p_b) const; + _FORCE_INLINE_ Basis outer(const Vector3& p_b) const; + _FORCE_INLINE_ Basis to_diagonal_matrix() const; _FORCE_INLINE_ Vector3 abs() const; _FORCE_INLINE_ Vector3 floor() const; @@ -144,6 +147,8 @@ struct Vector3 { #else +#include "matrix3.h" + Vector3 Vector3::cross(const Vector3& p_b) const { Vector3 ret ( @@ -160,6 +165,21 @@ real_t Vector3::dot(const Vector3& p_b) const { return x*p_b.x + y*p_b.y + z*p_b.z; } +Basis Vector3::outer(const Vector3& p_b) const { + + Vector3 row0(x*p_b.x, x*p_b.y, x*p_b.z); + Vector3 row1(y*p_b.x, y*p_b.y, y*p_b.z); + Vector3 row2(z*p_b.x, z*p_b.y, z*p_b.z); + + return Basis(row0, row1, row2); +} + +Basis Vector3::to_diagonal_matrix() const { + return Basis(x, 0, 0, + 0, y, 0, + 0, 0, z); +} + Vector3 Vector3::abs() const { return Vector3( Math::abs(x), Math::abs(y), Math::abs(z) ); @@ -293,7 +313,6 @@ bool Vector3::operator==(const Vector3& p_v) const { } bool Vector3::operator!=(const Vector3& p_v) const { - return (x!=p_v.x || y!=p_v.y || z!=p_v.z); } |