void CSPCharacter::LockViewToPlanet() { // Now lock the roll value to the planet. CPlanet* pNearestPlanet = GetNearestPlanet(); if (!pNearestPlanet) return; Matrix4x4 mGlobalRotation = GetGlobalTransform(); mGlobalRotation.SetTranslation(CScalableVector()); // Construct a "local space" for the planet Vector vecPlanetUp = GetUpVector(); Vector vecPlanetForward = mGlobalRotation.GetForwardVector(); Vector vecPlanetRight = vecPlanetForward.Cross(vecPlanetUp).Normalized(); vecPlanetForward = vecPlanetUp.Cross(vecPlanetRight).Normalized(); Matrix4x4 mPlanet(vecPlanetForward, vecPlanetUp, vecPlanetRight); Matrix4x4 mPlanetInverse = mPlanet; mPlanetInverse.InvertTR(); // Bring our current view angles into that local space Matrix4x4 mLocalRotation = mPlanetInverse * mGlobalRotation; EAngle angLocalRotation = mLocalRotation.GetAngles(); // Lock them so that the roll is 0 // I'm sure there's a way to do this without converting to euler but at this point I don't care. angLocalRotation.r = 0; Matrix4x4 mLockedLocalRotation; mLockedLocalRotation.SetAngles(angLocalRotation); // Bring it back out to global space Matrix4x4 mLockedRotation = mPlanet * mLockedLocalRotation; // Only use the changed r value to avoid floating point crap EAngle angNewLockedRotation = GetGlobalAngles(); EAngle angOverloadRotation = mLockedRotation.GetAngles(); // Lerp our way there float flTimeToLocked = 1; if (GameServer()->GetGameTime() - m_flLastEnteredAtmosphere > flTimeToLocked) angNewLockedRotation.r = angOverloadRotation.r; else angNewLockedRotation.r = RemapValClamped(SLerp(GameServer()->GetGameTime() - m_flLastEnteredAtmosphere, 0.3f), 0, flTimeToLocked, m_flRollFromSpace, angOverloadRotation.r); SetGlobalAngles(angNewLockedRotation); }
int main( int argc, char* argv[] ) { printf("Test quaternions.\n"); { printf("\n=== 1 =============================================\n"); CQuaternion Q1; Dump(Q1); } { printf("\n=== 2 =============================================\n"); CQuaternion Q2( CVector(0.0f,0.0f,666.0f), (float)CONST_PI ); Dump(Q2); } { printf("\n=== 3 =============================================\n"); CQuaternion Q3( 1, 1, 1, 1 ); Dump(Q3); printf("%f\n", Q3.Norm() ); printf("%f\n", Q3.Length() ); Q3.Normalize(); Dump(Q3); } { printf("\n=== 4 =============================================\n"); CQuaternion Q4( 1, 1, 1, 1 ); Dump(Q4); CQuaternion Q41 = !Q4; Dump(Q41); CQuaternion Q42 = -Q4; Dump(Q42); } { printf("\n=== 5 =============================================\n"); CQuaternion Q51( 1, 2, 3, 4 ); Dump(Q51); CQuaternion Q52( 1, 2, 3, -4 ); Dump(Q52); printf("%f\n", Q51^Q52 ); } { printf("\n=== 6 =============================================\n"); CQuaternion Q61( 1, 2, 3, 4 ); Dump(Q61); CQuaternion Q62( 5, 6, 7, 8 ); Dump(Q62); Dump( Q61 + Q62 ); Dump( Q61 - Q62 ); Dump( Q61 += Q62 ); Dump( Q61 -= Q62 ); } { printf("\n=== 7 =============================================\n"); CQuaternion Q71( 1, 2, 3, 4 ); Q71.Normalize(); Dump(Q71); printf("%f\n",Q71.Length()); //CQuaternion Q72( 5, 6, 7, 8 ); //Q72.Normalize(); //Dump(Q72); //Dump( Q71 * Q72 ); CQuaternion Q73 = -Q71; Dump( Q73 ); printf("%f\n",Q73.Length()); CQuaternion Product = Q71 * Q73; Dump( Product ); printf("%f\n",Product.Length()); Dump( Q71*=Q73 ); } { printf("\n=== 8 =============================================\n"); CQuaternion Q8( CVector(0.0f,0.0f,1.0f), (float)CONST_PI_2 ); //CQuaternion Q8( CVector(0,0,1), CONST_PI ); Dump(Q8); CVector Src(1,0,0); CVector Dst = RotateVectorByQuaternion( Src, Q8 ); printf("%f %f %f\n",Dst.x,Dst.y,Dst.z); } { printf("\n=== 9 =============================================\n"); CQuaternion Q81( CVector(0,0,1), 0 ); Dump(Q81); CQuaternion Q82( CVector(0,0,1), CONST_PI ); Dump(Q82); for( float t=0.0f; t<1.0f; t+=0.1f ) { CQuaternion R = SLerp(Q81,Q82,t); Dump( R ); } } { printf("\n=== 10 ============================================\n"); CQuaternion Q10( CVector(0,0,1), CONST_PI_2 ); //CQuaternion Q10( CVector(0,0,1), CONST_PI ); Dump(Q10); CVector V; float A; Q10.ToAxisAngle( V, A ); printf("%f %f %f\n",V.x,V.y,V.z); printf("%f\n",A); CVector Src(1,0,0); CVector Dst1 = RotateVectorByQuaternion( Src, Q10 ); printf("%f %f %f\n",Dst1.x,Dst1.y,Dst1.z); CVector Dst11 = Src*Q10; printf("%f %f %f\n",Dst11.x,Dst11.y,Dst11.z); CMatrix M( Q10.ToMatrix() ); CVector Dst2 = Src*M; printf("%f %f %f\n",Dst2.x,Dst2.y,Dst2.z); CMatrix M3; M3.ConstructRotation( CVector(0,0,1), CONST_PI_2 ); CVector Dst3 = Src*M3; printf("%f %f %f\n",Dst3.x,Dst3.y,Dst3.z); CMatrix M4; M4.ConstructRotationZ( CONST_PI_2 ); CVector Dst4 = Src*M4; printf("%f %f %f\n",Dst4.x,Dst4.y,Dst4.z); } { printf("\n=== 11 =============================================\n"); CMatrix M11; M11.ConstructRotation( CVector(0.3f,-0.78f,-0.9f), 0.666 ); CQuaternion Q11 = CreateNonUnitQuaternionFromRotationMatrix( M11 ); Q11.Normalize(); CQuaternion Q111 = CreateUnitQuaternionFromRotationMatrix( M11 ); Q111.Normalize(); CVector V11( 0.0f, 0.0f, 1.0f ); CVector R1 = V11*M11; printf("%f %f %f\n",R1.x,R1.y,R1.z); CVector R2 = RotateVectorByQuaternion( V11, Q11 ); printf("%f %f %f\n",R2.x,R2.y,R2.z); CVector R3 = RotateVectorByQuaternion( V11, Q111 ); printf("%f %f %f\n",R3.x,R3.y,R3.z); } { printf("\n=== 12 =============================================\n"); CQuaternion Q1( CVector(1.0f,1.0f,1.0f), (float)CONST_PI_3 ); Q1.Normalize(); CQuaternion Q2( CVector(1.0f,1.0f,1.0f), (float)CONST_PI_3 ); Q2.Normalize(); CQuaternion Q3 = SLerp(Q1,Q2,0.5f); Dump(Q3); } }
csQuaternion csQuaternion::Squad (const csQuaternion & t1, const csQuaternion & t2, const csQuaternion & q, float t) const { return SLerp (q, t).SLerp (t1.SLerp (t2, t), 2.0f*t * (1.0f - t)); }
Vector CAOGenerator::RenderSceneFromPosition(Vector vecPosition, Vector vecDirection, CConversionFace* pRenderFace) { TUnimplemented(); CRenderingContext c(SMAKRenderer()); c.UseFrameBuffer(&m_oRenderFB); // Bring it away from its poly so that the camera never clips around behind it. // Adds .001 because of a bug where GL for some reason won't show the faces unless I do that. Vector vecEye = vecPosition + (vecDirection + Vector(.001f, .001f, .001f)) * 0.1f; c.SetViewport(Rect(m_iRPVX, m_iRPVY, m_iRPVW, m_iRPVH)); c.SetProjection(Matrix4x4::ProjectPerspective(120.0f, 1, 0.01f, 100.0f)); c.SetView(Matrix4x4::ConstructCameraView(vecEye, vecDirection, Vector(0, 1, 0))); c.ClearColor(); c.ClearDepth(); for (size_t i = 0; i < m_aiSceneMaterials.size(); i++) { TAssert(i < SMAKWindow()->GetMaterials().size()); if (i >= SMAKWindow()->GetMaterials().size()) break; if (!m_aiSceneMaterialVerts[i]) continue; c.UseMaterial(SMAKWindow()->GetMaterials()[i]); c.BeginRenderVertexArray(m_aiSceneMaterials[i]); c.SetPositionBuffer((size_t)0, 5*sizeof(float)); c.SetTexCoordBuffer((size_t)3*sizeof(float), 5*sizeof(float)); c.EndRenderVertexArray(m_aiSceneMaterialVerts[i]); } c.Finish(); #ifdef AO_DEBUG DebugRenderSceneLookAtPosition(vecPosition, vecDirection, pRenderFace); glFinish(); #endif c.ReadPixels(m_iRPVX, m_iRPVY, m_iRPVW, m_iRPVH, m_pvecPixels); Vector vecShadowColor; float flTotal = 0; for (size_t p = 0; p < m_iRPVW*m_iRPVH*m_iPixelDepth; p++) { float flColumn = fmod((float)p / (float)m_iPixelDepth, (float)m_iRPVW); Vector vecUV(flColumn / m_iRPVW, (float)(p / m_iPixelDepth / m_iRPVW) / m_iRPVH, 0); Vector vecUVCenter(0.5f, 0.5f, 0); // Weight the pixel based on its distance to the center. // With the huge FOV that we work with, polygons to the // outside are huge on the screen. float flWeight = (0.5f-(vecUV - vecUVCenter).Length())*2.0f; if (flWeight <= 0.1) continue; // Pixels in the center of the screen are much, much more important. flWeight = SLerp(flWeight, 0.2f); Vector vecPixel(m_pvecPixels[p].x, m_pvecPixels[p].y, m_pvecPixels[p].z); vecShadowColor += vecPixel * flWeight; flTotal += flWeight; } vecShadowColor /= flTotal; return vecShadowColor; }