From eb7f07d654669d6849c5ec30eb710b2edad9bde5 Mon Sep 17 00:00:00 2001 From: kearwood Date: Sat, 15 Dec 2012 01:39:32 +0000 Subject: [PATCH] Implemented KRNode::getInverseModelMatrix Implemented KRNode::rayCast Implemented KRNode::lineCast Fixed bug in KRCollider::rayCast --HG-- extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%40193 --- KREngine/KREngine/Classes/KRCollider.cpp | 27 ++++++++++++++++++++++++ KREngine/KREngine/Classes/KRCollider.h | 3 +++ KREngine/KREngine/Classes/KRMat4.cpp | 10 +++++++++ KREngine/KREngine/Classes/KRMat4.h | 1 + KREngine/KREngine/Classes/KRModel.cpp | 10 +++++++-- KREngine/KREngine/Classes/KRNode.cpp | 11 ++++++++++ KREngine/KREngine/Classes/KRNode.h | 3 +++ 7 files changed, 63 insertions(+), 2 deletions(-) diff --git a/KREngine/KREngine/Classes/KRCollider.cpp b/KREngine/KREngine/Classes/KRCollider.cpp index 37973f4..817d0ed 100644 --- a/KREngine/KREngine/Classes/KRCollider.cpp +++ b/KREngine/KREngine/Classes/KRCollider.cpp @@ -73,3 +73,30 @@ KRAABB KRCollider::getBounds() { } } +bool KRCollider::lineCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo) +{ + if(m_models.size()) { + KRHitInfo hitinfo_model_space = KRHitInfo(KRMat4::Dot(getInverseModelMatrix(), hitinfo.getPosition()), KRMat4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal()), hitinfo.getNode()); + KRVector3 v0_model_space = KRMat4::Dot(getModelMatrix(), v0); + KRVector3 v1_model_space = KRMat4::Dot(getModelMatrix(), v1); + if(m_models[0]->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) { + hitinfo = KRHitInfo(KRMat4::Dot(getModelMatrix(), hitinfo_model_space.getPosition()), KRMat4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal()), hitinfo_model_space.getNode()); + return true; + } + } + return false; +} + +bool KRCollider::rayCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo) +{ + if(m_models.size()) { + KRHitInfo hitinfo_model_space = KRHitInfo(KRMat4::Dot(getInverseModelMatrix(), hitinfo.getPosition()), KRMat4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal()), hitinfo.getNode()); + KRVector3 v0_model_space = KRMat4::Dot(getModelMatrix(), v0); + KRVector3 v1_model_space = v0_model_space + KRMat4::DotNoTranslate(getModelMatrix(), KRVector3::Normalize(v1 - v0)); + if(m_models[0]->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) { + hitinfo = KRHitInfo(KRMat4::Dot(getModelMatrix(), hitinfo_model_space.getPosition()), KRMat4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal()), hitinfo_model_space.getNode()); + return true; + } + } + return false; +} diff --git a/KREngine/KREngine/Classes/KRCollider.h b/KREngine/KREngine/Classes/KRCollider.h index 4061c7d..5ab2a44 100644 --- a/KREngine/KREngine/Classes/KRCollider.h +++ b/KREngine/KREngine/Classes/KRCollider.h @@ -55,6 +55,9 @@ public: virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual KRAABB getBounds(); + bool lineCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo); + bool rayCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo); + private: std::vector m_models; std::string m_model_name; diff --git a/KREngine/KREngine/Classes/KRMat4.cpp b/KREngine/KREngine/Classes/KRMat4.cpp index d98bd40..be0624d 100644 --- a/KREngine/KREngine/Classes/KRMat4.cpp +++ b/KREngine/KREngine/Classes/KRMat4.cpp @@ -293,6 +293,16 @@ KRVector3 KRMat4::Dot(const KRMat4 &m, const KRVector3 &v) { ); } +// Dot product without including translation; useful for transforming normals and tangents +KRVector3 DotNoTranslate(const KRMat4 &m, const KRVector3 &v) +{ + return KRVector3( + v.x * (float)m[0*4 + 0] + v.y * (float)m[1*4 + 0] + v.z * (float)m[2*4 + 0], + v.x * (float)m[0*4 + 1] + v.y * (float)m[1*4 + 1] + v.z * (float)m[2*4 + 1], + v.x * (float)m[0*4 + 2] + v.y * (float)m[1*4 + 2] + v.z * (float)m[2*4 + 2] + ); +} + /* Dot Product, returning w component as if it were a KRVector4 (This will be deprecated once KRVector4 is implemented instead*/ float KRMat4::DotW(const KRMat4 &m, const KRVector3 &v) { return v.x * (float)m[0*4 + 3] + v.y * (float)m[1*4 + 3] + v.z * (float)m[2*4 + 3] + (float)m[3*4 + 3]; diff --git a/KREngine/KREngine/Classes/KRMat4.h b/KREngine/KREngine/Classes/KRMat4.h index 2a53064..3b10925 100644 --- a/KREngine/KREngine/Classes/KRMat4.h +++ b/KREngine/KREngine/Classes/KRMat4.h @@ -104,6 +104,7 @@ public: bool invert(); void transpose(); + static KRVector3 DotNoTranslate(const KRMat4 &m, const KRVector3 &v); // Dot product without including translation; useful for transforming normals and tangents static KRMat4 Invert(const KRMat4 &m); static KRMat4 Transpose(const KRMat4 &m); static KRVector3 Dot(const KRMat4 &m, const KRVector3 &v); diff --git a/KREngine/KREngine/Classes/KRModel.cpp b/KREngine/KREngine/Classes/KRModel.cpp index b711caa..7423b18 100644 --- a/KREngine/KREngine/Classes/KRModel.cpp +++ b/KREngine/KREngine/Classes/KRModel.cpp @@ -774,8 +774,14 @@ bool KRModel::rayCast(const KRVector3 &line_v0, const KRVector3 &line_v1, const // Update the hitinfo object if this hit is closer than the prior hit // Interpolate between the three vertex normals, performing a 3-way lerp of tri_n0, tri_n1, and tri_n2 - KRVector3 distances = KRVector3::Normalize(KRVector3((tri_v0 - hit_point).magnitude(), (tri_v1 - hit_point).magnitude(), (tri_v2 - hit_point).magnitude())); - KRVector3 normal = tri_n0 * (1.0 - distances[0]) + tri_n1 * (1.0 - distances[1]) + tri_n2 * (1.0 - distances[3]); + float distance_v0 = (tri_v0 - hit_point).magnitude(); + float distance_v1 = (tri_v1 - hit_point).magnitude(); + float distance_v2 = (tri_v2 - hit_point).magnitude(); + float distance_total = distance_v0 + distance_v1 + distance_v2; + distance_v0 /= distance_total; + distance_v1 /= distance_total; + distance_v2 /= distance_total; + KRVector3 normal = tri_n0 * (1.0 - distance_v0) + tri_n1 * (1.0 - distance_v1) + tri_n2 * (1.0 - distance_v2); hitinfo = KRHitInfo(hit_point, KRVector3()); } diff --git a/KREngine/KREngine/Classes/KRNode.cpp b/KREngine/KREngine/Classes/KRNode.cpp index ecc6d19..e5cfe1d 100644 --- a/KREngine/KREngine/Classes/KRNode.cpp +++ b/KREngine/KREngine/Classes/KRNode.cpp @@ -33,6 +33,7 @@ KRNode::KRNode(KRScene &scene, std::string name) : KRContextObject(scene.getCont m_pScene = &scene; getScene().notify_sceneGraphCreate(this); m_modelMatrixValid = false; + m_inverseModelMatrixValid = false; m_bindPoseMatrixValid = false; m_inverseBindPoseMatrixValid = false; m_modelMatrix = KRMat4(); @@ -98,6 +99,7 @@ void KRNode::loadXML(tinyxml2::XMLElement *e) { m_bindPoseMatrixValid = false; m_inverseBindPoseMatrixValid = false; m_modelMatrixValid = false; + m_inverseModelMatrixValid = false; for(tinyxml2::XMLElement *child_element=e->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) { KRNode *child_node = KRNode::LoadXML(getScene(), child_element); @@ -237,6 +239,7 @@ KRAABB KRNode::getBounds() { void KRNode::invalidateModelMatrix() { m_modelMatrixValid = false; + m_inverseModelMatrixValid = false; for(std::vector::iterator itr=m_childNodes.begin(); itr < m_childNodes.end(); ++itr) { KRNode *child = (*itr); child->invalidateModelMatrix(); @@ -275,6 +278,14 @@ const KRMat4 &KRNode::getModelMatrix() return m_modelMatrix; } +const KRMat4 &KRNode::getInverseModelMatrix() +{ + if(!m_inverseModelMatrixValid) { + m_inverseModelMatrix = KRMat4::Invert(getModelMatrix()); + } + return m_inverseModelMatrix; +} + const KRMat4 &KRNode::getBindPoseMatrix() { if(!m_bindPoseMatrixValid) { diff --git a/KREngine/KREngine/Classes/KRNode.h b/KREngine/KREngine/Classes/KRNode.h index 275383c..44b69cf 100644 --- a/KREngine/KREngine/Classes/KRNode.h +++ b/KREngine/KREngine/Classes/KRNode.h @@ -73,6 +73,7 @@ public: virtual KRAABB getBounds(); const KRMat4 &getModelMatrix(); + const KRMat4 &getInverseModelMatrix(); const KRMat4 &getBindPoseMatrix(); const KRMat4 &getInverseBindPoseMatrix(); @@ -114,9 +115,11 @@ private: void invalidateModelMatrix(); void invalidateBindPoseMatrix(); KRMat4 m_modelMatrix; + KRMat4 m_inverseModelMatrix; KRMat4 m_bindPoseMatrix; KRMat4 m_inverseBindPoseMatrix; bool m_modelMatrixValid; + bool m_inverseModelMatrixValid; bool m_bindPoseMatrixValid; bool m_inverseBindPoseMatrixValid;