void MainLoop() { Layer[0] = new VRLayer(Session); while (HandleMessages()) { //Need to check we're visible, before proceeding with velocity changes, //otherwise it does this a lot of times, and we //end up miles away from our start point from the sheer number of iterations. ovrSessionStatus sessionStatus; ovr_GetSessionStatus(Session, &sessionStatus); if (sessionStatus.IsVisible) { // Take out manual yaw rotation (leaving button move for now) ActionFromInput(1, false); ovrTrackingState trackingState = Layer[0]->GetEyePoses(); // Set various control methods into camera MainCam->Pos = XMVectorAdd(MainCam->Pos, FindVelocityFromTilt(this, Layer[0], &trackingState)); MainCam->Pos = XMVectorSet(XMVectorGetX(MainCam->Pos), GetAccelJumpPosY(this, &trackingState), XMVectorGetZ(MainCam->Pos), 0); MainCam->Rot = GetAutoYawRotation(Layer[0]); // If tap side of Rift, then fire a bullet bool singleTap = WasItTapped(trackingState.HeadPose.LinearAcceleration); static XMVECTOR bulletPos = XMVectorZero(); static XMVECTOR bulletVel = XMVectorZero(); if (singleTap) { XMVECTOR eye0 = ConvertToXM(Layer[0]->EyeRenderPose[0].Position); XMVECTOR eye1 = ConvertToXM(Layer[0]->EyeRenderPose[1].Position); XMVECTOR midEyePos = XMVectorScale(XMVectorAdd(eye0, eye1), 0.5f); XMVECTOR totalRot = XMQuaternionMultiply(ConvertToXM(Layer[0]->EyeRenderPose[0].Orientation), MainCam->Rot); XMVECTOR posOfOrigin = XMVectorAdd(MainCam->Pos, XMVector3Rotate(midEyePos, MainCam->Rot)); XMVECTOR unitDirOfMainCamera = XMVector3Rotate(XMVectorSet(0, 0, -1, 0), totalRot); bulletPos = XMVectorAdd(posOfOrigin, XMVectorScale(unitDirOfMainCamera, 2.0f)); bulletVel = XMVectorScale(unitDirOfMainCamera, 0.3f); } // Move missile on, and set its position bulletPos = XMVectorAdd(bulletPos, bulletVel); XMStoreFloat3(&RoomScene->Models[1]->Pos, bulletPos); for (int eye = 0; eye < 2; ++eye) { Layer[0]->RenderSceneToEyeBuffer(MainCam, RoomScene, eye); } Layer[0]->PrepareLayerHeader(); DistortAndPresent(1); } } }
void MainLoop() { Layer[0] = new VRLayer(HMD); while (HandleMessages()) { // We turn off yaw to keep the case simple ActionFromInput(1, false); Layer[0]->GetEyePoses(); // Find perturbation of position from point 1m in front of camera XMVECTOR eye0 = ConvertToXM(Layer[0]->EyeRenderPose[0].Position); XMVECTOR eye1 = ConvertToXM(Layer[0]->EyeRenderPose[1].Position); XMVECTOR perturb = XMVectorScale(XMVectorAdd(eye0, eye1), 0.5f); // Calculate velocity from this const float sensitivity = 0.2f; XMVECTOR vel = XMVectorScale(XMVectorSet(-XMVectorGetX(perturb), 0, -XMVectorGetZ(perturb), 0), sensitivity); // Add velocity to camera MainCam->Pos = XMVectorAdd(MainCam->Pos, vel); for (int eye = 0; eye < 2; ++eye) { Layer[0]->RenderSceneToEyeBuffer(MainCam, RoomScene, eye); } Layer[0]->PrepareLayerHeader(); DistortAndPresent(1); } }
VOID DebugDraw::DrawRay( const XMFLOAT3& Origin, const XMFLOAT3& Direction, BOOL bNormalize, D3DCOLOR Color ) { MeshVertexP verts[3]; memcpy( &verts[0], &Origin, 3 * sizeof( FLOAT ) ); XMVECTOR RayOrigin = XMLoadFloat3( &Origin ); XMVECTOR RayDirection = XMLoadFloat3( &Direction ); XMVECTOR NormDirection = XMVector3Normalize( RayDirection ); if( bNormalize ) RayDirection = NormDirection; XMVECTOR PerpVector; XMVECTOR CrossVector = XMVectorSet( 0, 1, 0, 0 ); PerpVector = XMVector3Cross( NormDirection, CrossVector ); if( XMVector3Equal( XMVector3LengthSq( PerpVector ), XMVectorSet( 0, 0, 0, 0 ) ) ) { CrossVector = XMVectorSet( 0, 0, 1, 0 ); PerpVector = XMVector3Cross( NormDirection, CrossVector ); } PerpVector = XMVector3Normalize( PerpVector ); XMStoreFloat3( ( XMFLOAT3* )&verts[1], XMVectorAdd( RayDirection, RayOrigin ) ); PerpVector = XMVectorScale( PerpVector, 0.0625f ); NormDirection = XMVectorScale( NormDirection, -0.25f ); RayDirection = XMVectorAdd( PerpVector, RayDirection ); RayDirection = XMVectorAdd( NormDirection, RayDirection ); XMStoreFloat3( ( XMFLOAT3* )&verts[2], XMVectorAdd( RayDirection, RayOrigin ) ); SimpleShaders::SetDeclPos(); SimpleShaders::BeginShader_Transformed_ConstantColor( g_matViewProjection, Color ); g_pd3dDevice->DrawPrimitiveUP( D3DPT_LINESTRIP, 2, ( const VOID* )verts, sizeof( MeshVertexP ) ); SimpleShaders::EndShader(); }
void GuardianSystemDemo::UpdateObjectsCollisionWithBoundary(float elapsedTimeSec) { if (mGlobalTimeSec < 1.0f) return; // Start update after 1s for (int32_t i = 0; i < mDynamicScene.numModels; ++i) { XMFLOAT3 newPosition; XMVECTOR newPositionVec = XMVectorAdd(mObjPosition[i], XMVectorScale(mObjVelocity[i], elapsedTimeSec)); XMStoreFloat3(&newPosition, newPositionVec); // Test object collision with boundary ovrBoundaryTestResult test; ovr_TestBoundaryPoint(mSession, (ovrVector3f*)&newPosition.x, ovrBoundary_Outer, &test); // Collides with surface at 2cm if (test.ClosestDistance < 0.02f) { XMVECTOR surfaceNormal = XMVectorSet(test.ClosestPointNormal.x, test.ClosestPointNormal.y, test.ClosestPointNormal.z, 0.0f); mObjVelocity[i] = XMVector3Reflect(mObjVelocity[i], surfaceNormal); newPositionVec = XMVectorAdd(mObjPosition[i], XMVectorScale(mObjVelocity[i], elapsedTimeSec)); XMStoreFloat3(&newPosition, newPositionVec); } mObjPosition[i] = newPositionVec; mDynamicScene.Models[i]->Pos = newPosition; } }
// Converts from barycentric to cartesian coordinates XMVECTOR BarycentricToCartesian(const XMFLOAT3& r, FXMVECTOR pos1, FXMVECTOR pos2, FXMVECTOR pos3) { XMVECTOR rvec; rvec = XMVectorScale(pos1, r.x); rvec += XMVectorScale(pos2, r.y); rvec += XMVectorScale(pos3, r.z); return rvec; }
HRESULT SceneObjectGrid::InitializeMeshStreams(__in ISceneObjectMesh* pMesh, __in UINT resolution, __in FLOAT size, __in XMFLOAT4 color) { if (resolution == 0 || size <= 0 || pMesh == NULL) { return E_INVALIDARG; } XMVECTOR xAxis = XMVectorScale(XMLoadFloat3(&XMFLOAT3(1.0f, 0.0f, 0.0f)), size); XMVECTOR yAxis = XMVectorScale(XMLoadFloat3(&XMFLOAT3(0.0f, 0.0f, 1.0f)), size); XMFLOAT3 origin(0.0f, 0.0f, 0.0f); return InitializeMeshStreams(pMesh, xAxis, yAxis, origin, resolution, resolution, color); }
void Cloth::calcForces() { double currentTime = getCounter(); for (int i = 0; i < numStructural; i++) { structuralSprings[i].calcSpringForce(); } for (int i = 0; i < numShear; i++) { shearSprings[i].calcSpringForce(); } for (int i = 0; i < numFlexion; i++) { flexionSprings[i].calcSpringForce(); } timeSpentCalculatingInternalForce += getCounter() - currentTime; currentTime = getCounter(); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { particles[(i * columns) + j].addForce(XMVectorScale(GRAVITY, particles[(i * columns) + j].getMass())); if (currentScenario == FLAG) { if (i < rows - 1 && j < columns - 1) { addWindForce(particles[(i * columns) + j], particles[(i * columns) + j + 1], particles[((i + 1) * columns) + j]); addWindForce(particles[((i + 1) * columns) + j], particles[(i * columns) + j + 1], particles[((i + 1) * columns) + j + 1]); } } } } timeSpentCalculatingExternalForce += getCounter() - currentTime; }
_Use_decl_annotations_ void BspCompiler::SplitEdge(const Vertex& v0, const Vertex& v1, const XMFLOAT4& plane, Vertex* v) { XMFLOAT3 vv0 = v0.Position; XMFLOAT3 vv1 = v1.Position; float d0 = DistToPlane(plane, vv0); XMVECTOR sub = XMVectorSubtract(XMLoadFloat3(&vv1), XMLoadFloat3(&vv0)); XMVECTOR dir = XMVector3Normalize(sub); XMVECTOR n = XMLoadFloat4(&plane); float d = d0; if (d > 0) { n = XMVectorNegate(n); } else if (d < 0) { d = -d; } else { assert(false); } float x = d / XMVectorGetX(XMVector3Dot(n, dir)); XMStoreFloat3(&v->Position, XMVectorAdd(XMLoadFloat3(&vv0), XMVectorScale(dir, x))); }
_Use_decl_annotations_ void KdTreeCompiler2::SplitEdge(_In_ const StaticGeometryVertex& v0, _In_ const StaticGeometryVertex& v1, uint32_t axis, float value, _Out_ StaticGeometryVertex* v) { XMFLOAT3 vv0 = v0.Position; XMFLOAT3 vv1 = v1.Position; float d0 = *(&vv0.x + axis) - value; XMVECTOR sub = XMVectorSubtract(XMLoadFloat3(&vv1), XMLoadFloat3(&vv0)); XMVECTOR dir = XMVector3Normalize(sub); XMVECTOR n = XMLoadFloat3(&_normals[axis]); float d = d0; if (d > 0) { n = XMVectorNegate(n); } else if (d < 0) { d = -d; } else { assert(false); } float x = d / XMVectorGetX(XMVector3Dot(n, dir)); XMStoreFloat3(&v->Position, XMVectorAdd(XMLoadFloat3(&vv0), XMVectorScale(dir, x))); }
void ComputeAabbFromOrientedBox(SAxisAlignedBox* aabb, const SOrientedBox& obb) { XMFLOAT3 points[8]; XMVECTOR bu = XMLoadFloat3(&obb.Axis[0]); XMVECTOR bv = XMLoadFloat3(&obb.Axis[1]); XMVECTOR bw = XMLoadFloat3(&obb.Axis[2]); bu = XMVectorScale(bu, obb.Extents.x); bv = XMVectorScale(bv, obb.Extents.y); bw = XMVectorScale(bw, obb.Extents.z); XMStoreFloat3(&points[0], bu + bv + bw); XMStoreFloat3(&points[1], bu + bv - bw); XMStoreFloat3(&points[2], bu - bv + bw); XMStoreFloat3(&points[3], bu - bv - bw); XMStoreFloat3(&points[4], -bu + bv + bw); XMStoreFloat3(&points[5], -bu + bv - bw); XMStoreFloat3(&points[6], -bu - bv + bw); XMStoreFloat3(&points[7], -bu - bv - bw); XMFLOAT3 maxPoint(-FLT_MAX, -FLT_MAX, -FLT_MAX); XMFLOAT3 minPoint(FLT_MAX, FLT_MAX, FLT_MAX); for (u32 i = 0; i < 8; i++) { XMFLOAT3 point = points[i]; if (point.x > maxPoint.x) maxPoint.x = point.x; if (point.x < minPoint.x) minPoint.x = point.x; if (point.y > maxPoint.y) maxPoint.y = point.y; if (point.y < minPoint.y) minPoint.y = point.y; if (point.z > maxPoint.z) maxPoint.z = point.z; if (point.z < minPoint.z) minPoint.z = point.z; } aabb->Center = obb.Center; aabb->Extents = XMFLOAT3((maxPoint.x - minPoint.x) * 0.5f, (maxPoint.y - minPoint.y) * 0.5f, (maxPoint.z - minPoint.z) * 0.5f); }
void BatchRenderer::DrawGrid( const Vec3D& XAxis, const Vec3D& YAxis, const Vec3D& Origin, int iXDivisions, int iYDivisions, const FColor& color ) { // HRESULT hr; iXDivisions = Max( 1, iXDivisions ); iYDivisions = Max( 1, iYDivisions ); // build grid geometry // INT iLineCount = iXDivisions + iYDivisions + 2; //assert( (2*iLineCount) <= MAX_VERTS ); XMVECTOR vX = XMLoadFloat3( &as_float3(XAxis) ); XMVECTOR vY = XMLoadFloat3( &as_float3(YAxis) ); XMVECTOR vOrigin = XMLoadFloat3( &as_float3(Origin) ); for( INT i = 0; i <= iXDivisions; i++ ) { FLOAT fPercent = ( FLOAT )i / ( FLOAT )iXDivisions; fPercent = ( fPercent * 2.0f ) - 1.0f; XMVECTOR vScale = XMVectorScale( vX, fPercent ); vScale = XMVectorAdd( vScale, vOrigin ); XMVECTOR vA, vB; vA = XMVectorSubtract( vScale, vY ); vB = XMVectorAdd( vScale, vY ); DrawLine3D( as_vec4(vA).ToVec3(), as_vec4(vB).ToVec3(), color, color ); } // INT iStartIndex = ( iXDivisions + 1 ) * 2; for( INT i = 0; i <= iYDivisions; i++ ) { FLOAT fPercent = ( FLOAT )i / ( FLOAT )iYDivisions; fPercent = ( fPercent * 2.0f ) - 1.0f; XMVECTOR vScale = XMVectorScale( vY, fPercent ); vScale = XMVectorAdd( vScale, vOrigin ); XMVECTOR vA, vB; vA = XMVectorSubtract( vScale, vX ); vB = XMVectorAdd( vScale, vX ); DrawLine3D( as_vec4(vA).ToVec3(), as_vec4(vB).ToVec3(), color, color ); } }
/** * Code available for download at http://cg.alexandra.dk/?p=147 used as reference for addWindForce */ void Cloth::addWindForce(Particle& p1, Particle& p2, Particle& p3) { XMVECTOR pos1, pos2, pos3, temp1, temp2, normal, force; pos1 = p1.getPosition(); pos2 = p2.getPosition(); pos3 = p3.getPosition(); temp1 = XMVectorSubtract(pos2, pos1); temp2 = XMVectorSubtract(pos3, pos1); normal = XMVector3Cross(temp1, temp2); temp1 = XMVector3Normalize(normal); force = XMVectorScale(normal, XMVectorScale(XMVector3Dot(temp1, windDirection), windConstant).m128_f32[0]); p1.addForce(force); p2.addForce(force); p3.addForce(force); }
void BatchRenderer::DrawRay( const XMFLOAT3& Origin, const XMFLOAT3& Direction, BOOL bNormalize, const FColor& Color ) { XMFLOAT3 verts[3]; memcpy( &verts[0], &Origin, 3 * sizeof( FLOAT ) ); XMVECTOR RayOrigin = XMLoadFloat3( &Origin ); XMVECTOR RayDirection = XMLoadFloat3( &Direction ); XMVECTOR NormDirection = XMVector3Normalize( RayDirection ); if( bNormalize ) RayDirection = NormDirection; XMVECTOR PerpVector; XMVECTOR CrossVector = XMVectorSet( 0, 1, 0, 0 ); PerpVector = XMVector3Cross( NormDirection, CrossVector ); if( XMVector3Equal( XMVector3LengthSq( PerpVector ), XMVectorSet( 0, 0, 0, 0 ) ) ) { CrossVector = XMVectorSet( 0, 0, 1, 0 ); PerpVector = XMVector3Cross( NormDirection, CrossVector ); } PerpVector = XMVector3Normalize( PerpVector ); XMStoreFloat3( ( XMFLOAT3* )&verts[1], XMVectorAdd( RayDirection, RayOrigin ) ); PerpVector = XMVectorScale( PerpVector, 0.0625f ); NormDirection = XMVectorScale( NormDirection, -0.25f ); RayDirection = XMVectorAdd( PerpVector, RayDirection ); RayDirection = XMVectorAdd( NormDirection, RayDirection ); XMStoreFloat3( ( XMFLOAT3* )&verts[2], XMVectorAdd( RayDirection, RayOrigin ) ); // Copy to vertex buffer assert( 3 <= MAX_VERTS ); XMFLOAT3* pVerts = NULL; HRESULT hr; V( g_pVB->Lock( 0, 0, (void**)&pVerts, D3DLOCK_DISCARD ) ) memcpy( pVerts, verts, sizeof(verts) ); V( g_pVB->Unlock() ) // Draw ray D3DXCOLOR clr = Color; g_pEffect9->SetFloatArray( g_Color, clr, 4 ); g_pEffect9->CommitChanges(); pd3dDevice->DrawPrimitive( D3DPT_LINESTRIP, 0, 2 ); }
VOID DebugDraw::DrawGrid( const XMFLOAT3& XAxis, const XMFLOAT3& YAxis, const XMFLOAT3& Origin, INT iXDivisions, INT iYDivisions, D3DCOLOR Color ) { iXDivisions = max( 1, iXDivisions ); iYDivisions = max( 1, iYDivisions ); // build grid geometry INT iLineCount = iXDivisions + iYDivisions + 2; XMFLOAT3* pLines = new XMFLOAT3[ 2 * iLineCount ]; XMVECTOR vX = XMLoadFloat3( &XAxis ); XMVECTOR vY = XMLoadFloat3( &YAxis ); XMVECTOR vOrigin = XMLoadFloat3( &Origin ); for( INT i = 0; i <= iXDivisions; i++ ) { FLOAT fPercent = ( FLOAT )i / ( FLOAT )iXDivisions; fPercent = ( fPercent * 2.0f ) - 1.0f; XMVECTOR vScale = XMVectorScale( vX, fPercent ); vScale = XMVectorAdd( vScale, vOrigin ); XMStoreFloat3( &pLines[ ( i * 2 ) ], XMVectorSubtract( vScale, vY ) ); XMStoreFloat3( &pLines[ ( i * 2 ) + 1 ], XMVectorAdd( vScale, vY ) ); } INT iStartIndex = ( iXDivisions + 1 ) * 2; for( INT i = 0; i <= iYDivisions; i++ ) { FLOAT fPercent = ( FLOAT )i / ( FLOAT )iYDivisions; fPercent = ( fPercent * 2.0f ) - 1.0f; XMVECTOR vScale = XMVectorScale( vY, fPercent ); vScale = XMVectorAdd( vScale, vOrigin ); XMStoreFloat3( &pLines[ ( i * 2 ) + iStartIndex ], XMVectorSubtract( vScale, vX ) ); XMStoreFloat3( &pLines[ ( i * 2 ) + 1 + iStartIndex ], XMVectorAdd( vScale, vX ) ); } // draw grid SimpleShaders::SetDeclPos(); SimpleShaders::BeginShader_Transformed_ConstantColor( g_matViewProjection, Color ); g_pd3dDevice->DrawPrimitiveUP( D3DPT_LINELIST, iLineCount, pLines, sizeof( XMFLOAT3 ) ); SimpleShaders::EndShader(); delete[] pLines; }
void World::moveEntity( WorldEntity* entity, XMVECTOR moveVec, float dist ) { //Try to move the entity in the world along the moveVec XMVECTOR pos = XMLoadFloat4( &entity->getPosition() ); XMVECTOR wall = XMVectorZero(); XMVECTOR vel = XMVectorScale( moveVec, dist ); XMVECTOR desiredPos; XMFLOAT4 check; XMFLOAT4 negativeCheck; int checks = 0; int maxChecks = 10; float saveDist = dist; float distInterval = dist / static_cast<float>(maxChecks); XMStoreFloat4( &check, XMVector3Length(moveVec) ); //Don't bother doing anything if there is no movement direction if( check.x <= 0.0f ){ return; } //Check collision at where we plan to be if( checkEntityCollision( entity, pos, &wall ) ){ XMStoreFloat4( &check, wall ); XMStoreFloat4( &negativeCheck, vel ); //Check the negative bit of the x and z values and see if they are equal, if they are, then stop movement bool negativeXWall = *(int*)(&check.x) < 0; bool negativeZWall = *(int*)(&check.z) < 0; bool negativeXVel = *(int*)(&negativeCheck.x) < 0; bool negativeZVel = *(int*)(&negativeCheck.z) < 0; //If we are not in a corner, collide with the wall, otherwise stop movement if(check.w <= 1.5f || ( negativeXWall != negativeXVel || negativeZWall != negativeZVel ) ){ XMVECTOR invWall = XMVectorNegate( wall ); wall = wall * XMVector3Length( moveVec * invWall ); vel = (moveVec - wall) * dist; }else{ vel = XMVectorZero(); } } desiredPos = pos + vel; XMStoreFloat4( &entity->getPosition(), desiredPos ); }
void CMesh::Setup(unsigned int vbovertices) { m_nVBOVertices = vbovertices; _ASSERT_EXPR_A(!(error = glGetError()), (const char*)gluErrorString(error)); glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBOVertices); _ASSERT_EXPR_A(!(error = glGetError()), (const char*)gluErrorString(error)); std::vector<XMFLOAT3> data(polygons.size() * VERTICESPERPOLY); for (size_t i = 0, dst = 0; i < polygons.size(); ++i) { data[dst++] = vertices[polygons[i].v[0]]; data[dst++] = vertices[polygons[i].v[1]]; data[dst++] = vertices[polygons[i].v[2]]; } glBufferDataARB(GL_ARRAY_BUFFER_ARB, data.size() * sizeof(XMFLOAT3), &data.front(), GL_STATIC_DRAW_ARB); _ASSERT_EXPR_A(!(error = glGetError()), (const char*)gluErrorString(error)); // Normals... glGenBuffersARB(1, &m_nVBONormals); _ASSERT_EXPR_A(!(error = glGetError()), (const char*)gluErrorString(error)); std::vector<XMFLOAT3> normals(polygons.size() * VERTICESPERPOLY); for (size_t i = 0, dst = 0; i < polygons.size(); ++i) { // TODO:: ccw hack XMFLOAT3 n; XMStoreFloat3(&n, XMVectorScale(XMLoadFloat3(&normalsV[i].n[0]), -1.f)); normals[dst++] = n; XMStoreFloat3(&n, XMVectorScale(XMLoadFloat3(&normalsV[i].n[1]), -1.f)); normals[dst++] = n; XMStoreFloat3(&n, XMVectorScale(XMLoadFloat3(&normalsV[i].n[2]), -1.f)); normals[dst++] = n; } glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBONormals); _ASSERT_EXPR_A(!(error = glGetError()), (const char*)gluErrorString(error)); glBufferDataARB(GL_ARRAY_BUFFER_ARB, normals.size() * sizeof(XMFLOAT3), &normals.front(), GL_STATIC_DRAW_ARB); _ASSERT_EXPR_A(!(error = glGetError()), (const char*)gluErrorString(error)); }
void RayTraceDataGenerator::GenerateRaytraceResult(int width, int height,float scale, XMFLOAT4 loc, int neardistance, int maxdepth, XMFLOAT4 n, XMFLOAT4 up, void(*CallbackFunc)(int x, int y, const int& TexType, const XMFLOAT4& loc, const XMFLOAT4& n,const float& depth, void* arg), void* arg) { XMVECTOR v_ori = XMLoadFloat4(&loc); XMVECTOR v_center=XMLoadFloat4(&loc); XMVECTOR v_n = XMLoadFloat4(&n); XMVECTOR v_up = XMVector3Normalize(XMLoadFloat4(&up)); v_center = XMVectorAdd(v_center, XMVectorScale(v_n, neardistance)); XMVECTOR v_dir_x = XMVector3Cross(v_n, v_up); XMVECTOR v_dir_y = XMVector3Cross(v_n, v_dir_x); XMVECTOR v_current = XMVectorAdd(v_center, XMVectorScale(v_dir_x, -scale*width*0.5)); XMVECTOR v_ret_n; XMVECTOR v_ret_loc; //XMFLOAT4 v_unpacked; XMFLOAT4 v_ret_unpack_n; XMFLOAT4 v_ret_unpack_loc; XMVECTOR v_corner1; XMVECTOR v_corner2; bool result; float f_ret_depth; v_current = XMVectorAdd(v_current, XMVectorScale(v_dir_y, -scale*height*0.5)); v_corner1 = v_current; v_corner2 = XMVectorAdd(v_current, XMVectorScale(v_dir_y, +scale*height*1.0)); v_corner2 = XMVectorAdd(v_corner2, XMVectorScale(v_dir_x, +scale*width*1.0)); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) {//XMVector3Normalize(XMVectorSubtract(v_current, v_ori)) result = CalcIntersect(v_current, v_n, &v_ret_n, &v_ret_loc, &f_ret_depth); if (result) { XMStoreFloat4(&v_ret_unpack_loc,v_ret_loc); XMStoreFloat4(&v_ret_unpack_n, v_ret_n); CallbackFunc(i, j, GetLocInfo((int)v_ret_unpack_loc.x, (int)v_ret_unpack_loc.y, (int)v_ret_unpack_loc.z), v_ret_unpack_loc, v_ret_unpack_n, f_ret_depth, arg); } else { v_ret_unpack_n.x = v_ret_unpack_n.y = v_ret_unpack_n.z = -1; v_ret_unpack_loc.x = v_ret_unpack_loc.y = v_ret_unpack_loc.z = -1; f_ret_depth = -1; CallbackFunc(i, j, -1, v_ret_unpack_loc, v_ret_unpack_n, f_ret_depth, arg); } v_current = XMVectorAdd(v_current, XMVectorScale(v_dir_y, scale)); } v_current = XMVectorAdd(v_current, XMVectorScale(v_dir_x, scale)); } }
void Ball::Reset() { FLOAT angle; //set random angle for initial impulse srand((unsigned int)time(NULL)); angle = ((FLOAT)rand() / RAND_MAX ) * 360; if (angle > 45 && angle < 135) { angle -= 90; } else if (angle > 225 && angle < 315) { angle -= 90; } angle *= (XM_2PI / 360); //initialize position to screen center ( bounding box center) XMFLOAT2 center; center.x = (system->table.left + system->table.right)/2.0f; center.y = (system->table.top + system->table.bottom)/2.0f; center.x -= radius; center.y -= radius; impulse = XMVectorSet(cos(angle),sin(angle),0,0); impulse = XMVectorScale(impulse,37000); position = XMVectorSet(center.x,center.y,0,0); object_time = 0; }
XMFLOAT2 Skeleton::CalculatePosition2D(std::vector<XMFLOAT2> &jointPositions2D, std::vector<float> &jointRotations2D, XMFLOAT2 &endEffectorPosition) { if (jointPositions2D.size() < 2) return XMFLOAT2(0.f, 0.f); // Walk through each link and apply the transform for (size_t i = 0; i < jointPositions2D.size() - 1; ++i) { float sumRotations = 0.f; for (size_t j = 0; j <= i; ++j) { sumRotations += jointRotations2D[j]; } XMFLOAT2 direction; direction.x = cos(sumRotations); direction.y = sin(sumRotations); XMStoreFloat2(&jointPositions2D[i + 1], XMVectorAdd(XMLoadFloat2(&jointPositions2D[i]), XMVectorScale(XMLoadFloat2(&direction), m_IKLinkLength))); } float sumRotations = 0.f; for (size_t j = 0; j < jointRotations2D.size(); ++j) { sumRotations += jointRotations2D[j]; } XMFLOAT2 direction; direction.x = cos(sumRotations); direction.y = sin(sumRotations); XMStoreFloat2(&endEffectorPosition, XMVectorAdd(XMLoadFloat2(&jointPositions2D.back()), XMVectorScale(XMLoadFloat2(&direction), m_IKLinkLength))); return endEffectorPosition; }
bool RayTraceDataGenerator::CalcIntersect(const XMVECTOR& p1, const XMVECTOR& n, XMVECTOR* nResult, XMVECTOR* intersectLocation, float* depth) { /* // grid space vec3 grid = floor( pos ); //向下取整将坐标在网格中使用 vec3 grid_step = sign( dir ); //获取dir(方向)的正负符号<-意思就是说获取网格的步进方向,虽然只是正负 vec3 corner = max( grid_step, vec3( 0.0 ) );//负号->0 //应该是最后在步进方向上产生的偏差值,但是原因不明 // ray space vec3 inv = vec3( 1.0 ) / dir; //取倒数使得各个方向的比值倒过来 vec3 ratio = ( grid + corner - pos ) * inv;//corn+pos的小数部分 vec3 ratio_step = grid_step * inv;//不懂 //于是这个rayspace只是提供一个比值,来决定grid的步进么 // dda <-数值微分法 float hit = -1.0; for ( int i = 0; i < 128; i++ ) { if ( voxel( grid ) > 0.5 ) { hit = 1.0; break; //这里应该是可以直接退出循环的,感觉没什么区别 continue; } vec3 cp = step( ratio, ratio.yzx );//二维情况的搞清楚了,问题还有就是在三维空间上的扩展 mask = cp * ( vec3( 1.0 ) - cp.zxy ); grid += grid_step * mask; ratio += ratio_step * mask; } center = grid + vec3( 0.5 );//中心形式表示(跟grid应该没区别吧0 0) return dot(ratio - ratio_step,vec3(1.0)) * hit;//dot( ratio - ratio_step, mask ) * hit; //这里关心的是hit的深度好像 */ //p1是起点 XMVECTOR start = p1; XMVECTOR dir = n; XMVECTOR zero = XMVectorSetBinaryConstant(0, 0, 0, 0); XMVECTOR one = XMVectorSetBinaryConstant(1, 1, 1, 1); XMVECTOR grid; XMVECTOR grid_step; XMVECTOR grid_corner; grid = XMVectorFloor(start);//实际上w分量为0应该就不影响了吧( //好像DirectXMath没有提供Sign的函数(于是用了一个挺别扭的方法- - //grid_step 就是 sign_dir grid_step = DirectX::XMVectorOrInt(DirectX::XMVectorAndInt(dir, DirectX::XMVectorSplatSignMask()), DirectX::XMVectorSplatOne()); grid_corner = XMVectorClamp(grid_step, zero, one); XMVECTOR inv; XMVECTOR ratio; XMVECTOR ratio_step; inv = XMVectorReciprocal(dir); ratio = XMVectorMultiply(XMVectorSubtract(XMVectorAdd(grid, grid_corner), start), inv); ratio_step = XMVectorMultiply(grid_step, inv); bool hit = false; XMVECTOR cp; XMVECTOR mask; XMVECTOR ratioyzx; XMVECTOR cpzxy; XMFLOAT4 tmp1; XMFLOAT4 tmp2; int i; for (i = 0; i < 128; ++i)//最大深度为128 { XMStoreFloat4(&tmp1, grid); /* __try{ if (map->At(tmp1.x, tmp1.y, tmp1.z).TexType != -1) { hit = true; break; } } __except ((GetExceptionCode() == EXCEPTION_ARRAY_BOUNDS_EXCEEDED)?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH) { //捕获越界错误作为跳出条件,看看有没有问题... break; } */ //理论上来说异常的话处理代价太大,还是判断一下range吧= = if ((RangeCheck(tmp1.x, tmp1.y, tmp1.z))) { if (GetLocInfo(tmp1.x, tmp1.y, tmp1.z) != -1) { hit = true; break; } } /* 修正:发生越界的时候并不一定就要终止,需要考虑到从值域外射出的射线..... 不过就算不break效率应该也比原先的算法要高...(除了要限制一下最大遍历深度这方面 */ XMStoreFloat4(&tmp1, ratio); tmp2.x = tmp1.y; tmp2.y = tmp1.z; tmp2.z = tmp1.x; ratioyzx = XMLoadFloat4(&tmp2); cp = XMVectorAndInt(XMVectorGreaterOrEqual(ratioyzx, ratio), XMVectorSplatOne());//1 or 0 XMStoreFloat4(&tmp1, cp); tmp2.x = tmp1.z; tmp2.y = tmp1.x; tmp2.z = tmp1.y; cpzxy = XMLoadFloat4(&tmp2); mask = XMVectorMultiply(cp, XMVectorSubtract(one, cpzxy)); grid += XMVectorMultiply(grid_step, mask); ratio += XMVectorMultiply(ratio_step, mask); } if (hit) { XMFLOAT4 result; result = tmp1; //所在方块 if (i == 0) { //这是在方块内部的情况 result.w = -1; return false; } XMVECTOR ftmp; ftmp = XMVectorSubtract(ratio, ratio_step);//因为取的只是mask方向的值,所以step在这里没必要乘mask *depth = XMVectorGetX(DirectX::XMVector3Dot(ftmp, mask)); ftmp = XMVectorAdd(XMVectorScale(dir,*depth) , p1); XMStoreFloat4(&tmp1, ftmp); //需要全部反过来,因为上面的式子没有取反 *intersectLocation = ftmp; result = tmp1; result.w = 0; XMVECTOR normal; normal = XMVectorMultiply(mask, grid_step); XMStoreFloat4(&tmp1, normal); //需要全部反过来,因为上面的式子没有取反 if (tmp1.x > 0.5) { //法向量为1,0,0,后方 *nResult = XMVectorSetBinaryConstant(1, 0, 0, 0); } else if (tmp1.x < -0.5) { //法向量为-1,0,0,前方 *nResult = XMVectorSetBinaryConstant(-1, 0, 0, 0); } else if (tmp1.y < -0.5) { //法向量为0,-1,0,右方 *nResult = XMVectorSetBinaryConstant(0, -1, 0, 0); } else if (tmp1.y > 0.5) { //法向量为0,1,0,左方 *nResult = XMVectorSetBinaryConstant(0, 1, 0, 0); } else if (tmp1.z < -0.5) { //法向量为0,0,-1,上方 *nResult = XMVectorSetBinaryConstant(0, 0, -1, 0); } else if (tmp1.z > 0.5) { //法向量为0,0,1,下方 *nResult = XMVectorSetBinaryConstant(0, 0, 1, 0); } return true; //return result; } else { return false; } //上面成功的进行了判断,可以得出grid编号了,不过还要算一下相交面( return false; }
bool WorldEntity::circleAALineIntersect( XMVECTOR start, XMVECTOR end, XMVECTOR circleCenter, float circleRadius ) { //A collision function we actually understand... //Create a vector from the start to the circle position XMVECTOR cToStart = circleCenter - start; XMVECTOR cToEnd = circleCenter - end; XMVECTOR lenToStart = XMVector4Length( cToStart ); XMVECTOR lenToEnd = XMVector4Length( cToEnd ); XMFLOAT4 ans; XMStoreFloat4( &ans, lenToStart ); if( ans.x <= circleRadius ){ return true; } XMStoreFloat4( &ans, lenToEnd ); if( ans.x <= circleRadius ){ return true; } //Calculate the start to end XMVECTOR endToStart = end - start; XMVECTOR endToStartLen = XMVector4Length( endToStart ); XMFLOAT4 tmp; XMStoreFloat4(&tmp, endToStartLen); tmp.x = 1.0f / tmp.x; XMVECTOR tmpA = XMVectorScale(endToStart, tmp.x); XMVECTOR tmpB = XMVectorScale(cToStart, tmp.x); //Project it onto the start -> end vector XMVECTOR dot = XMVector4Dot( tmpA, tmpB ); //Calculate the Perpendicular point XMVECTOR per = start + ( endToStart * dot ); //If the perpendicular point is within range of the circle, there is a collision XMVECTOR perDist = XMVector4Length( circleCenter - per ); XMStoreFloat4( &ans, perDist ); if( ans.x > circleRadius ){ return false; } //Store the dot product to see how far down the line the collision happens XMStoreFloat4( &ans, dot ); //If the dot product is negative, the collision is outside the range if( ans.x < 0.0f ){ return false; } //If the dot product is bigger than 1.0f, meaning it scaled the vector passed the segment, the collision is outside the range if( ans.x > 1.0f ){ return false; } return true; }
HRESULT SceneObjectGrid::InitializeMeshStreams(__in ISceneObjectMesh* pMesh, const XMVECTOR xAxis, const XMVECTOR yAxis, const XMFLOAT3& origin, UINT xResolution, UINT yResolution, XMFLOAT4 color) { if (xResolution == 0 || yResolution == 0 || pMesh == NULL) { return E_INVALIDARG; } HRESULT hr = S_OK; xResolution = max(1, xResolution); yResolution = max(1, yResolution); // Build grid geometry INT iLineCount = xResolution + yResolution + 2; VertexType* pLines = new VertexType[2 * iLineCount]; if (!pLines) { hr = E_OUTOFMEMORY; } else { XMVECTOR vOrigin = XMLoadFloat3(&origin); for (UINT i = 0; i <= xResolution; i++) { FLOAT fPercent = (FLOAT)i / (FLOAT)xResolution; fPercent = (fPercent * 2.0f) - 1.0f; XMVECTOR vScale = XMVectorScale(xAxis, fPercent); vScale = XMVectorAdd( vScale, vOrigin ); XMStoreFloat3(&pLines[(i * 2)].position, XMVectorSubtract(vScale, yAxis)); pLines[(i * 2)].color = color; XMStoreFloat3(&pLines[(i * 2) + 1].position, XMVectorAdd(vScale, yAxis)); pLines[(i * 2) + 1].color = color; } UINT iStartIndex = (xResolution + 1) * 2; for (UINT i = 0; i <= yResolution; i++) { FLOAT fPercent = (FLOAT)i / (FLOAT)yResolution; fPercent = (fPercent * 2.0f) - 1.0f; XMVECTOR vScale = XMVectorScale(yAxis, fPercent); vScale = XMVectorAdd(vScale, vOrigin); XMStoreFloat3(&pLines[(i * 2) + iStartIndex].position, XMVectorSubtract(vScale, xAxis)); pLines[(i * 2) + iStartIndex].color = color; XMStoreFloat3(&pLines[(i * 2) + 1 + iStartIndex].position, XMVectorAdd(vScale, xAxis)); pLines[(i * 2) + 1 + iStartIndex].color = color; } SmartPtr<IVertexStream> spVertexStream; hr = CreateVertexStream(2 * iLineCount, pLines, &spVertexStream); if (SUCCEEDED(hr)) { hr = pMesh->SetMeshStream(MeshStreamType::MST_VERTEX_POSITIONS, spVertexStream.CastTo<IMeshStream>()); } pMesh->SetPrimitiveTopologyType(PrimitiveTopologyType::PTT_LINELIST); } delete[] pLines; return hr; }
MeshData(const string& name) { static Assimp::Importer importer; D3DInfo& d3d = *D3DInfo::CurrentInstance(); // Read the mesh data from file using Asset Importer. const aiScene* scene = importer.ReadFile(config::Meshes + name, ImportSetting); if (!scene || !scene->mNumMeshes) { Warn("Mesh read failed for " + name); return; } const aiMesh* mesh = scene->mMeshes[0]; WarnIf(scene->mNumMeshes > 1, "Mesh " + name + " has more sub-meshes than are currently supported"); // Verify mesh texture coordinates and tangents. bool hasTexCoords = true; if (!mesh->HasTextureCoords(0)) { hasTexCoords = false; Warn("Mesh " + name + " doesn't have texture coordinates"); } bool hasTangents = true; if (!mesh->HasTangentsAndBitangents()) { hasTangents = false; Warn("Mesh " + name + " doesn't have tangents/bitangents"); } float minFloat = numeric_limits<float>::min(); float maxFloat = numeric_limits<float>::max(); boundingBox.max = { minFloat, minFloat, minFloat }; boundingBox.min = { maxFloat, maxFloat, maxFloat }; // Copy all vertices. vertices.resize(mesh->mNumVertices); for (size_t i = 0; i < mesh->mNumVertices; ++i) { vertices[i].position = reinterpret_cast<const float3&>(mesh->mVertices[i]); vertices[i].normal = reinterpret_cast<const float3&>(mesh->mNormals[i]); if (hasTexCoords) { vertices[i].tex = reinterpret_cast<const float2&>(mesh->mTextureCoords[0][i]); } if (hasTangents) { vertices[i].tangent = reinterpret_cast<const float3&>(mesh->mTangents[i]); vertices[i].bitangent = reinterpret_cast<const float3&>(mesh->mBitangents[i]); } // Determine the min and max extents of the mesh. if (vertices[i].position.x < boundingBox.min.x) boundingBox.min.x = vertices[i].position.x; if (vertices[i].position.y < boundingBox.min.y) boundingBox.min.y = vertices[i].position.y; if (vertices[i].position.z < boundingBox.min.z) boundingBox.min.z = vertices[i].position.z; if (vertices[i].position.x > boundingBox.max.x) boundingBox.max.x = vertices[i].position.x; if (vertices[i].position.y > boundingBox.max.y) boundingBox.max.y = vertices[i].position.y; if (vertices[i].position.z > boundingBox.max.z) boundingBox.max.z = vertices[i].position.z; } // Calculate the centroid of the mesh: centroid = min + ((max - min) / 2) XMVECTOR minVector = XMLoadFloat3(&boundingBox.min); XMVECTOR cornerToCorner = XMVectorSubtract(XMLoadFloat3(&boundingBox.max), minVector); XMStoreFloat3( &boundingBox.centroid, XMVectorAdd( minVector, XMVectorScale(cornerToCorner, 0.5f))); // Center the mesh on (0,0,0) by subtracting the centroid position from all vertex positions. for (auto& vertex : vertices) { vertex.position.x -= boundingBox.centroid.x; vertex.position.y -= boundingBox.centroid.y; vertex.position.z -= boundingBox.centroid.z; } // Copy all indices. indices.resize(mesh->mNumFaces * 3); for (size_t i = 0; i < mesh->mNumFaces; ++i) { indices[i * 3 + 0] = mesh->mFaces[i].mIndices[0]; indices[i * 3 + 1] = mesh->mFaces[i].mIndices[1]; indices[i * 3 + 2] = mesh->mFaces[i].mIndices[2]; } // Free the loaded scene. importer.FreeScene(); // Create the index buffer. D3D11_BUFFER_DESC bufferDesc; bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; bufferDesc.ByteWidth = indices.size() * sizeof(indices[0]); bufferDesc.CPUAccessFlags = 0; bufferDesc.MiscFlags = 0; bufferDesc.StructureByteStride = 0; bufferDesc.Usage = D3D11_USAGE_IMMUTABLE; D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = indices.data(); initData.SysMemPitch = 0; initData.SysMemSlicePitch = 0; DX(d3d.Device->CreateBuffer(&bufferDesc, &initData, indexBuffer)); // Create the vertex buffer. bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; bufferDesc.ByteWidth = vertices.size() * sizeof(vertices[0]); initData.pSysMem = vertices.data(); DX(d3d.Device->CreateBuffer(&bufferDesc, &initData, vertexBuffer)); // Create the constant buffer. D3D11_BUFFER_DESC cbDesc; ZeroMemory(&cbDesc, sizeof(cbDesc)); cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbDesc.ByteWidth = sizeof(ObjectConstants); cbDesc.Usage = D3D11_USAGE_DEFAULT; DX(d3d.Device->CreateBuffer(&cbDesc, nullptr, constantBuffer)); }
// Renders meshes using cascaded shadow mapping void MeshRenderer::RenderSunShadowMap(ID3D11DeviceContext* context, const Camera& camera) { PIXEvent event(L"Sun Shadow Map Rendering"); const float MinDistance = reductionDepth.x; const float MaxDistance = reductionDepth.y; // Compute the split distances based on the partitioning mode float CascadeSplits[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; { float lambda = 1.0f; float nearClip = camera.NearClip(); float farClip = camera.FarClip(); float clipRange = farClip - nearClip; float minZ = nearClip + MinDistance * clipRange; float maxZ = nearClip + MaxDistance * clipRange; float range = maxZ - minZ; float ratio = maxZ / minZ; for(uint32 i = 0; i < NumCascades; ++i) { float p = (i + 1) / static_cast<float>(NumCascades); float log = minZ * std::pow(ratio, p); float uniform = minZ + range * p; float d = lambda * (log - uniform) + uniform; CascadeSplits[i] = (d - nearClip) / clipRange; } } Float3 c0Extents; Float4x4 c0Matrix; const Float3 lightDir = AppSettings::SunDirection; // Render the meshes to each cascade for(uint32 cascadeIdx = 0; cascadeIdx < NumCascades; ++cascadeIdx) { PIXEvent cascadeEvent((L"Rendering Shadow Map Cascade " + ToString(cascadeIdx)).c_str()); // Set the viewport SetViewport(context, ShadowMapSize, ShadowMapSize); // Set the shadow map as the depth target ID3D11DepthStencilView* dsv = sunShadowDepthMap.DSView; ID3D11RenderTargetView* nullRenderTargets[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = { NULL }; context->OMSetRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, nullRenderTargets, dsv); context->ClearDepthStencilView(dsv, D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0); // Get the 8 points of the view frustum in world space XMVECTOR frustumCornersWS[8] = { XMVectorSet(-1.0f, 1.0f, 0.0f, 1.0f), XMVectorSet( 1.0f, 1.0f, 0.0f, 1.0f), XMVectorSet( 1.0f, -1.0f, 0.0f, 1.0f), XMVectorSet(-1.0f, -1.0f, 0.0f, 1.0f), XMVectorSet(-1.0f, 1.0f, 1.0f, 1.0f), XMVectorSet( 1.0f, 1.0f, 1.0f, 1.0f), XMVectorSet( 1.0f, -1.0f, 1.0f, 1.0f), XMVectorSet(-1.0f, -1.0f, 1.0f, 1.0f), }; float prevSplitDist = cascadeIdx == 0 ? MinDistance : CascadeSplits[cascadeIdx - 1]; float splitDist = CascadeSplits[cascadeIdx]; XMVECTOR det; XMMATRIX invViewProj = XMMatrixInverse(&det, camera.ViewProjectionMatrix().ToSIMD()); for(uint32 i = 0; i < 8; ++i) frustumCornersWS[i] = XMVector3TransformCoord(frustumCornersWS[i], invViewProj); // Get the corners of the current cascade slice of the view frustum for(uint32 i = 0; i < 4; ++i) { XMVECTOR cornerRay = XMVectorSubtract(frustumCornersWS[i + 4], frustumCornersWS[i]); XMVECTOR nearCornerRay = XMVectorScale(cornerRay, prevSplitDist); XMVECTOR farCornerRay = XMVectorScale(cornerRay, splitDist); frustumCornersWS[i + 4] = XMVectorAdd(frustumCornersWS[i], farCornerRay); frustumCornersWS[i] = XMVectorAdd(frustumCornersWS[i], nearCornerRay); } // Calculate the centroid of the view frustum slice XMVECTOR frustumCenterVec = XMVectorZero(); for(uint32 i = 0; i < 8; ++i) frustumCenterVec = XMVectorAdd(frustumCenterVec, frustumCornersWS[i]); frustumCenterVec = XMVectorScale(frustumCenterVec, 1.0f / 8.0f); Float3 frustumCenter = frustumCenterVec; // Pick the up vector to use for the light camera Float3 upDir = camera.Right(); Float3 minExtents; Float3 maxExtents; { // Create a temporary view matrix for the light Float3 lightCameraPos = frustumCenter; Float3 lookAt = frustumCenter - lightDir; XMMATRIX lightView = XMMatrixLookAtLH(lightCameraPos.ToSIMD(), lookAt.ToSIMD(), upDir.ToSIMD()); // Calculate an AABB around the frustum corners XMVECTOR mins = XMVectorSet(REAL_MAX, REAL_MAX, REAL_MAX, REAL_MAX); XMVECTOR maxes = XMVectorSet(-REAL_MAX, -REAL_MAX, -REAL_MAX, -REAL_MAX); for(uint32 i = 0; i < 8; ++i) { XMVECTOR corner = XMVector3TransformCoord(frustumCornersWS[i], lightView); mins = XMVectorMin(mins, corner); maxes = XMVectorMax(maxes, corner); } minExtents = mins; maxExtents = maxes; } // Adjust the min/max to accommodate the filtering size float scale = (ShadowMapSize + FilterSize) / static_cast<float>(ShadowMapSize); minExtents.x *= scale; minExtents.y *= scale; maxExtents.x *= scale; maxExtents.x *= scale; Float3 cascadeExtents = maxExtents - minExtents; // Get position of the shadow camera Float3 shadowCameraPos = frustumCenter + lightDir * -minExtents.z; // Come up with a new orthographic camera for the shadow caster OrthographicCamera shadowCamera(minExtents.x, minExtents.y, maxExtents.x, maxExtents.y, 0.0f, cascadeExtents.z); shadowCamera.SetLookAt(shadowCameraPos, frustumCenter, upDir); // Draw the mesh with depth only, using the new shadow camera RenderDepth(context, shadowCamera, true, false); // Apply the scale/offset matrix, which transforms from [-1,1] // post-projection space to [0,1] UV space XMMATRIX texScaleBias; texScaleBias.r[0] = XMVectorSet(0.5f, 0.0f, 0.0f, 0.0f); texScaleBias.r[1] = XMVectorSet(0.0f, -0.5f, 0.0f, 0.0f); texScaleBias.r[2] = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); texScaleBias.r[3] = XMVectorSet(0.5f, 0.5f, 0.0f, 1.0f); XMMATRIX shadowMatrix = shadowCamera.ViewProjectionMatrix().ToSIMD(); shadowMatrix = XMMatrixMultiply(shadowMatrix, texScaleBias); // Store the split distance in terms of view space depth const float clipDist = camera.FarClip() - camera.NearClip(); shadowConstants.Data.CascadeSplits[cascadeIdx] = camera.NearClip() + splitDist * clipDist; if(cascadeIdx == 0) { c0Extents = cascadeExtents; c0Matrix = shadowMatrix; shadowConstants.Data.ShadowMatrix = XMMatrixTranspose(shadowMatrix); shadowConstants.Data.CascadeOffsets[0] = Float4(0.0f, 0.0f, 0.0f, 0.0f); shadowConstants.Data.CascadeScales[0] = Float4(1.0f, 1.0f, 1.0f, 1.0f); } else { // Calculate the position of the lower corner of the cascade partition, in the UV space // of the first cascade partition Float4x4 invCascadeMat = Float4x4::Invert(shadowMatrix); Float3 cascadeCorner = Float3::Transform(Float3(0.0f, 0.0f, 0.0f), invCascadeMat); cascadeCorner = Float3::Transform(cascadeCorner, c0Matrix); // Do the same for the upper corner Float3 otherCorner = Float3::Transform(Float3(1.0f, 1.0f, 1.0f), invCascadeMat); otherCorner = Float3::Transform(otherCorner, c0Matrix); // Calculate the scale and offset Float3 cascadeScale = Float3(1.0f, 1.0f, 1.f) / (otherCorner - cascadeCorner); shadowConstants.Data.CascadeOffsets[cascadeIdx] = Float4(-cascadeCorner, 0.0f); shadowConstants.Data.CascadeScales[cascadeIdx] = Float4(cascadeScale, 1.0f); } ConvertToEVSM(context, cascadeIdx, shadowConstants.Data.CascadeScales[cascadeIdx].To3D()); } }
EnemyWithStates* EnemyBuilder::AddNewEnemy(const XMFLOAT3 &position, const EnemyTypes typeOfEnemy) { EnemyWithStates* newEnemyWithStates = new EnemyWithStates(); switch (typeOfEnemy) { case EnemyTypes::ENEMY_TYPE_NORMAL: { Entity newEntity; newEntity = _builder->EntityC().Create(); _builder->Light()->BindPointLight(newEntity, XMFLOAT3(0.0f, 0.0f, 0.0f), STARTRANGELIGHT*3.0f, ENEMY_TYPE_NORMAL_COLOR, STARTINTENSITYLIGHT); _builder->Light()->SetAsVolumetric(newEntity, true); _builder->Light()->ChangeLightBlobRange(newEntity, STARTBLOBRANGELIGHT); _builder->Transform()->CreateTransform(newEntity); _builder->Bounding()->CreateBoundingSphere(newEntity, STARTBLOBRANGELIGHT*0.5f); _builder->Transform()->SetPosition(newEntity, XMVectorSet(position.x, position.y, position.z, 1.0f)); newEnemyWithStates->_thisEnemy = new Enemy(newEntity, _builder); newEnemyWithStates->_thisEnemyStateController = new AIStateController(); newEnemyWithStates->_thisEnemyStateController->AddState(new AIPatrolState(AI_STATE_NONE, _controller, newEnemyWithStates->_thisEnemy, _builder)); newEnemyWithStates->_thisEnemyStateController->AddState(new AIAttackState(AI_STATE_NONE, _controller, newEnemyWithStates->_thisEnemy, _builder)); newEnemyWithStates->_thisEnemyStateController->AddState(new AITransitionState(AI_STATE_NONE, _controller, newEnemyWithStates->_thisEnemy, _builder)); //Add 10 bricks around the light XMVECTOR enemyPos = XMVectorSet(position.x, position.y, position.z, 1.0f); const int nrOfBricks = 5; std::vector<string> pro; pro.push_back("DiffuseMap"); pro.push_back("NormalMap"); pro.push_back("Roughness"); std::vector<wstring> texs; texs.push_back(L"Assets/Textures/Enemy_Brick_Dif_01.png"); texs.push_back(L"Assets/Textures/Enemy_Brick_NM.png"); texs.push_back(L"Assets/Textures/Enemy_Brick_Roughness.png"); for (int i = 0; i < nrOfBricks; ++i) { XMVECTOR offset = XMVectorSet(static_cast<float>((rand() % 100) - 50), static_cast<float>((rand() % 100) - 50), static_cast<float>((rand() % 100) - 50), 0.0f); offset = XMVector3Normalize(offset); offset = XMVectorScale(offset, 0.33f); Entity brick = _builder->EntityC().Create(); unsigned int br = rand() % 2 + 1; _builder->Mesh()->CreateStaticMesh(brick, ("Assets/Models/Enemy_Brick_0" + to_string(br) + ".arf").c_str()); _builder->Material()->BindMaterial(brick, "Shaders/GBuffer.hlsl"); _builder->Material()->SetEntityTexture(brick, pro, texs); _builder->Bounding()->CreateBoundingSphere(brick, _builder->Mesh()->GetMesh(brick)); _builder->Transform()->CreateTransform(brick); _builder->Transform()->SetDirection(brick, -offset); if (br == 2) _builder->Transform()->RotateRoll(brick, 90.0f); _builder->Transform()->SetScale(brick, XMVectorSet(0.1f, 0.1f, 0.1f, 0.0f)); Entity brickRot = _builder->EntityC().Create(); _builder->Transform()->CreateTransform(brickRot); _builder->Transform()->BindChild(newEntity, brickRot); _builder->Transform()->BindChild(brickRot, brick); unsigned int rot = rand() % 3; _builder->Animation()->CreateAnimation(brickRot, "rotate", 90.0f, [this, brickRot, rot](float delta, float amount, float offset) { switch (rot) { case 0: _builder->Transform()->RotatePitch(brickRot, delta); break; case 1: _builder->Transform()->RotateYaw(brickRot, delta); break; case 2: _builder->Transform()->RotateRoll(brickRot, delta); break; default: break; } }, [this, brickRot]() { _builder->Animation()->PlayAnimation(brickRot, "rotate", 360.0f*20.0f); }); _builder->Animation()->PlayAnimation(brickRot, "rotate", 360.0f*20.0f); _builder->Transform()->SetPosition(brick, offset); newEnemyWithStates->_thisEnemy->AddChild(brick); newEnemyWithStates->_thisEnemy->AddChild(brickRot); } break; } case EnemyTypes::ENEMY_TYPE_TELEPORTER: { Entity newEntity; newEntity = _builder->EntityC().Create(); Entity emesh = _builder->EntityC().Create(); _builder->Mesh()->CreateStaticMesh(emesh, "Assets/Models/BallHorizontal.arf"); _builder->Material()->BindMaterial(emesh, "Shaders/GBuffer.hlsl"); std::vector<string> pro; pro.push_back("DiffuseMap"); pro.push_back("NormalMap"); pro.push_back("Roughness"); std::vector<wstring> texs; texs.push_back(L"Assets/Textures/Ball.png"); texs.push_back(L"Assets/Textures/Enemy_Brick_NM.png"); texs.push_back(L"Assets/Textures/Enemy_Brick_Roughness.png"); _builder->Material()->SetEntityTexture(emesh, pro, texs); _builder->Transform()->CreateTransform(emesh); _builder->Transform()->CreateTransform(newEntity); _builder->Transform()->BindChild(newEntity, emesh); _builder->Light()->BindPointLight(newEntity, XMFLOAT3(0.0f, 0.0f, 0.0f), STARTRANGELIGHT*3.0f, ENEMY_TYPE_TELEPORTER_COLOR, STARTINTENSITYLIGHT); _builder->Light()->SetAsVolumetric(newEntity, true); _builder->Light()->ChangeLightBlobRange(newEntity, STARTBLOBRANGELIGHT); _builder->Bounding()->CreateBoundingSphere(newEntity, _builder->Mesh()->GetMesh(emesh)); _builder->Bounding()->CreateBoundingSphere(emesh, _builder->Mesh()->GetMesh(emesh)); _builder->Transform()->SetPosition(newEntity, XMVectorSet(position.x, position.y, position.z, 1.0f)); newEnemyWithStates->_thisEnemy = new Enemy(newEntity, _builder); newEnemyWithStates->_thisEnemyStateController = new AIStateController(); newEnemyWithStates->_thisEnemyStateController->AddState(new AITeleportMoveState(AI_STATE_NONE, _controller, newEnemyWithStates->_thisEnemy, _builder)); newEnemyWithStates->_thisEnemy->SetScaleFactor(0.0075f); _builder->Transform()->SetScale(newEntity, XMFLOAT3(0.005f, 0.005f, 0.005f)); _builder->Animation()->CreateAnimation(emesh, "rotate", 90.0f, [this, emesh](float delta, float amount, float offset) { _builder->Transform()->RotateYaw(emesh, delta); }, [this, emesh]() { _builder->Animation()->PlayAnimation(emesh, "rotate", 360.0f*20.0f); }); _builder->Animation()->PlayAnimation(emesh, "rotate", 360.0f*20.0f); newEnemyWithStates->_thisEnemy->AddChild(emesh); break; } case EnemyTypes::ENEMY_TYPE_MINI_GUN: { Entity newEntity; newEntity = _builder->EntityC().Create(); _builder->Mesh()->CreateStaticMesh(newEntity, "Assets/Models/BallFlipped.arf"); _builder->Material()->BindMaterial(newEntity, "Shaders/GBuffer.hlsl"); std::vector<string> pro; pro.push_back("DiffuseMap"); pro.push_back("NormalMap"); pro.push_back("Roughness"); std::vector<wstring> texs; texs.push_back(L"Assets/Textures/Ball.png"); texs.push_back(L"Assets/Textures/Enemy_Brick_NM.png"); texs.push_back(L"Assets/Textures/Enemy_Brick_Roughness.png"); _builder->Material()->SetEntityTexture(newEntity, pro, texs); _builder->Light()->BindPointLight(newEntity, XMFLOAT3(0.0f, 0.0f, 0.0f), STARTRANGELIGHT*3.0f, ENEMY_TYPE_MINI_GUN_COLOR, STARTINTENSITYLIGHT); _builder->Light()->SetAsVolumetric(newEntity, true); _builder->Light()->ChangeLightBlobRange(newEntity, STARTBLOBRANGELIGHT); _builder->Transform()->CreateTransform(newEntity); _builder->Bounding()->CreateBoundingSphere(newEntity, _builder->Mesh()->GetMesh(newEntity)); _builder->Transform()->SetPosition(newEntity, XMVectorSet(position.x, position.y, position.z, 1.0f)); _builder->Transform()->SetScale(newEntity, XMFLOAT3(0.005f, 0.005f, 0.005f)); newEnemyWithStates->_thisEnemy = new Enemy(newEntity, _builder); newEnemyWithStates->_thisEnemy->SetScaleFactor(0.01f); newEnemyWithStates->_thisEnemyStateController = new AIStateController(); newEnemyWithStates->_thisEnemyStateController->AddState(new AIMiniGunLightState(AI_STATE_NONE, _controller, newEnemyWithStates->_thisEnemy, _builder)); break; } case EnemyTypes::ENEMY_TYPE_SHADOW: { Entity newEntity; newEntity = _builder->EntityC().Create(); _builder->Light()->BindPointLight(newEntity, XMFLOAT3(0.0f, 0.0f, 0.0f), STARTRANGELIGHT*3.0f, ENEMY_TYPE_SHADOW_COLOR, STARTINTENSITYLIGHT); _builder->Light()->SetAsVolumetric(newEntity, true); _builder->Light()->ChangeLightBlobRange(newEntity, STARTBLOBRANGELIGHT); _builder->Transform()->CreateTransform(newEntity); _builder->Bounding()->CreateBoundingSphere(newEntity, STARTBLOBRANGELIGHT *0.3f); _builder->Transform()->SetPosition(newEntity, XMVectorSet(position.x, position.y, position.z, 1.0f)); newEnemyWithStates->_thisEnemy = new Enemy(newEntity, _builder); newEnemyWithStates->_thisEnemyStateController = new AIStateController(); newEnemyWithStates->_thisEnemyStateController->AddState(new AIPatrolState(AI_STATE_NONE, _controller, newEnemyWithStates->_thisEnemy, _builder)); newEnemyWithStates->_thisEnemyStateController->AddState(new AIWalkIntoTheLightAttackState(AI_STATE_NONE, _controller, newEnemyWithStates->_thisEnemy, _builder)); break; } case EnemyTypes::ENEMY_TYPE_PROXIMITY_SITH: { Entity e = _builder->EntityC().Create(); _builder->Light()->BindPointLight( e, XMFLOAT3( 0.0f, 0.0f, 0.0f ), STARTRANGELIGHT * 3.0f, ENEMY_TYPE_PROXIMITY_SITH_COLOR, STARTINTENSITYLIGHT ); _builder->Light()->SetAsVolumetric( e, true ); _builder->Light()->ChangeLightBlobRange( e, STARTBLOBRANGELIGHT ); _builder->Transform()->CreateTransform( e ); _builder->Bounding()->CreateBoundingSphere( e, STARTBLOBRANGELIGHT*0.3f ); _builder->Transform()->SetPosition( e, XMVectorSet( position.x, position.y, position.z, 1.0f ) ); _builder->ProximityLightning()->Add( e ); newEnemyWithStates->_thisEnemy = new Enemy( e, _builder ); newEnemyWithStates->_thisEnemyStateController = new AIStateController(); newEnemyWithStates->_thisEnemyStateController->AddState( new AIPatrolState( AI_STATE_NONE, _controller, newEnemyWithStates->_thisEnemy, _builder ) ); newEnemyWithStates->_thisEnemyStateController->AddState( new AIAttackState( AI_STATE_NONE, _controller, newEnemyWithStates->_thisEnemy, _builder ) ); newEnemyWithStates->_thisEnemyStateController->AddState( new AITransitionState( AI_STATE_NONE, _controller, newEnemyWithStates->_thisEnemy, _builder ) ); } } _builder->Transform()->RotateRoll(newEnemyWithStates->_thisEnemy->GetEntity(), 0.0f); return newEnemyWithStates; }
bool DX11::ModelShader::SetParameters(ID3D11DeviceContext * direct3Dcontext, Gpu::Model * model, Gpu::Camera * camera, Gpu::Light ** lights, unsigned numLights, float aspect, Gpu::Effect * effect) { if(!model || !camera) return false; if(camera->position == camera->target) { OutputDebugString(L"Cannot construct view matrix!"); return false; } // MATRIX OPS - SIGNIFICANT COST - ~9us // glm::mat4 modelMatrix = model->GetMatrix(); XMMATRIX world((float*)&modelMatrix); XMStoreFloat4x4(&vertexConstData.world, world); glm::mat4 camMatrix = camera->GetProjMatrix(aspect) * camera->GetViewMatrix(); XMMATRIX viewProj((float*)&camMatrix); XMStoreFloat4x4(&vertexConstData.viewProjection, viewProj); XMMATRIX wit = XMMatrixInverse(0, XMMatrixTranspose(world)); XMStoreFloat4x4(&vertexConstData.worldInverseTranspose, wit); vertexConstData.materialColor = XMFLOAT4(model->color.r, model->color.g, model->color.b, model->color.a); ID3D11ShaderResourceView * nullResource = 0; if(model->texture) { DX11::Texture* texture = static_cast<DX11::Texture*>(model->texture); direct3Dcontext->PSSetShaderResources(0, 1, &texture->shaderView); } else { direct3Dcontext->PSSetShaderResources(0, 1, &nullResource); } // BEGIN LIGHTING - VARIABLE COST // if(model->cubeMap) { DX11::CubeMap * cubeMap = static_cast<DX11::CubeMap*>(model->cubeMap); direct3Dcontext->PSSetShaderResources(1, 1, &cubeMap->shaderView); pixelConstData.cubeMapAlpha = 1.0f; } else { direct3Dcontext->PSSetShaderResources(1, 1, &nullResource); pixelConstData.cubeMapAlpha = 0.0f; } if(model->normalMap) { DX11::Texture * normalMap = static_cast<DX11::Texture*>(model->normalMap); direct3Dcontext->PSSetShaderResources(2, 1, &normalMap->shaderView); } else { direct3Dcontext->PSSetShaderResources(2, 1, &nullResource); } pixelConstData.numLights = numLights; if(numLights > 0) { pixelConstData.ambient = 0.0f; pixelConstData.cameraPosition = XMFLOAT3(camera->position.x, camera->position.y, camera->position.z); pixelConstData.specularPower = model->specPower; pixelConstData.specularFactor = model->specFactor; pixelConstData.diffuseFactor = model->diffuseFactor; for(unsigned i = 0; i < numLights && i < MAX_LIGHTS; ++i) { // Hmm, really the specular highlight should be calculated // from the light's size, position and intensity. // Do a little more investigation into Physically Based Lighting lightConstData.positionSpecs[i].specPower = 12.0f; Gpu::LightType lightType = lights[i]->GetType(); if(lightType == Gpu::LightType_Directional) { Gpu::DirectionalLight * dirLight = static_cast<Gpu::DirectionalLight*>(lights[i]); XMVECTOR lightDirVec = XMLoadFloat3(&XMFLOAT3(dirLight->direction.x, dirLight->direction.y, dirLight->direction.z)); XMStoreFloat3(&(lightConstData.positionSpecs[i].position), XMVectorScale(lightDirVec, 10.0e+10f)); lightConstData.colorAttenuations[i].color = XMFLOAT3(dirLight->color.r, dirLight->color.g, dirLight->color.b); lightConstData.colorAttenuations[i].attenuation = 0.0f; lightConstData.spotDirPowers[i].direction = XMFLOAT3(0.0f, 0.0f, 0.0f); lightConstData.spotDirPowers[i].spotPower = 0.0f; } if(lightType == Gpu::LightType_Point) { Gpu::PointLight * pointLight = static_cast<Gpu::PointLight*>(lights[i]); lightConstData.positionSpecs[i].position = XMFLOAT3(pointLight->position.x, pointLight->position.y, pointLight->position.z); lightConstData.colorAttenuations[i].color = XMFLOAT3(pointLight->color.r, pointLight->color.g, pointLight->color.b); lightConstData.colorAttenuations[i].attenuation = pointLight->atten; lightConstData.spotDirPowers[i].direction = XMFLOAT3(0.0f, 0.0f, 0.0f); lightConstData.spotDirPowers[i].spotPower = 0.0f; } if(lightType == Gpu::LightType_Spot) { Gpu::SpotLight * spotLight = static_cast<Gpu::SpotLight*>(lights[i]); lightConstData.positionSpecs[i].position = XMFLOAT3(spotLight->position.x, spotLight->position.y, spotLight->position.z); lightConstData.colorAttenuations[i].color = XMFLOAT3(spotLight->color.r, spotLight->color.g, spotLight->color.b); lightConstData.colorAttenuations[i].attenuation = spotLight->atten; XMStoreFloat3(&lightConstData.spotDirPowers[i].direction, XMVector3Normalize(XMLoadFloat3( &XMFLOAT3(spotLight->direction.x, spotLight->direction.y, spotLight->direction.z)))); lightConstData.spotDirPowers[i].spotPower = spotLight->power; if(i == 0) { float lightFOV = XM_PI * 0.15f; glm::mat4 lightGlmMatrix = spotLight->GetMatrix(lightFOV, glm::vec3(0.0f, 1.0f, 0.0f)); XMMATRIX lightXMMatrix((float*)&lightGlmMatrix); //XMMATRIX lightView = XMMatrixLookToLH( // XMLoadFloat3(&lightConstData.positionSpecs[i].position), // XMLoadFloat3(&lightConstData.spotDirPowers[i].direction), // XMLoadFloat3(&XMFLOAT3(0.0f, 1.0f, 0.0f))); //XMMATRIX lightLens = XMMatrixPerspectiveFovLH(lightFOV, 1.0f, 1.0f, 200.0f); XMStoreFloat4x4(&vertexConstData.lightViewProjection, lightXMMatrix); } } } static unsigned setCount = 0; setCount++; direct3Dcontext->UpdateSubresource(lightParamsBuffer, 0, 0, &lightConstData, sizeof(LightConstants), sizeof(LightConstants)); setCount++; direct3Dcontext->PSSetConstantBuffers(1, 1, &lightParamsBuffer); } else { pixelConstData.lightPosition = XMFLOAT3(0.0f, 0.0f, 0.0f); pixelConstData.lightColor = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f); pixelConstData.cameraPosition = XMFLOAT3(camera->position.x, camera->position.y, camera->position.z); pixelConstData.spotPower = 0.0f; pixelConstData.specularPower = FLT_MAX; pixelConstData.spotDirection = XMFLOAT3(0.0f, 0.0f, 0.0f); pixelConstData.ambient = 1.0f; } // END LIGHTING // // UPDATING CONSTANT BUFFERS - SIGNIFICANT COST - 17us // direct3Dcontext->UpdateSubresource(pixelConstBuffer, 0, 0, &pixelConstData, sizeof(PixelConstants), sizeof(PixelConstants)); direct3Dcontext->PSSetConstantBuffers(0, 1, &pixelConstBuffer); direct3Dcontext->UpdateSubresource(vertexConstBuffer, 0, 0, &vertexConstData, sizeof(VertexConstants), sizeof(VertexConstants)); direct3Dcontext->VSSetConstantBuffers(0, 1, &vertexConstBuffer); // SETTING EXTRA PARAMS - VARIABLE COST // if(effect) { return currentTechnique->SetExtraParameters(direct3Dcontext, effect); } else { return true; } }
void Inky::Update(float dt, bool powerUpActivated, Direction::DIRECTION facingState, XMFLOAT3 blinkyPos, int levelNumber, int pelletCounter) { if (!isDead) { if (pelletCounter >= 30 && isIdle) { this->isIdle = false; mGhostStates = GHOST_STATES::SCATTER; } if (!isIdle) { switch (mGhostStates) { case SCATTER: SetSpeed(levelNumber, GHOST_STATES::SCATTER); if (!scatterPathDrawn) { PrePathFinding(this->mPos.x, this->mPos.z, this->mScatterWaypoints[0]->xPos, this->mScatterWaypoints[0]->zPos); if (PostPathFinding()) { this->UpdateCurrentTweenPoint(dt); scatterPathDrawn = true; } } if (mTweenPoints.size() != 0) { if (!this->reachedEnd) { this->mPos = this->mCurrTweenPoint; this->UpdateCurrentTweenPoint(dt); } else if (this->reachedEnd) { if (!isLooping) { this->SetWayPoints(mScatterWaypoints); this->isLooping = true; } if (isLooping == true && this->reachedEnd) { this->UpdateCurrentTweenPoint(dt); this->mPos = this->mCurrTweenPoint; } } } if (!powerUpActivated) { this->mGhostStates = GHOST_STATES::SCATTER; mScatterTimer += 5.7142f * dt; //dt currently takes (without mutliplying) 40 seconds to reach 7.0f, 5.7142 comes from 40 / 7 to get the number as accurate as possible. if (mScatterTimer >= 7.0f) { this->mGhostStates = GHOST_STATES::CHASE; mScatterTimer = 0.0f; reachedEnd = false; isLooping = false; CleanUpNodesWaypoints(); mTweenPoints.clear(); } } //If the powerup is activated, switch to the FRIGHTENED state else if (powerUpActivated) { SetSpeed(levelNumber, GHOST_STATES::FRIGHTENED); CleanUpNodesWaypoints(); mTweenPoints.clear(); scatterPathDrawn = false; reachedEnd = false; isLooping = false; mPrevState = mGhostStates; this->mGhostStates = GHOST_STATES::FRIGHTENED; } break; case CHASE: SetSpeed(levelNumber, GHOST_STATES::CHASE); if (!firstChasePathDrawn) { PrePathFinding(this->mPos.x, this->mPos.z, this->mScatterWaypoints[0]->xPos, this->mScatterWaypoints[0]->zPos); if (PostPathFinding()) { this->UpdateCurrentTweenPoint(dt); firstChasePathDrawn = true; } } else { mPathCurrent += dt; if (mPathCurrent >= mPathNext) { if (facingState == Direction::DIRECTION::NORTH || facingState == Direction::DIRECTION::SOUTH) { //Offset tile = 2 spaces in PuckMan's facing offsetTile.xPos = round(MazeLoader::GetPacManData().at(0).pos.x); offsetTile.zPos = round(MazeLoader::GetPacManData().at(0).pos.z + (2 * Direction::getDirecitonVector(facingState).m128_f32[2])); //Draw a vector from Blinky's current position to the offset tile's position XMVECTOR targetTile = XMVectorSet(offsetTile.xPos - blinkyPos.x, 0.0f, offsetTile.zPos - blinkyPos.z, 0.0f); //Double the vector length extending forward, this is Inky's target targetTile = XMVectorScale(targetTile, 2.0f); //Clamp the X and Z value of the targetTile so it cannot choose a tile outside of the level float clampedX = MathHelper::Clamp((int)targetTile.m128_f32[0], 0, (int)(MazeLoader::GetMazeWidth())); float clampedZ = MathHelper::Clamp((int)targetTile.m128_f32[2], 0, (int)(MazeLoader::GetMazeHeight())); //Check if clampedZ is a valid tile, if not move the target tile one more in the opposite direction and try again int goalRow = (MazeLoader::GetMazeHeight()) - round(clampedZ + 15.5f); int goalCol = round(clampedX + 14.5f) - 1; while (MazeLoader::IsBlocked(goalRow, goalCol)) { clampedX -= 1 * Direction::getDirecitonVector(facingState).m128_f32[0]; clampedZ -= 1 * Direction::getDirecitonVector(facingState).m128_f32[2]; if (MazeLoader::IsBlocked(clampedZ, clampedX)) { break; } } PrePathFinding(this->mPos.x, this->mPos.z, round(MazeLoader::GetPacManData().at(0).pos.x), round(MazeLoader::GetPacManData().at(0).pos.z)); if (PostPathFinding()) { this->UpdateCurrentTweenPoint(dt); mPathNext += (1.0f / 10.0f); } } else if (facingState == Direction::DIRECTION::WEST || facingState == Direction::DIRECTION::EAST) { //Offset tile = 2 spaces in PuckMan's facing offsetTile.xPos = round(MazeLoader::GetPacManData().at(0).pos.x); offsetTile.zPos = round(MazeLoader::GetPacManData().at(0).pos.z + (2 * Direction::getDirecitonVector(facingState).m128_f32[2])); //Draw a vector from Blinky's current position to the offset tile's position XMVECTOR targetTile = XMVectorSet(offsetTile.xPos - blinkyPos.x, 0.0f, offsetTile.zPos - blinkyPos.z, 0.0f); //Double the vector length extending forward, this is Inky's target targetTile = XMVectorScale(targetTile, 2.0f); //Clamp the X and Z value of the targetTile so it cannot choose a tile outside of the level //Subract one from the highest value to zero base it float clampedX = MathHelper::Clamp((int)targetTile.m128_f32[0], 0, (int)(MazeLoader::GetMazeWidth())); float clampedZ = MathHelper::Clamp((int)targetTile.m128_f32[2], 0, (int)(MazeLoader::GetMazeHeight())); //Check if clampedZ is a valid tile, if not move the target tile one more in the opposite direction and try again //Because clampedZ and clampedX are already tile based, we can pass it into the function without conversion while (MazeLoader::IsBlocked(clampedZ, clampedX)) { clampedX -= 1 * Direction::getDirecitonVector(facingState).m128_f32[0]; clampedZ -= 1 * Direction::getDirecitonVector(facingState).m128_f32[2]; if (MazeLoader::IsBlocked(clampedZ, clampedX)) { break; } } PrePathFinding(this->mPos.x, this->mPos.z, round(MazeLoader::GetPacManData().at(0).pos.x), round(MazeLoader::GetPacManData().at(0).pos.z)); if (PostPathFinding()) { this->UpdateCurrentTweenPoint(dt); mPathNext += (1.0f / 10.0f); } } } } if (mTweenPoints.size() != 0) { this->mPos = this->mCurrTweenPoint; this->UpdateCurrentTweenPoint(dt); } if (!powerUpActivated) { mGhostStates = GHOST_STATES::CHASE; mChaseTimer += 5.7142f * dt; //dt currently takes (without mutliplying) 40 seconds to reach 7.0f, 5.7142 comes from 40 / 7 to get the number as accurate as possible. if (mChaseTimer >= 7.0f) //Chase time is over, time to scatter { this->mGhostStates = GHOST_STATES::SCATTER; mChaseTimer = 0.0f; scatterPathDrawn = false; reachedEnd = false; isLooping = false; CleanUpNodesWaypoints(); mTweenPoints.clear(); } } //If the powerup is activated, switch to the FRIGHTENED state else if (powerUpActivated) { SetSpeed(levelNumber, GHOST_STATES::FRIGHTENED); CleanUpNodesWaypoints(); mTweenPoints.clear(); mPrevState = mGhostStates; this->mGhostStates = GHOST_STATES::FRIGHTENED; scatterPathDrawn = false; firstChasePathDrawn = false; } break; case FRIGHTENED: SetSpeed(levelNumber, GHOST_STATES::FRIGHTENED); if (!scatterPathDrawn) { PrePathFinding(this->mPos.x, this->mPos.z, this->mScatterWaypoints[0]->xPos, this->mScatterWaypoints[0]->zPos); if (PostPathFinding()) { this->UpdateCurrentTweenPoint(dt); scatterPathDrawn = true; } } if (mTweenPoints.size() != 0) { if (!this->reachedEnd) { this->mPos = this->mCurrTweenPoint; this->UpdateCurrentTweenPoint(dt); } else if (this->reachedEnd) { if (!isLooping) { this->SetWayPoints(mScatterWaypoints); this->isLooping = true; } if (isLooping == true && this->reachedEnd) { this->UpdateCurrentTweenPoint(dt); this->mPos = this->mCurrTweenPoint; } } } if (!powerUpActivated) { mGhostStates = mPrevState; mTweenPoints.clear(); } break; } } } }
VOID FilterDoubleExponential::Update( const NUI_SKELETON_DATA* pSkeletonData, UINT i, NUI_TRANSFORM_SMOOTH_PARAMETERS smoothingParams ) { XMVECTOR vPrevRawPosition; XMVECTOR vPrevFilteredPosition; XMVECTOR vPrevTrend; XMVECTOR vRawPosition; XMVECTOR vFilteredPosition; XMVECTOR vPredictedPosition; XMVECTOR vDiff; XMVECTOR vTrend; XMVECTOR vLength; FLOAT fDiff; BOOL bJointIsValid; const XMVECTOR* __restrict pJointPositions = pSkeletonData->SkeletonPositions; vRawPosition = pJointPositions[i]; vPrevFilteredPosition = m_History[i].m_vFilteredPosition; vPrevTrend = m_History[i].m_vTrend; vPrevRawPosition = m_History[i].m_vRawPosition; bJointIsValid = JointPositionIsValid(vRawPosition); // If joint is invalid, reset the filter if (!bJointIsValid) { m_History[i].m_dwFrameCount = 0; } // Initial start values if (m_History[i].m_dwFrameCount == 0) { vFilteredPosition = vRawPosition; vTrend = XMVectorZero(); m_History[i].m_dwFrameCount++; } else if (m_History[i].m_dwFrameCount == 1) { vFilteredPosition = XMVectorScale(XMVectorAdd(vRawPosition, vPrevRawPosition), 0.5f); vDiff = XMVectorSubtract(vFilteredPosition, vPrevFilteredPosition); vTrend = XMVectorAdd(XMVectorScale(vDiff, smoothingParams.fCorrection), XMVectorScale(vPrevTrend, 1.0f - smoothingParams.fCorrection)); m_History[i].m_dwFrameCount++; } else { // First apply jitter filter vDiff = XMVectorSubtract(vRawPosition, vPrevFilteredPosition); vLength = XMVector3Length(vDiff); fDiff = fabs(XMVectorGetX(vLength)); if (fDiff <= smoothingParams.fJitterRadius) { vFilteredPosition = XMVectorAdd(XMVectorScale(vRawPosition, fDiff/smoothingParams.fJitterRadius), XMVectorScale(vPrevFilteredPosition, 1.0f - fDiff/smoothingParams.fJitterRadius)); } else { vFilteredPosition = vRawPosition; } // Now the double exponential smoothing filter vFilteredPosition = XMVectorAdd(XMVectorScale(vFilteredPosition, 1.0f - smoothingParams.fSmoothing), XMVectorScale(XMVectorAdd(vPrevFilteredPosition, vPrevTrend), smoothingParams.fSmoothing)); vDiff = XMVectorSubtract(vFilteredPosition, vPrevFilteredPosition); vTrend = XMVectorAdd(XMVectorScale(vDiff, smoothingParams.fCorrection), XMVectorScale(vPrevTrend, 1.0f - smoothingParams.fCorrection)); } // Predict into the future to reduce latency vPredictedPosition = XMVectorAdd(vFilteredPosition, XMVectorScale(vTrend, smoothingParams.fPrediction)); // Check that we are not too far away from raw data vDiff = XMVectorSubtract(vPredictedPosition, vRawPosition); vLength = XMVector3Length(vDiff); fDiff = fabs(XMVectorGetX(vLength)); if (fDiff > smoothingParams.fMaxDeviationRadius) { vPredictedPosition = XMVectorAdd(XMVectorScale(vPredictedPosition, smoothingParams.fMaxDeviationRadius/fDiff), XMVectorScale(vRawPosition, 1.0f - smoothingParams.fMaxDeviationRadius/fDiff)); } // Save the data from this frame m_History[i].m_vRawPosition = vRawPosition; m_History[i].m_vFilteredPosition = vFilteredPosition; m_History[i].m_vTrend = vTrend; // Output the data m_FilteredJoints[i] = vPredictedPosition; m_FilteredJoints[i].w = 1.0f; }
//-------------------------------------------------------------------------------------- // The Taylor Series smooths and removes jitter based on a taylor series expansion //-------------------------------------------------------------------------------------- VOID FilterTaylorSeries::Update( const XMVECTOR* pJointPositions ) { const FLOAT fJitterRadius = 0.05f; const FLOAT fAlphaCoef = 1.0f - m_fSmoothing; const FLOAT fBetaCoeff = (fAlphaCoef * fAlphaCoef ) / ( 2 - fAlphaCoef ); XMVECTOR vRawPos; XMVECTOR vCurFilteredPos, vCurEstVel, vCurEstVel2, vCurEstVel3; XMVECTOR vPrevFilteredPos, vPrevEstVel, vPrevEstVel2, vPrevEstVel3; XMVECTOR vDiff; FLOAT fDiff; XMVECTOR vPredicted, vError; XMVECTOR vConstants = { 0.0f, 1.0f, 0.5f, 0.1667f }; for (INT i = 0; i < NUI_SKELETON_POSITION_COUNT; i++) { vRawPos = pJointPositions[i]; vPrevFilteredPos = m_History[i].vPos; vPrevEstVel = m_History[i].vEstVel; vPrevEstVel2 = m_History[i].vEstVel2; vPrevEstVel3 = m_History[i].vEstVel3; if (!JointPositionIsValid(vPrevFilteredPos)) { vCurFilteredPos = vRawPos; vCurEstVel = XMVectorZero(); vCurEstVel2 = XMVectorZero(); vCurEstVel3 = XMVectorZero(); } else if (!JointPositionIsValid(vRawPos)) { vCurFilteredPos = vPrevFilteredPos; vCurEstVel = vPrevEstVel; vCurEstVel2 = vPrevEstVel2; vCurEstVel3 = vPrevEstVel3; } else { // If the current and previous frames have valid data, perform interpolation vDiff = XMVectorSubtract(vPrevFilteredPos, vRawPos); fDiff = fabs(XMVector3Length(vDiff).x); if (fDiff <= fJitterRadius) { vCurFilteredPos = XMVectorAdd(XMVectorScale(vRawPos, fDiff/fJitterRadius), XMVectorScale(vPrevFilteredPos, 1.0f - fDiff/fJitterRadius)); } else { vCurFilteredPos = vRawPos; } vPredicted = XMVectorAdd(vPrevFilteredPos, vPrevEstVel); vPredicted = XMVectorAdd(vPredicted, vPrevEstVel2 * (vConstants.y * vConstants.y * vConstants.z)); vPredicted = XMVectorAdd(vPredicted, vPrevEstVel3 * (vConstants.y * vConstants.y * vConstants.y * vConstants.w)); vError = XMVectorSubtract(vCurFilteredPos, vPredicted); vCurFilteredPos = XMVectorAdd(vPredicted, vError * fAlphaCoef); vCurEstVel = XMVectorAdd(vPrevEstVel, vError * fBetaCoeff); vCurEstVel2 = XMVectorSubtract(vCurEstVel, vPrevEstVel); vCurEstVel3 = XMVectorSubtract(vCurEstVel2, vPrevEstVel2); } // Update the state m_History[i].vPos = vCurFilteredPos; m_History[i].vEstVel = vCurEstVel; m_History[i].vEstVel2 = vCurEstVel2; m_History[i].vEstVel3 = vCurEstVel3; // Output the data m_FilteredJoints[i] = vCurFilteredPos; m_FilteredJoints[i].w = 1.0f; } }
VOID DebugDraw::DrawConeWireframe( const XMFLOAT3& CenterBase, const XMFLOAT3& Axis, FLOAT fBaseRadius, FLOAT fTopRadius, D3DCOLOR Color ) { XMVECTOR vAxis = XMLoadFloat3( &Axis ); XMVECTOR vAxisNorm = XMVector3Normalize( vAxis ); // compute orthogonal vectors for the base of the cone XMVECTOR vBaseVectorX = XMVector3Normalize( XMVector3Orthogonal( vAxisNorm ) ); XMVECTOR vBaseVectorZ = XMVector3Cross( vAxisNorm, vBaseVectorX ); XMVECTOR vBaseVectorXScale = XMVectorScale( vBaseVectorX, fBaseRadius ); XMVECTOR vBaseVectorZScale = XMVectorScale( vBaseVectorZ, fBaseRadius ); // draw base ring if( fBaseRadius != 0 ) { XMFLOAT3 BaseRingAxisX, BaseRingAxisZ; XMStoreFloat3( &BaseRingAxisX, vBaseVectorXScale ); XMStoreFloat3( &BaseRingAxisZ, vBaseVectorZScale ); DrawRing( CenterBase, BaseRingAxisX, BaseRingAxisZ, Color ); } // compute center top location XMVECTOR vCenterTop = XMLoadFloat3( &CenterBase ); vCenterTop = XMVectorAdd( vCenterTop, vAxis ); // compute orthogonal vectors for the top of the cone XMVECTOR vTopVectorXScale = XMVectorScale( vBaseVectorX, fTopRadius ); XMVECTOR vTopVectorZScale = XMVectorScale( vBaseVectorZ, fTopRadius ); // build top ring if( fTopRadius != 0 ) { XMFLOAT3 CenterTop; XMStoreFloat3( &CenterTop, vCenterTop ); XMFLOAT3 TopRingAxisX, TopRingAxisZ; XMStoreFloat3( &TopRingAxisX, vTopVectorXScale ); XMStoreFloat3( &TopRingAxisZ, vTopVectorZScale ); DrawRing( CenterTop, TopRingAxisX, TopRingAxisZ, Color ); } // build walls XMVECTOR vCenterBase = XMLoadFloat3( &CenterBase ); const DWORD dwDivisions = 8; XMFLOAT3 WallVerts[ dwDivisions * 2 ]; for( DWORD i = 0; i < dwDivisions; ++i ) { FLOAT fTheta = ( ( FLOAT )i * XM_2PI ) / ( FLOAT )dwDivisions; XMVECTOR vSin, vCos; XMVectorSinCos( &vSin, &vCos, XMVectorReplicate( fTheta ) ); XMVECTOR vBottom = vCenterBase + vBaseVectorXScale * vSin + vBaseVectorZScale * vCos; XMVECTOR vTop = vCenterTop + vTopVectorXScale * vSin + vTopVectorZScale * vCos; XMStoreFloat3( &WallVerts[ i * 2 ], vBottom ); XMStoreFloat3( &WallVerts[ i * 2 + 1 ], vTop ); } // draw walls SimpleShaders::SetDeclPos(); SimpleShaders::BeginShader_Transformed_ConstantColor( g_matViewProjection, Color ); g_pd3dDevice->DrawPrimitiveUP( D3DPT_LINELIST, dwDivisions, WallVerts, sizeof( XMFLOAT3 ) ); SimpleShaders::EndShader(); }