summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/bullet/collision_object_bullet.cpp9
-rw-r--r--modules/bullet/generic_6dof_joint_bullet.cpp40
-rw-r--r--modules/bullet/rigid_body_bullet.cpp5
-rw-r--r--modules/csg/csg_shape.cpp127
-rw-r--r--modules/csg/csg_shape.h18
-rw-r--r--modules/csg/doc_classes/CSGShape.xml3
-rw-r--r--modules/squish/image_compress_squish.cpp7
7 files changed, 200 insertions, 9 deletions
diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp
index 402a276f95..441fa7c8af 100644
--- a/modules/bullet/collision_object_bullet.cpp
+++ b/modules/bullet/collision_object_bullet.cpp
@@ -304,7 +304,11 @@ bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) {
}
void RigidCollisionObjectBullet::shape_changed(int p_shape_index) {
- bulletdelete(shapes.write[p_shape_index].bt_shape);
+ ShapeWrapper &shp = shapes.write[p_shape_index];
+ if (shp.bt_shape == mainShape) {
+ mainShape = NULL;
+ }
+ bulletdelete(shp.bt_shape);
reload_shapes();
}
@@ -366,5 +370,8 @@ void RigidCollisionObjectBullet::body_scale_changed() {
void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) {
ShapeWrapper &shp = shapes.write[p_index];
shp.shape->remove_owner(this, p_permanentlyFromThisBody);
+ if (shp.bt_shape == mainShape) {
+ mainShape = NULL;
+ }
bulletdelete(shp.bt_shape);
}
diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp
index a36f1123bc..a94b88d566 100644
--- a/modules/bullet/generic_6dof_joint_bullet.cpp
+++ b/modules/bullet/generic_6dof_joint_bullet.cpp
@@ -135,6 +135,15 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT:
sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis] = p_value;
break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis] = p_value;
+ break;
case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT:
limits_lower[1][p_axis] = p_value;
set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter
@@ -143,6 +152,9 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
limits_upper[1][p_axis] = p_value;
set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter
break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce = p_value;
+ break;
case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP:
sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP = p_value;
break;
@@ -152,6 +164,15 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT:
sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce = p_value;
break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint = p_value;
+ break;
default:
ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
WARN_DEPRECATED
@@ -170,6 +191,12 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6
return sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis];
case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT:
return sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis];
+ case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT:
+ return sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis];
case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT:
return limits_lower[1][p_axis];
case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT:
@@ -182,6 +209,12 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6
return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity;
case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT:
return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping;
+ case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT:
+ return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint;
default:
ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
WARN_DEPRECATED;
@@ -215,6 +248,12 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF
case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR:
sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] = flags[p_axis][p_flag];
break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING:
+ sixDOFConstraint->getTranslationalLimitMotor()->m_enableSpring[p_axis] = p_value;
+ break;
+ case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING:
+ sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableSpring = p_value;
+ break;
default:
ERR_EXPLAIN("This flag " + itos(p_flag) + " is deprecated");
WARN_DEPRECATED
@@ -224,6 +263,5 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF
bool Generic6DOFJointBullet::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const {
ERR_FAIL_INDEX_V(p_axis, 3, false);
-
return flags[p_axis][p_flag];
}
diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp
index 37e7718969..85659e1523 100644
--- a/modules/bullet/rigid_body_bullet.cpp
+++ b/modules/bullet/rigid_body_bullet.cpp
@@ -797,7 +797,10 @@ void RigidBodyBullet::reload_shapes() {
const btScalar mass = invMass == 0 ? 0 : 1 / invMass;
if (mainShape) {
- btVector3 inertia;
+ // inertia initialised zero here because some of bullet's collision
+ // shapes incorrectly do not set the vector in calculateLocalIntertia.
+ // Arbitrary zero is preferable to undefined behaviour.
+ btVector3 inertia(0, 0, 0);
mainShape->calculateLocalInertia(mass, inertia);
btBody->setMassProps(mass, inertia);
}
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 4eb798de11..23d879e1cd 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -159,6 +159,74 @@ CSGBrush *CSGShape::_get_brush() {
return brush;
}
+int CSGShape::mikktGetNumFaces(const SMikkTSpaceContext *pContext) {
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ return surface.vertices.size() / 3;
+}
+
+int CSGShape::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) {
+ // always 3
+ return 3;
+}
+
+void CSGShape::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) {
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ Vector3 v = surface.verticesw[iFace * 3 + iVert];
+ fvPosOut[0] = v.x;
+ fvPosOut[1] = v.y;
+ fvPosOut[2] = v.z;
+}
+
+void CSGShape::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) {
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ Vector3 n = surface.normalsw[iFace * 3 + iVert];
+ fvNormOut[0] = n.x;
+ fvNormOut[1] = n.y;
+ fvNormOut[2] = n.z;
+}
+
+void CSGShape::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) {
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ Vector2 t = surface.uvsw[iFace * 3 + iVert];
+ fvTexcOut[0] = t.x;
+ fvTexcOut[1] = t.y;
+}
+
+void CSGShape::mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) {
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ int i = (iFace * 3 + iVert) * 4;
+
+ // Godot seems to want the tangent flipped because our handedness is reversed..
+ surface.tansw[i++] = -fvTangent[0];
+ surface.tansw[i++] = -fvTangent[1];
+ surface.tansw[i++] = -fvTangent[2];
+ surface.tansw[i++] = fSign;
+}
+
+void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
+ const tbool bIsOrientationPreserving, const int iFace, const int iVert) {
+
+ ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData);
+
+ int i = iFace * 3 + iVert;
+ Vector3 normal = surface.normalsw[i];
+ Vector3 tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]);
+ Vector3 bitangent = Vector3(fvBiTangent[0], fvBiTangent[1], fvBiTangent[2]);
+ float d = bitangent.dot(normal.cross(tangent));
+
+ // Godot seems to want the tangent flipped because our handedness is reversed..
+ i *= 4;
+ surface.tansw[i++] = -tangent.x;
+ surface.tansw[i++] = -tangent.y;
+ surface.tansw[i++] = -tangent.z;
+ surface.tansw[i++] = d < 0 ? -1 : 1;
+}
+
void CSGShape::_update_shape() {
if (parent)
@@ -211,6 +279,9 @@ void CSGShape::_update_shape() {
surfaces.write[i].vertices.resize(face_count[i] * 3);
surfaces.write[i].normals.resize(face_count[i] * 3);
surfaces.write[i].uvs.resize(face_count[i] * 3);
+ if (calculate_tangents) {
+ surfaces.write[i].tans.resize(face_count[i] * 3 * 4);
+ }
surfaces.write[i].last_added = 0;
if (i != surfaces.size() - 1) {
@@ -220,6 +291,9 @@ void CSGShape::_update_shape() {
surfaces.write[i].verticesw = surfaces.write[i].vertices.write();
surfaces.write[i].normalsw = surfaces.write[i].normals.write();
surfaces.write[i].uvsw = surfaces.write[i].uvs.write();
+ if (calculate_tangents) {
+ surfaces.write[i].tansw = surfaces.write[i].tans.write();
+ }
}
//fill arrays
@@ -274,9 +348,19 @@ void CSGShape::_update_shape() {
normal = -normal;
}
- surfaces[idx].verticesw[last + order[j]] = v;
- surfaces[idx].uvsw[last + order[j]] = n->faces[i].uvs[j];
- surfaces[idx].normalsw[last + order[j]] = normal;
+ int k = last + order[j];
+ surfaces[idx].verticesw[k] = v;
+ surfaces[idx].uvsw[k] = n->faces[i].uvs[j];
+ surfaces[idx].normalsw[k] = normal;
+
+ if (calculate_tangents) {
+ // zero out our tangents for now
+ k *= 4;
+ surfaces[idx].tansw[k++] = 0.0;
+ surfaces[idx].tansw[k++] = 0.0;
+ surfaces[idx].tansw[k++] = 0.0;
+ surfaces[idx].tansw[k++] = 0.0;
+ }
}
surfaces.write[idx].last_added += 3;
@@ -287,20 +371,43 @@ void CSGShape::_update_shape() {
//create surfaces
for (int i = 0; i < surfaces.size(); i++) {
+ // calculate tangents for this surface
+ bool have_tangents = calculate_tangents;
+ if (have_tangents) {
+ SMikkTSpaceInterface mkif;
+ mkif.m_getNormal = mikktGetNormal;
+ mkif.m_getNumFaces = mikktGetNumFaces;
+ mkif.m_getNumVerticesOfFace = mikktGetNumVerticesOfFace;
+ mkif.m_getPosition = mikktGetPosition;
+ mkif.m_getTexCoord = mikktGetTexCoord;
+ mkif.m_setTSpace = mikktSetTSpaceDefault;
+ mkif.m_setTSpaceBasic = NULL;
+
+ SMikkTSpaceContext msc;
+ msc.m_pInterface = &mkif;
+ msc.m_pUserData = &surfaces.write[i];
+ have_tangents = genTangSpaceDefault(&msc);
+ }
+ // unset write access
surfaces.write[i].verticesw = PoolVector<Vector3>::Write();
surfaces.write[i].normalsw = PoolVector<Vector3>::Write();
surfaces.write[i].uvsw = PoolVector<Vector2>::Write();
+ surfaces.write[i].tansw = PoolVector<float>::Write();
if (surfaces[i].last_added == 0)
continue;
+ // and convert to surface array
Array array;
array.resize(Mesh::ARRAY_MAX);
array[Mesh::ARRAY_VERTEX] = surfaces[i].vertices;
array[Mesh::ARRAY_NORMAL] = surfaces[i].normals;
array[Mesh::ARRAY_TEX_UV] = surfaces[i].uvs;
+ if (have_tangents) {
+ array[Mesh::ARRAY_TANGENT] = surfaces[i].tans;
+ }
int idx = root_mesh->get_surface_count();
root_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, array);
@@ -400,6 +507,15 @@ CSGShape::Operation CSGShape::get_operation() const {
return operation;
}
+void CSGShape::set_calculate_tangents(bool p_calculate_tangents) {
+ calculate_tangents = p_calculate_tangents;
+ _make_dirty();
+}
+
+bool CSGShape::is_calculating_tangents() const {
+ return calculate_tangents;
+}
+
void CSGShape::_validate_property(PropertyInfo &property) const {
if (is_inside_tree() && property.name.begins_with("use_collision") && !is_root_shape()) {
//hide collision if not root
@@ -421,9 +537,13 @@ void CSGShape::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap);
ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap);
+ ClassDB::bind_method(D_METHOD("set_calculate_tangents", "enabled"), &CSGShape::set_calculate_tangents);
+ ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape::is_calculating_tangents);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "operation", PROPERTY_HINT_ENUM, "Union,Intersection,Subtraction"), "set_operation", "get_operation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_collision"), "set_use_collision", "is_using_collision");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001"), "set_snap", "get_snap");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "calculate_tangents"), "set_calculate_tangents", "is_calculating_tangents");
BIND_ENUM_CONSTANT(OPERATION_UNION);
BIND_ENUM_CONSTANT(OPERATION_INTERSECTION);
@@ -438,6 +558,7 @@ CSGShape::CSGShape() {
use_collision = false;
operation = OPERATION_UNION;
snap = 0.001;
+ calculate_tangents = true;
}
CSGShape::~CSGShape() {
diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h
index 6898cdaf64..0a4bb5f665 100644
--- a/modules/csg/csg_shape.h
+++ b/modules/csg/csg_shape.h
@@ -36,6 +36,7 @@
#include "csg.h"
#include "scene/3d/visual_instance.h"
#include "scene/resources/concave_polygon_shape.h"
+#include "thirdparty/misc/mikktspace.h"
class CSGShape : public VisualInstance {
GDCLASS(CSGShape, VisualInstance);
@@ -63,6 +64,8 @@ private:
Ref<ConcavePolygonShape> root_collision_shape;
RID root_collision_instance;
+ bool calculate_tangents;
+
Ref<ArrayMesh> root_mesh;
struct Vector3Hasher {
@@ -78,14 +81,26 @@ private:
PoolVector<Vector3> vertices;
PoolVector<Vector3> normals;
PoolVector<Vector2> uvs;
+ PoolVector<float> tans;
Ref<Material> material;
int last_added;
PoolVector<Vector3>::Write verticesw;
PoolVector<Vector3>::Write normalsw;
PoolVector<Vector2>::Write uvsw;
+ PoolVector<float>::Write tansw;
};
+ //mikktspace callbacks
+ static int mikktGetNumFaces(const SMikkTSpaceContext *pContext);
+ static int mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace);
+ static void mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert);
+ static void mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert);
+ static void mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert);
+ static void mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert);
+ static void mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
+ const tbool bIsOrientationPreserving, const int iFace, const int iVert);
+
void _update_shape();
protected:
@@ -115,6 +130,9 @@ public:
void set_snap(float p_snap);
float get_snap() const;
+ void set_calculate_tangents(bool p_calculate_tangents);
+ bool is_calculating_tangents() const;
+
bool is_root_shape() const;
CSGShape();
~CSGShape();
diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape.xml
index 90621b94f4..ac3c2342fc 100644
--- a/modules/csg/doc_classes/CSGShape.xml
+++ b/modules/csg/doc_classes/CSGShape.xml
@@ -20,6 +20,9 @@
</method>
</methods>
<members>
+ <member name="calculate_tangents" type="bool" setter="set_calculate_tangents" getter="is_calculating_tangents">
+ Calculate tangents for the CSG shape which allows the use of normal maps. This is only applied on the root shape, this setting is ignored on any child.
+ </member>
<member name="operation" type="int" setter="set_operation" getter="get_operation" enum="CSGShape.Operation">
The operation that is performed on this shape. This is ignored for the first CSG child node as the operation is between this node and the previous child of this nodes parent.
</member>
diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp
index 26cb76011c..a08ac7bd28 100644
--- a/modules/squish/image_compress_squish.cpp
+++ b/modules/squish/image_compress_squish.cpp
@@ -64,12 +64,13 @@ void image_decompress_squish(Image *p_image) {
return;
}
- int dst_ofs = 0;
-
for (int i = 0; i <= mm_count; i++) {
int src_ofs = 0, mipmap_size = 0, mipmap_w = 0, mipmap_h = 0;
p_image->get_mipmap_offset_size_and_dimensions(i, src_ofs, mipmap_size, mipmap_w, mipmap_h);
- squish::DecompressImage(&wb[dst_ofs], mipmap_w, mipmap_h, &rb[src_ofs], squish_flags);
+ int dst_ofs = Image::get_image_mipmap_offset(p_image->get_width(), p_image->get_height(), target_format, i);
+ squish::DecompressImage(&wb[dst_ofs], w, h, &rb[src_ofs], squish_flags);
+ w >>= 1;
+ h >>= 1;
}
p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data);