diff --git a/irr/include/matrix4.h b/irr/include/matrix4.h index 374fc6e4a..8fce0157a 100644 --- a/irr/include/matrix4.h +++ b/irr/include/matrix4.h @@ -24,7 +24,12 @@ namespace core { //! 4x4 matrix. Mostly used as transformation matrix for 3d calculations. -/** The matrix is a D3D style matrix, row major with translations in the 4th row. */ +/** Conventions: Matrices are considered to be in row-major order. + * Multiplication of a matrix A with a row vector v is the premultiplication vA. + * Translations are thus in the 4th row. + * The matrix product AB yields a matrix C such that vC = (vB)A: + * B is applied first, then A. + */ template class CMatrix4 { @@ -242,17 +247,11 @@ public: //! Translate a vector by the inverse of the translation part of this matrix. void inverseTranslateVect(vector3df &vect) const; - //! Rotate a vector by the inverse of the rotation part of this matrix. - void inverseRotateVect(vector3df &vect) const; + //! Scale a vector, then rotate by the inverse of the rotation part of this matrix. + [[nodiscard]] vector3d scaleThenInvRotVect(const vector3d &vect) const; - //! Rotate a vector by the rotation part of this matrix. - void rotateVect(vector3df &vect) const; - - //! An alternate transform vector method, writing into a second vector - void rotateVect(core::vector3df &out, const core::vector3df &in) const; - - //! An alternate transform vector method, writing into an array of 3 floats - void rotateVect(T *out, const core::vector3df &in) const; + //! Rotate and scale a vector. Applies both rotation & scale part of the matrix. + [[nodiscard]] vector3d rotateAndScaleVect(const vector3d &vect) const; //! Transforms the vector by this matrix /** This operation is performed as if the vector was 4d with the 4th component =1 */ @@ -1154,39 +1153,23 @@ inline bool CMatrix4::isIdentity_integer_base() const } template -inline void CMatrix4::rotateVect(vector3df &vect) const +inline vector3d CMatrix4::rotateAndScaleVect(const vector3d &v) const { - vector3d tmp(static_cast(vect.X), static_cast(vect.Y), static_cast(vect.Z)); - vect.X = static_cast(tmp.X * M[0] + tmp.Y * M[4] + tmp.Z * M[8]); - vect.Y = static_cast(tmp.X * M[1] + tmp.Y * M[5] + tmp.Z * M[9]); - vect.Z = static_cast(tmp.X * M[2] + tmp.Y * M[6] + tmp.Z * M[10]); -} - -//! An alternate transform vector method, writing into a second vector -template -inline void CMatrix4::rotateVect(core::vector3df &out, const core::vector3df &in) const -{ - out.X = in.X * M[0] + in.Y * M[4] + in.Z * M[8]; - out.Y = in.X * M[1] + in.Y * M[5] + in.Z * M[9]; - out.Z = in.X * M[2] + in.Y * M[6] + in.Z * M[10]; -} - -//! An alternate transform vector method, writing into an array of 3 floats -template -inline void CMatrix4::rotateVect(T *out, const core::vector3df &in) const -{ - out[0] = in.X * M[0] + in.Y * M[4] + in.Z * M[8]; - out[1] = in.X * M[1] + in.Y * M[5] + in.Z * M[9]; - out[2] = in.X * M[2] + in.Y * M[6] + in.Z * M[10]; + return { + v.X * M[0] + v.Y * M[4] + v.Z * M[8], + v.X * M[1] + v.Y * M[5] + v.Z * M[9], + v.X * M[2] + v.Y * M[6] + v.Z * M[10] + }; } template -inline void CMatrix4::inverseRotateVect(vector3df &vect) const +inline vector3d CMatrix4::scaleThenInvRotVect(const vector3d &v) const { - vector3d tmp(static_cast(vect.X), static_cast(vect.Y), static_cast(vect.Z)); - vect.X = static_cast(tmp.X * M[0] + tmp.Y * M[1] + tmp.Z * M[2]); - vect.Y = static_cast(tmp.X * M[4] + tmp.Y * M[5] + tmp.Z * M[6]); - vect.Z = static_cast(tmp.X * M[8] + tmp.Y * M[9] + tmp.Z * M[10]); + return { + v.X * M[0] + v.Y * M[1] + v.Z * M[2], + v.X * M[4] + v.Y * M[5] + v.Z * M[6], + v.X * M[8] + v.Y * M[9] + v.Z * M[10] + }; } template @@ -1247,8 +1230,7 @@ inline void CMatrix4::transformPlane(core::plane3d &plane) const // Transform the normal by the transposed inverse of the matrix CMatrix4 transposedInverse(*this, EM4CONST_INVERSE_TRANSPOSED); - vector3df normal = plane.Normal; - transposedInverse.rotateVect(normal); + vector3df normal = transposedInverse.rotateAndScaleVect(plane.Normal); plane.setPlane(member, normal.normalize()); } diff --git a/irr/src/CB3DMeshFileLoader.cpp b/irr/src/CB3DMeshFileLoader.cpp index 4d78860b2..60eeb5743 100644 --- a/irr/src/CB3DMeshFileLoader.cpp +++ b/irr/src/CB3DMeshFileLoader.cpp @@ -389,7 +389,7 @@ bool CB3DMeshFileLoader::readChunkVRTS(CSkinnedMesh::SJoint *inJoint) // Transform the Vertex position by nested node... inJoint->GlobalMatrix.transformVect(Vertex.Pos); - inJoint->GlobalMatrix.rotateVect(Vertex.Normal); + Vertex.Normal = inJoint->GlobalMatrix.rotateAndScaleVect(Vertex.Normal); // Add it... BaseVertices.push_back(Vertex); diff --git a/irr/src/CGLTFMeshFileLoader.cpp b/irr/src/CGLTFMeshFileLoader.cpp index 64bbc10f1..b0c424936 100644 --- a/irr/src/CGLTFMeshFileLoader.cpp +++ b/irr/src/CGLTFMeshFileLoader.cpp @@ -354,8 +354,7 @@ static void transformVertices(std::vector &vertices, const cor // Apply scaling, rotation and rotation (in that order) to the position. transform.transformVect(vertex.Pos); // For the normal, we do not want to apply the translation. - // TODO note that this also applies scaling; the Irrlicht method is misnamed. - transform.rotateVect(vertex.Normal); + vertex.Normal = transform.rotateAndScaleVect(vertex.Normal); // Renormalize (length might have been affected by scaling). vertex.Normal.normalize(); } diff --git a/irr/src/CSkinnedMesh.cpp b/irr/src/CSkinnedMesh.cpp index 5db027abc..a0d3c3ec6 100644 --- a/irr/src/CSkinnedMesh.cpp +++ b/irr/src/CSkinnedMesh.cpp @@ -511,7 +511,7 @@ void CSkinnedMesh::skinJoint(SJoint *joint, SJoint *parentJoint) jointVertexPull.transformVect(thisVertexMove, weight.StaticPos); if (AnimateNormals) - jointVertexPull.rotateVect(thisNormalMove, weight.StaticNormal); + thisNormalMove = jointVertexPull.rotateAndScaleVect(weight.StaticNormal); if (!(*(weight.Moved))) { *(weight.Moved) = true; diff --git a/src/client/camera.cpp b/src/client/camera.cpp index bf9ec0bd5..615d30c87 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -405,10 +405,11 @@ void Camera::update(LocalPlayer* player, f32 frametime, f32 tool_reload_ratio) // Compute absolute camera position and target m_headnode->getAbsoluteTransformation().transformVect(m_camera_position, rel_cam_pos); - m_headnode->getAbsoluteTransformation().rotateVect(m_camera_direction, rel_cam_target - rel_cam_pos); + m_camera_direction = m_headnode->getAbsoluteTransformation() + .rotateAndScaleVect(rel_cam_target - rel_cam_pos); - v3f abs_cam_up; - m_headnode->getAbsoluteTransformation().rotateVect(abs_cam_up, rel_cam_up); + v3f abs_cam_up = m_headnode->getAbsoluteTransformation() + .rotateAndScaleVect(rel_cam_up); // Separate camera position for calculation v3f my_cp = m_camera_position; diff --git a/src/client/clientmap.cpp b/src/client/clientmap.cpp index d608ae2f6..ab826c775 100644 --- a/src/client/clientmap.cpp +++ b/src/client/clientmap.cpp @@ -1015,8 +1015,7 @@ int ClientMap::getBackgroundBrightness(float max_d, u32 daylight_factor, v3f z_dir = z_directions[i]; core::CMatrix4 a; a.buildRotateFromTo(v3f(0,1,0), z_dir); - v3f dir = m_camera_direction; - a.rotateVect(dir); + v3f dir = a.rotateAndScaleVect(m_camera_direction); int br = 0; float step = BS*1.5; if(max_d > 35*BS) diff --git a/src/client/hud.cpp b/src/client/hud.cpp index e4c06b542..2a1acb288 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -536,9 +536,9 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) return; // Avoid zero divides // Angle according to camera view - v3f fore(0.f, 0.f, 1.f); scene::ICameraSceneNode *cam = client->getSceneManager()->getActiveCamera(); - cam->getAbsoluteTransformation().rotateVect(fore); + v3f fore = cam->getAbsoluteTransformation() + .rotateAndScaleVect(v3f(0.f, 0.f, 1.f)); int angle = - fore.getHorizontalAngle().Y; // Limit angle and ajust with given offset diff --git a/src/client/particles.cpp b/src/client/particles.cpp index 1eab93579..3a2dace12 100644 --- a/src/client/particles.cpp +++ b/src/client/particles.cpp @@ -357,16 +357,18 @@ void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius, if (attached_absolute_pos_rot_matrix) { // Apply attachment rotation - attached_absolute_pos_rot_matrix->rotateVect(pp.vel); - attached_absolute_pos_rot_matrix->rotateVect(pp.acc); + pp.vel = attached_absolute_pos_rot_matrix->rotateAndScaleVect(pp.vel); + pp.acc = attached_absolute_pos_rot_matrix->rotateAndScaleVect(pp.acc); } if (attractor_obj) attractor_origin += attractor_obj->getPosition() / BS; if (attractor_direction_obj) { auto *attractor_absolute_pos_rot_matrix = attractor_direction_obj->getAbsolutePosRotMatrix(); - if (attractor_absolute_pos_rot_matrix) - attractor_absolute_pos_rot_matrix->rotateVect(attractor_direction); + if (attractor_absolute_pos_rot_matrix) { + attractor_direction = attractor_absolute_pos_rot_matrix + ->rotateAndScaleVect(attractor_direction); + } } pp.expirationtime = r_exp.pickWithin(); diff --git a/src/client/shadows/dynamicshadows.cpp b/src/client/shadows/dynamicshadows.cpp index ffe7d4de5..2722c871b 100644 --- a/src/client/shadows/dynamicshadows.cpp +++ b/src/client/shadows/dynamicshadows.cpp @@ -137,8 +137,8 @@ void DirectionalLight::update_frustum(const Camera *cam, Client *client, bool fo // when camera offset changes, adjust the current frustum view matrix to avoid flicker v3s16 cam_offset = cam->getOffset(); if (cam_offset != shadow_frustum.camera_offset) { - v3f rotated_offset; - shadow_frustum.ViewMat.rotateVect(rotated_offset, intToFloat(cam_offset - shadow_frustum.camera_offset, BS)); + v3f rotated_offset = shadow_frustum.ViewMat.rotateAndScaleVect( + intToFloat(cam_offset - shadow_frustum.camera_offset, BS)); shadow_frustum.ViewMat.setTranslation(shadow_frustum.ViewMat.getTranslation() + rotated_offset); shadow_frustum.player += intToFloat(shadow_frustum.camera_offset - cam->getOffset(), BS); shadow_frustum.camera_offset = cam_offset; diff --git a/src/client/sky.cpp b/src/client/sky.cpp index 65577418e..27640bc28 100644 --- a/src/client/sky.cpp +++ b/src/client/sky.cpp @@ -838,14 +838,10 @@ void Sky::updateStars() ); core::CMatrix4 a; a.buildRotateFromTo(v3f(0, 1, 0), r); - v3f p = v3f(-d, 1, -d); - v3f p1 = v3f(d, 1, -d); - v3f p2 = v3f(d, 1, d); - v3f p3 = v3f(-d, 1, d); - a.rotateVect(p); - a.rotateVect(p1); - a.rotateVect(p2); - a.rotateVect(p3); + v3f p = a.rotateAndScaleVect(v3f(-d, 1, -d)); + v3f p1 = a.rotateAndScaleVect(v3f(d, 1, -d)); + v3f p2 = a.rotateAndScaleVect(v3f(d, 1, d)); + v3f p3 = a.rotateAndScaleVect(v3f(-d, 1, d)); vertices.push_back(video::S3DVertex(p, {}, {}, {})); vertices.push_back(video::S3DVertex(p1, {}, {}, {})); vertices.push_back(video::S3DVertex(p2, {}, {}, {})); diff --git a/src/gui/guiScene.cpp b/src/gui/guiScene.cpp index 9293ebe22..33310fe35 100644 --- a/src/gui/guiScene.cpp +++ b/src/gui/guiScene.cpp @@ -225,8 +225,7 @@ void GUIScene::setCameraRotation(v3f rot) core::matrix4 mat; mat.setRotationDegrees(rot); - m_cam_pos = v3f(0.f, 0.f, m_cam_distance); - mat.rotateVect(m_cam_pos); + m_cam_pos = mat.rotateAndScaleVect(v3f(0.f, 0.f, m_cam_distance)); m_cam_pos += m_target_pos; m_cam->setPosition(m_cam_pos);