dev.nlited.com

>>

Terrain Alignment

<<<< prev
next >>>>

2017-12-02 03:21:19 chip Page 2077 📢 PUBLIC

Nov 30 2017

The Tiger needs to lie flat along the surface of the terrain. This seems like a simple problem, but it has me stumped. This XBox forum and GameDev.net and Microsoft forum might provide a clue. I downloaded the referenced HeightMap example. This looked promising but uses Visual Studio 2010 and XNA; VS15 refuses to load it. Frustrating! This example does exactly what I am trying to accomplish but the code uses a deprecated library, is written in C#, and the docs are stored in a strange format (.PDN?) I tried to walk through the code but I can't use the code as-is because with DirectXTK Right and Forward are read-only properties of the matrix. The example is setting them.

SUCCESS! Once again success and failure hinge on a random forum post:

Hi, try this:

// Obtain model "normal" from current rotation quaternion (or rotation matrix) Vector3 currentNormal = Matrix.CreateFromQuaternion(m_Rotation).Up; // Obtain triangle normal Vector3 newNormal = tri.Normal; // Obtain axis between two normals, it will be the rotation axis Vector3 axis = Vector3.Normalize(Vector3.Cross(currentNormal, newNormal)); // Calc angle between normals float angle = (float)Math.Acos(Vector3.Dot(currentNormal, newNormal)); if (angle != 0.0f) { // Create a quaternion with the rotation difference between normals m_Inclination = Quaternion.CreateFromAxisAngle(axis, angle); } else { m_Inclination = Quaternion.Identity; } // Calc final transform m_ModelSpace = Matrix.CreateScale(m_Scale); m_ModelSpace *= Matrix.CreateFromQuaternion(m_Rotation); m_ModelSpace *= Matrix.CreateFromQuaternion(m_Inclination); m_ModelSpace *= Matrix.CreateTranslation(m_Position);

If you want you can apply some slerp to make the transitions between triangles more realistic.

You can see the results of this code in www.codeplex.com/tanksgame

Regards
Friday, May 04, 2007 2:16 PM

I integrated it as:


GameObj.cpp: void ObjTiger::Update(float secTotal, float secElapsed, Keyboard *pKB, Mouse *pMouse) { xform = Matrix::Identity; if(pGame->ctrlObjID==CTRL_TIGER) { Keyboard::State kb= pKB->GetState(); if(kb.A) dir.y+= secElapsed*0.10f; if(kb.D) dir.y-= secElapsed*0.20f; if(kb.W) Move(secElapsed*0.20f); if(kb.S) Move(-secElapsed*0.05f); } VertexPositionNormalColor vtxPos; pGame->getVertex(pos.x,pos.z,vtxPos); pos.y= vtxPos.position.y+0.10f; xform*= Matrix::CreateFromYawPitchRoll(dir.y,dir.z,dir.x); xform*= Matrix::CreateFromYawPitchRoll(XMConvertToRadians(-90.0f),0,0); //Align with the terrain by using the vertex normal. Vector3 curNormal= xform.Up(); //This should always be (0,1,0) Vector3 axis= curNormal.Cross(vtxPos.normal); // Model.Up X Terrain.Up gives the axis of rotation. axis.Normalize(); // Model.Up . Terrain.Up is the cosine of the angle of rotation. float angle= acosf(curNormal.Dot(vtxPos.normal)); if(fabsf(angle)>0.01f) { // Create an inclination quaternion from the axis and angle, then apply it. (Magic!) Quaternion inclination= Quaternion::CreateFromAxisAngle(axis,angle); xform*= Matrix::CreateFromQuaternion(inclination); } xform*= Matrix::CreateScale(Scale); xform.Translation(pos); }

And now my Tiger is climbing the hills!

Direct3D Models



WebV7 (C)2018 nlited | Rendered by tikope in 44.003ms | 3.149.231.122