//------------------------------------------------------------------------------- // @ IvQuat::Set() //------------------------------------------------------------------------------- // Set quaternion based on axis-angle //------------------------------------------------------------------------------- void IvQuat::Set( const IvVector3& axis, float angle ) { // if axis of rotation is zero vector, just set to identity quat float length = axis.LengthSquared(); if ( ::IsZero( length ) ) { Identity(); return; } // take half-angle angle *= 0.5f; float sintheta, costheta; IvSinCos(angle, sintheta, costheta); float scaleFactor = sintheta/IvSqrt( length ); w = costheta; x = scaleFactor * axis.x; y = scaleFactor * axis.y; z = scaleFactor * axis.z; } // End of IvQuat::Set()
//------------------------------------------------------------------------------- // @ IvQuat::Set() //------------------------------------------------------------------------------- // Set quaternion based on fixed angles //------------------------------------------------------------------------------- void IvQuat::Set( float zRotation, float yRotation, float xRotation ) { zRotation *= 0.5f; yRotation *= 0.5f; xRotation *= 0.5f; // get sines and cosines of half angles float Cx, Sx; IvSinCos(xRotation, Sx, Cx); float Cy, Sy; IvSinCos(yRotation, Sy, Cy); float Cz, Sz; IvSinCos(zRotation, Sz, Cz); // multiply it out w = Cx*Cy*Cz - Sx*Sy*Sz; x = Sx*Cy*Cz + Cx*Sy*Sz; y = Cx*Sy*Cz - Sx*Cy*Sz; z = Cx*Cy*Sz + Sx*Sy*Cx; } // End of IvQuat::Set()
//------------------------------------------------------------------------------- // @ Player::CreateCylinder() //------------------------------------------------------------------------------- // Create vertex arrays for a cylinder centered around the origin //------------------------------------------------------------------------------- void Player::CreateCylinder() { // Creates a grid of points, shaped into a cylinder. In order to avoid a // texturing anomaly, we cannot simply share the vertical seam edge vertices // They must be duplicated; one copy must have a U-coord of 0.0, the other a // U-coord of 1.0f const unsigned int steps = 32; mCylinderVerts = IvRenderer::mRenderer->GetResourceManager()->CreateVertexBuffer( kTCPFormat, (steps + 1) * steps, nullptr, kDefaultUsage); IvTCPVertex* tempVerts0 = (IvTCPVertex*)(mCylinderVerts->BeginLoadData()); // temporary pointers that can be stepped along the arrays const float phiIncrement = kPI / (steps - 1); const float thetaIncrement = kTwoPI / steps; unsigned int i,j; // A double loop, walking around and down the cylinder for (j = 0; j <= steps; j++) { float theta = thetaIncrement * j; float u = j / (float)steps; float sinTheta, cosTheta; IvSinCos(theta, sinTheta, cosTheta); for (i = 0; i < steps; i++) { float phi = -kHalfPI + phiIncrement * i; float v = i / (float)(steps - 1); if (i == 0) { tempVerts0->position = IvVector3(0.0f, 0.0f, -mRadius); } else if (i == (steps - 1)) { tempVerts0->position = IvVector3(0.0f, 0.0f, mRadius); } else { tempVerts0->position = IvVector3(mRadius * cosTheta, mRadius * sinTheta, mRadius * IvSin(phi)); } tempVerts0->texturecoord = IvVector2(u, v); tempVerts0->color.mAlpha = tempVerts0->color.mRed = tempVerts0->color.mGreen = tempVerts0->color.mBlue = 255; tempVerts0++; } } mCylinderVerts->EndLoadData(); // Create index arrays - just a 32x31-quad mesh of triangles // Each of the 32 strips has 31 * 2 triangles plus two dummy indices // This means that there are 31 * 2 + 2 + 2 (two extra to start the // strip, and two extra to end the previous strip) indices in each // strip, although we can avoid two indices in the first strip, as // there is no previous strip to be ended in that case. Thus, // 64 + 66 * 31 indices for the entire cylinder unsigned int cylinderIndexCount = steps * 2 + (steps - 1) * (steps * 2 + 2); mCylinderIndices = IvRenderer::mRenderer->GetResourceManager()->CreateIndexBuffer( cylinderIndexCount, nullptr, kDefaultUsage); UInt32* tempIndices = (UInt32*)mCylinderIndices->BeginLoadData(); for (j = 0; j < steps; j++) { UInt32 baseIndex0 = steps * j; UInt32 baseIndex1 = steps * (j + 1); // restart the strip by doubling the last and next indices if (j != 0) { *(tempIndices++) = tempIndices[-1]; *(tempIndices++) = baseIndex0; } unsigned int i; for (i = 0; i < steps; i++) { *(tempIndices++) = baseIndex0; *(tempIndices++) = baseIndex1; baseIndex0++; baseIndex1++; } } mCylinderIndices->EndLoadData(); } // End of Player::CreateCylinder()
//------------------------------------------------------------------------------- // @ Player::CreateSphere() //------------------------------------------------------------------------------- // Create vertex arrays for a sphere centered around the origin //------------------------------------------------------------------------------- void Player::CreateSphere() { // Creates a grid of points, shaped into a sphere. This is not an // efficient way to create a sphere (the verts are not evenly distributed), // but it shows how to set up arrays of vertices and normals const unsigned int steps = 32; const unsigned int verts = steps * steps; mSphereVerts = IvRenderer::mRenderer->GetResourceManager()->CreateVertexBuffer( kCPFormat, verts, nullptr, kDefaultUsage); // temporary pointers that can be stepped along the arrays IvCPVertex* tempVerts = (IvCPVertex*)(mSphereVerts->BeginLoadData()); // A double loop, walking around and down the sphere const float phiIncrement = kPI / (steps - 1); const float thetaIncrement = kTwoPI / steps; unsigned int j; for (j = 0; j < steps; j++) { float theta = thetaIncrement * j; float sinTheta, cosTheta; IvSinCos(theta, sinTheta, cosTheta); unsigned int i; for (i = 0; i < steps; i++) { float phi = phiIncrement * i - kHalfPI; float sinPhi, cosPhi; IvSinCos(phi, sinPhi, cosPhi); tempVerts->position.x = mRadius * cosTheta * cosPhi; tempVerts->position.y = mRadius * sinTheta * cosPhi; tempVerts->position.z = mRadius * sinPhi; tempVerts->color.mAlpha = 255; tempVerts->color.mRed = 255; tempVerts->color.mGreen = 255; tempVerts->color.mBlue = 255; tempVerts++; } } mSphereVerts->EndLoadData(); // Create index arrays - just a 32x31-quad mesh of triangles // Each of the 32 strips has 31 * 2 triangles plus two dummy indices // This means that there are 31 * 2 + 2 + 2 (two extra to start the // strip, and two extra to end the previous strip) indices in each // strip, although we can avoid two indices in the first strip, as // there is no previous strip to be ended in that case. Thus, // 64 + 66 * 31 indices for the entire sphere const unsigned int sphereIndexCount = steps * 2 + (steps - 1) * (steps * 2 + 2); mSphereIndices = IvRenderer::mRenderer->GetResourceManager()-> CreateIndexBuffer(sphereIndexCount, nullptr, kDefaultUsage); unsigned int* tempIndices = (unsigned int*)(mSphereIndices->BeginLoadData()); for (j = 0; j < steps; j++) { unsigned int baseIndex0 = steps * j; unsigned int baseIndex1 = steps * ((j + 1) % steps); // restart the strip by doubling the last and next indices if (j != 0) { *(tempIndices++) = tempIndices[-1]; *(tempIndices++) = baseIndex0; } unsigned int i; for (i = 0; i < steps; i++) { *(tempIndices++) = baseIndex0; *(tempIndices++) = baseIndex1; baseIndex0++; baseIndex1++; } } mSphereIndices->EndLoadData(); } // End of Player::CreateSphere()