void Game::CreateSphere(int latLines, int longLines) { NumSphereVertices = ((latLines - 2) * longLines) + 2; NumSphereFaces = ((latLines - 3)*(longLines)* 2) + (longLines * 2); float sphereYaw = 0.0f; float spherePitch = 0.0f; std::vector<Vertex> vertices(NumSphereVertices); XMVECTOR currVertPos = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f); vertices[0].pos.x = 0.0f; vertices[0].pos.y = 0.0f; vertices[0].pos.z = 1.0f; for (DWORD i = 0; i < latLines - 2; ++i) { spherePitch = (i + 1) * (3.14 / (latLines - 1)); skyRotationX = XMMatrixRotationX(spherePitch); for (DWORD j = 0; j < longLines; ++j) { sphereYaw = j * (6.28 / (longLines)); skyRotationY = XMMatrixRotationZ(sphereYaw); currVertPos = XMVector3TransformNormal(XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f), (skyRotationX * skyRotationY)); currVertPos = XMVector3Normalize(currVertPos); vertices[i*longLines + j + 1].pos.x = XMVectorGetX(currVertPos); vertices[i*longLines + j + 1].pos.y = XMVectorGetY(currVertPos); vertices[i*longLines + j + 1].pos.z = XMVectorGetZ(currVertPos); } } vertices[NumSphereVertices - 1].pos.x = 0.0f; vertices[NumSphereVertices - 1].pos.y = 0.0f; vertices[NumSphereVertices - 1].pos.z = -1.0f; D3D11_BUFFER_DESC vertexBufferDesc; ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc)); vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT; vertexBufferDesc.ByteWidth = sizeof(Vertex)* NumSphereVertices; vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = 0; vertexBufferDesc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA vertexBufferData; ZeroMemory(&vertexBufferData, sizeof(vertexBufferData)); vertexBufferData.pSysMem = &vertices[0]; hr = device->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &sphereVertBuffer); std::vector<DWORD> indices(NumSphereFaces * 3); int k = 0; for (DWORD l = 0; l < longLines - 1; ++l) { indices[k] = 0; indices[k + 1] = l + 1; indices[k + 2] = l + 2; k += 3; } indices[k] = 0; indices[k + 1] = longLines; indices[k + 2] = 1; k += 3; for (DWORD i = 0; i < latLines - 3; ++i) { for (DWORD j = 0; j < longLines - 1; ++j) { indices[k] = i*longLines + j + 1; indices[k + 1] = i*longLines + j + 2; indices[k + 2] = (i + 1)*longLines + j + 1; indices[k + 3] = (i + 1)*longLines + j + 1; indices[k + 4] = i*longLines + j + 2; indices[k + 5] = (i + 1)*longLines + j + 2; k += 6; // next quad } indices[k] = (i*longLines) + longLines; indices[k + 1] = (i*longLines) + 1; indices[k + 2] = ((i + 1)*longLines) + longLines; indices[k + 3] = ((i + 1)*longLines) + longLines; indices[k + 4] = (i*longLines) + 1; indices[k + 5] = ((i + 1)*longLines) + 1; k += 6; } for (DWORD l = 0; l < longLines - 1; ++l) { indices[k] = NumSphereVertices - 1; indices[k + 1] = (NumSphereVertices - 1) - (l + 1); indices[k + 2] = (NumSphereVertices - 1) - (l + 2); k += 3; } indices[k] = NumSphereVertices - 1; indices[k + 1] = (NumSphereVertices - 1) - longLines; indices[k + 2] = NumSphereVertices - 2; D3D11_BUFFER_DESC indexBufferDesc; ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc)); indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; indexBufferDesc.ByteWidth = sizeof(DWORD)* NumSphereFaces * 3; indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; indexBufferDesc.CPUAccessFlags = 0; indexBufferDesc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA iinitData; iinitData.pSysMem = &indices[0]; device->CreateBuffer(&indexBufferDesc, &iinitData, &sphereIndexBuffer); }
void GeometryGenerator::CreateSphere(float radius, UINT sliceCount, UINT stackCount, MeshData& meshData) { meshData.Vertices.clear(); meshData.Indices.clear(); // // Compute the vertices stating at the top pole and moving down the stacks. // // Poles: note that there will be texture coordinate distortion as there is // not a unique point on the texture map to assign to the pole when mapping // a rectangular texture onto a sphere. Vertex topVertex(0.0f, +radius, 0.0f, 0.0f, +1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f); Vertex bottomVertex(0.0f, -radius, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f); meshData.Vertices.push_back(topVertex); float phiStep = XM_PI / stackCount; float thetaStep = 2.0f*XM_PI / sliceCount; // Compute vertices for each stack ring (do not count the poles as rings). for (UINT i = 1; i <= stackCount - 1; ++i) { float phi = i*phiStep; // Vertices of ring. for (UINT j = 0; j <= sliceCount; ++j) { float theta = j*thetaStep; Vertex v; // spherical to cartesian v.Position.x = radius*sinf(phi)*cosf(theta); v.Position.y = radius*cosf(phi); v.Position.z = radius*sinf(phi)*sinf(theta); // Partial derivative of P with respect to theta v.TangentU.x = -radius*sinf(phi)*sinf(theta); v.TangentU.y = 0.0f; v.TangentU.z = +radius*sinf(phi)*cosf(theta); XMVECTOR T = XMLoadFloat3(&v.TangentU); XMStoreFloat3(&v.TangentU, XMVector3Normalize(T)); XMVECTOR p = XMLoadFloat3(&v.Position); XMStoreFloat3(&v.Normal, XMVector3Normalize(p)); v.TexC.x = theta / XM_2PI; v.TexC.y = phi / XM_PI; meshData.Vertices.push_back(v); } } meshData.Vertices.push_back(bottomVertex); // // Compute indices for top stack. The top stack was written first to the vertex buffer // and connects the top pole to the first ring. // for (UINT i = 1; i <= sliceCount; ++i) { meshData.Indices.push_back(0); meshData.Indices.push_back(i + 1); meshData.Indices.push_back(i); } // // Compute indices for inner stacks (not connected to poles). // // Offset the indices to the index of the first vertex in the first ring. // This is just skipping the top pole vertex. UINT baseIndex = 1; UINT ringVertexCount = sliceCount + 1; for (UINT i = 0; i < stackCount - 2; ++i) { for (UINT j = 0; j < sliceCount; ++j) { meshData.Indices.push_back(baseIndex + i*ringVertexCount + j); meshData.Indices.push_back(baseIndex + i*ringVertexCount + j + 1); meshData.Indices.push_back(baseIndex + (i + 1)*ringVertexCount + j); meshData.Indices.push_back(baseIndex + (i + 1)*ringVertexCount + j); meshData.Indices.push_back(baseIndex + i*ringVertexCount + j + 1); meshData.Indices.push_back(baseIndex + (i + 1)*ringVertexCount + j + 1); } } // // Compute indices for bottom stack. The bottom stack was written last to the vertex buffer // and connects the bottom pole to the bottom ring. // // South pole vertex was added last. UINT southPoleIndex = (UINT)meshData.Vertices.size() - 1; // Offset the indices to the index of the first vertex in the last ring. baseIndex = southPoleIndex - ringVertexCount; for (UINT i = 0; i < sliceCount; ++i) { meshData.Indices.push_back(southPoleIndex); meshData.Indices.push_back(baseIndex + i); meshData.Indices.push_back(baseIndex + i + 1); } }
GfxEntityHeightMap::GfxEntityHeightMap(const XMVECTOR& _lowerLeftCorner, float _quadSize, unsigned int _width, unsigned int _length, float* heights) { //compute how many vertices we have m_vertexCount = (_width + 3) * (_length + 3); XMVECTOR* verticesPosition = (XMVECTOR*)_aligned_malloc(sizeof(XMVECTOR)* m_vertexCount, 16);// new XMVECTOR[vertexCount]; XMVECTOR* verticesNormal = (XMVECTOR*)_aligned_malloc(sizeof(XMVECTOR)* m_vertexCount, 16);//new XMVECTOR[vertexCount]; //fill in the array of vertices int vertexId = 0; for (unsigned int row = 0; row <= _length+2; ++row) //loop through each row { int borderedRow = row - 1; XMVECTOR offsetZ = _lowerLeftCorner + (XMVectorSet(0, 0, _quadSize, 0) * (float)borderedRow); for (unsigned int column = 0; column <= _width+2; ++column) //loop through each column { int borderedColumn = column - 1; verticesPosition[vertexId] = offsetZ + (XMVectorSet(_quadSize, 0, 0, 0) * (float)(borderedColumn)) + XMVectorSet(0, heights[vertexId], 0, 0); verticesNormal[vertexId] = XMVectorSet(0, 0, 0, 0); ++vertexId; } } //compute how many triangle and indices we need unsigned int triangleCount = (_width) * (_length) * 2; m_indicesCount = triangleCount * 3; //create the index buffer unsigned int indexId = 0; unsigned long* indices = new unsigned long[m_indicesCount]; unsigned int vertexPerRow = _width + 3; for (unsigned int row = 0; row < _length + 2; ++row) //loop through each row { unsigned int offsetId = row * vertexPerRow; for (unsigned int column = 0; column < _width + 2; ++column)//loop through each column { unsigned int id0 = offsetId + column; unsigned int id1 = offsetId + column + vertexPerRow + 1; unsigned int id2 = offsetId + column + 1; if (row != 0 && row != _length + 1 && column != 0 && column != _width + 1) { //lower right triangle indices[indexId] = id0; indices[indexId + 1] = id1; indices[indexId + 2] = id2; indexId += 3; } //compute normals XMVECTOR v0 = verticesPosition[id0]; XMVECTOR v1 = verticesPosition[id1]; XMVECTOR v2 = verticesPosition[id2]; XMVECTOR normal = XMVector3Cross(v0 - v1, v2 - v1); normal = XMVector3Normalize(normal); verticesNormal[id0] += normal; verticesNormal[id1] += normal; verticesNormal[id2] += normal; id0 = offsetId + column; id1 = offsetId + column + vertexPerRow; id2 = offsetId + column + vertexPerRow + 1; if (row != 0 && row != _length + 1 && column != 0 && column != _width + 1) { indices[indexId] = id0; indices[indexId + 1] = id1; indices[indexId + 2] = id2; indexId += 3; } //compute normals v0 = verticesPosition[id0]; v1 = verticesPosition[id1]; v2 = verticesPosition[id2]; normal = XMVector3Cross(v0 - v1, v2 - v1); normal = XMVector3Normalize(normal); verticesNormal[id0] += normal; verticesNormal[id1] += normal; verticesNormal[id2] += normal; } } //compute normals //unsigned int vertexPerRow = _length + 3; //unsigned int vertexPerColumn = _length + 3; for (unsigned int row = 0; row <= _length+2; ++row) //loop through each row { unsigned int offset = row * (_width + 3); for (unsigned int column = 0; column <= _width+2; ++column)//loop through each column { unsigned int vertexId = offset + column; //case where a vertex is shared by 1 triangle if ((row == 0 && column == _width+2) || //bottom right corner (row == _length+2 && column == 0)) //top left corner { //nothing to do } //case where a vertex is shared by 2 triangles else if ((row == 0 && column == 0) || //bottom left corner (row == _length+2 && column == _width+2)) //top right corner { verticesNormal[vertexId] = verticesNormal[vertexId] / 2; } //case where a vertex is shared by 3 triangles else if (row == 0 || row == _length+2 || column == 0 || column == _width+2) //border { verticesNormal[vertexId] = verticesNormal[vertexId] / 3; } else //the inside of the height map. Each vertex is shared by 6 triangles { verticesNormal[vertexId] = verticesNormal[vertexId] / 6; } verticesNormal[vertexId] = XMVector3Normalize(verticesNormal[vertexId]); } } //fill in dx structures VertexPositionNormalColor* vertices = new VertexPositionNormalColor[m_vertexCount]; for (unsigned int i = 0; i < m_vertexCount; ++i) { XMStoreFloat3(&vertices[i].position, verticesPosition[i]); XMStoreFloat3(&vertices[i].normal, verticesNormal[i]); XMFLOAT4 myColor; myColor.x = 0.4f; myColor.y = 0.4f; myColor.z = abs((vertices[i].position.y + 200) / 1000.f)+0.1f; myColor.w = 1.f; vertices[i].color = myColor; } // Set up the description of the static vertex buffer. D3D11_BUFFER_DESC vertexBufferDesc; vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT; vertexBufferDesc.ByteWidth = sizeof(VertexPositionNormalColor)* m_vertexCount; vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = 0; vertexBufferDesc.MiscFlags = 0; vertexBufferDesc.StructureByteStride = 0; // Give the subresource structure a pointer to the vertex data. D3D11_SUBRESOURCE_DATA vertexData; vertexData.pSysMem = vertices; vertexData.SysMemPitch = 0; vertexData.SysMemSlicePitch = 0; // Now create the vertex buffer. HRESULT result = GRAPHICS->getDirectXWrapper()->getDevice()->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer); if (FAILED(result)) throw; // Set up the description of the static index buffer. D3D11_BUFFER_DESC indexBufferDesc; indexBufferDesc.Usage = D3D11_USAGE_DEFAULT; indexBufferDesc.ByteWidth = sizeof(unsigned long)* m_indicesCount; indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; indexBufferDesc.CPUAccessFlags = 0; indexBufferDesc.MiscFlags = 0; indexBufferDesc.StructureByteStride = 0; // Give the subresource structure a pointer to the index data. D3D11_SUBRESOURCE_DATA indexData; indexData.pSysMem = indices; indexData.SysMemPitch = 0; indexData.SysMemSlicePitch = 0; // Create the index buffer. result = GRAPHICS->getDirectXWrapper()->getDevice()->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer); if (FAILED(result)) throw; // Release the arrays now that the vertex and index buffers have been created and loaded. _aligned_free(verticesPosition); _aligned_free(verticesNormal); delete[] vertices; delete[] indices; m_effect = EFFECT->getBasicEffect(); m_inputLayout = EFFECT->getInputLayout(); }
void GeometryGenerator::CreateGeosphere(float radius, UINT numSubdivisions, MeshData& meshData) { // Put a cap on the number of subdivisions. numSubdivisions = MathHelper::Min(numSubdivisions, 5u); // Approximate a sphere by tessellating an icosahedron. const float X = 0.525731f; const float Z = 0.850651f; XMFLOAT3 pos[12] = { XMFLOAT3(-X, 0.0f, Z), XMFLOAT3(X, 0.0f, Z), XMFLOAT3(-X, 0.0f, -Z), XMFLOAT3(X, 0.0f, -Z), XMFLOAT3(0.0f, Z, X), XMFLOAT3(0.0f, Z, -X), XMFLOAT3(0.0f, -Z, X), XMFLOAT3(0.0f, -Z, -X), XMFLOAT3(Z, X, 0.0f), XMFLOAT3(-Z, X, 0.0f), XMFLOAT3(Z, -X, 0.0f), XMFLOAT3(-Z, -X, 0.0f) }; DWORD k[60] = { 1,4,0, 4,9,0, 4,5,9, 8,5,4, 1,8,4, 1,10,8, 10,3,8, 8,3,5, 3,2,5, 3,7,2, 3,10,7, 10,6,7, 6,11,7, 6,0,11, 6,1,0, 10,1,6, 11,0,9, 2,11,9, 5,2,9, 11,2,7 }; meshData.Vertices.resize(12); meshData.Indices.resize(60); for (UINT i = 0; i < 12; ++i) meshData.Vertices[i].Position = pos[i]; for (UINT i = 0; i < 60; ++i) meshData.Indices[i] = k[i]; for (UINT i = 0; i < numSubdivisions; ++i) Subdivide(meshData); // Project vertices onto sphere and scale. for (UINT i = 0; i < meshData.Vertices.size(); ++i) { // Project onto unit sphere. XMVECTOR n = XMVector3Normalize(XMLoadFloat3(&meshData.Vertices[i].Position)); // Project onto sphere. XMVECTOR p = radius*n; XMStoreFloat3(&meshData.Vertices[i].Position, p); XMStoreFloat3(&meshData.Vertices[i].Normal, n); // Derive texture coordinates from spherical coordinates. float theta = MathHelper::AngleFromXY( meshData.Vertices[i].Position.x, meshData.Vertices[i].Position.z); float phi = acosf(meshData.Vertices[i].Position.y / radius); meshData.Vertices[i].TexC.x = theta / XM_2PI; meshData.Vertices[i].TexC.y = phi / XM_PI; // Partial derivative of P with respect to theta meshData.Vertices[i].TangentU.x = -radius*sinf(phi)*sinf(theta); meshData.Vertices[i].TangentU.y = 0.0f; meshData.Vertices[i].TangentU.z = +radius*sinf(phi)*cosf(theta); XMVECTOR T = XMLoadFloat3(&meshData.Vertices[i].TangentU); XMStoreFloat3(&meshData.Vertices[i].TangentU, XMVector3Normalize(T)); } }
void GeometryGenerator::CreateCylinder(float bottomRadius, float topRadius, float height, UINT sliceCount, UINT stackCount, MeshData& meshData) { meshData.Vertices.clear(); meshData.Indices.clear(); // // Build Stacks. // float stackHeight = height / stackCount; // Amount to increment radius as we move up each stack level from bottom to top. float radiusStep = (topRadius - bottomRadius) / stackCount; UINT ringCount = stackCount + 1; // Compute vertices for each stack ring starting at the bottom and moving up. for (UINT i = 0; i < ringCount; ++i) { float y = -0.5f*height + i*stackHeight; float r = bottomRadius + i*radiusStep; // vertices of ring float dTheta = 2.0f*XM_PI / sliceCount; for (UINT j = 0; j <= sliceCount; ++j) { Vertex vertex; float c = cosf(j*dTheta); float s = sinf(j*dTheta); vertex.Position = XMFLOAT3(r*c, y, r*s); vertex.TexC.x = (float)j / sliceCount; vertex.TexC.y = 1.0f - (float)i / stackCount; // Cylinder can be parameterized as follows, where we introduce v // parameter that goes in the same direction as the v tex-coord // so that the bitangent goes in the same direction as the v tex-coord. // Let r0 be the bottom radius and let r1 be the top radius. // y(v) = h - hv for v in [0,1]. // r(v) = r1 + (r0-r1)v // // x(t, v) = r(v)*cos(t) // y(t, v) = h - hv // z(t, v) = r(v)*sin(t) // // dx/dt = -r(v)*sin(t) // dy/dt = 0 // dz/dt = +r(v)*cos(t) // // dx/dv = (r0-r1)*cos(t) // dy/dv = -h // dz/dv = (r0-r1)*sin(t) // This is unit length. vertex.TangentU = XMFLOAT3(-s, 0.0f, c); float dr = bottomRadius - topRadius; XMFLOAT3 bitangent(dr*c, -height, dr*s); XMVECTOR T = XMLoadFloat3(&vertex.TangentU); XMVECTOR B = XMLoadFloat3(&bitangent); XMVECTOR N = XMVector3Normalize(XMVector3Cross(T, B)); XMStoreFloat3(&vertex.Normal, N); meshData.Vertices.push_back(vertex); } } // Add one because we duplicate the first and last vertex per ring // since the texture coordinates are different. UINT ringVertexCount = sliceCount + 1; // Compute indices for each stack. for (UINT i = 0; i < stackCount; ++i) { for (UINT j = 0; j < sliceCount; ++j) { meshData.Indices.push_back(i*ringVertexCount + j); meshData.Indices.push_back((i + 1)*ringVertexCount + j); meshData.Indices.push_back((i + 1)*ringVertexCount + j + 1); meshData.Indices.push_back(i*ringVertexCount + j); meshData.Indices.push_back((i + 1)*ringVertexCount + j + 1); meshData.Indices.push_back(i*ringVertexCount + j + 1); } } BuildCylinderTopCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData); BuildCylinderBottomCap(bottomRadius, topRadius, height, sliceCount, stackCount, meshData); }
bool FireBallParticles::Update(FXMVECTOR newPos, float fireballRadius, float dt, ID3D11DeviceContext* context) { if (!mProperties.isFire || mIsAllParticlesDead) { return true; } XMVECTOR nPos = newPos; if (mTweenPoints.size() > 0) { nPos = XMLoadFloat3(&mCurrTweenPoint); UpdateCurrentTweenPoint(dt); } XMFLOAT3 fVel3; float pSize; bool isParticleStillAlive = false; for (int i = 0; i < mFireBallParticles.size(); ++i) { XMVECTOR pos = XMLoadFloat3(&mFireBallParticles[i].pos); XMVECTOR vel = XMLoadFloat3(&mFireBallParticles[i].vel); mFireBallParticles[i].age += dt; if (mProperties.isOneShot && (mFireBallParticles[i].age >= mFireBallParticles[i].lifetime)) { continue; } else if (mFireBallParticles[i].age <= mFireBallParticles[i].lifetime) { isParticleStillAlive = true; } else if (!mProperties.isOneShot && (mFireBallParticles[i].age >= mFireBallParticles[i].lifetime)) { isParticleStillAlive = true; vel = XMVector3Normalize(XMVectorSet(MathHelper::RandF(-1.0f, 1.0f), MathHelper::RandF(-1.0f, 1.0f), MathHelper::RandF(-1.0f, 1.0f), 0.0f)) * fireballRadius; XMStoreFloat3(&mFireBallParticles[i].pos, nPos + vel); fVel3 = GetVelocity(); vel = XMVector3Normalize(XMVectorSet(fVel3.x, fVel3.y, fVel3.z, 0.0f)); float speedMult = GetSpeedMultiplier(); if (MathHelper::RandF() > 0.50f) { if (MathHelper::RandF() > 0.50f) { vel.m128_f32[0] += MathHelper::RandF(-0.4f, 0.4f); //vel.m128_f32[0] *= MathHelper::RandF(-0.06f, 0.06f); //vel.m128_f32[2] *= MathHelper::RandF(-0.06f, 0.06f); } else { vel.m128_f32[2] += MathHelper::RandF(-0.4f, 0.4f); //vel.m128_f32[0] *= MathHelper::RandF(-0.06f, 0.06f); //vel.m128_f32[2] *= MathHelper::RandF(-0.06f, 0.06f); } } XMStoreFloat3(&mFireBallParticles[i].vel, vel * speedMult); pSize = GetSize(); mFireBallParticles[i].size.x = pSize; mFireBallParticles[i].size.y = pSize; mFireBallParticles[i].age = 0.0f; mFireBallParticles[i].lifetime = GetLifetime(); pos = XMLoadFloat3(&mFireBallParticles[i].pos); vel = XMLoadFloat3(&mFireBallParticles[i].vel); } if (pos.m128_f32[1] < (nPos.m128_f32[1] + (fireballRadius * 0.60f))) { XMVECTOR s1Center = nPos; float s1Radius = fireballRadius; float currOverLap = 0.0f; XMVECTOR correction = XMVectorZero(); XMVECTOR d = s1Center - pos; float distance = sqrt((d.m128_f32[0] * d.m128_f32[0]) /*+ (d.m128_f32[1] * d.m128_f32[1])*/ + (d.m128_f32[2] * d.m128_f32[2])); //Magnitude of the difference float overLap = s1Radius - distance; if (overLap > currOverLap) // Have Collision { currOverLap = overLap; correction = XMVector3Normalize(d) * currOverLap; //correct collision by moving sphere out of box } pos += correction; } pos = pos + vel; XMStoreFloat3(&mFireBallParticles[i].pos, pos); } if (isParticleStillAlive) { UpdateFireBallParticleVB(context); } else { mIsAllParticlesDead = true; if (mProperties.isOneShot) { ResetParticles(); } } return false; }
void Player::HandleInput(float deltatime) { auto i = System::GetInput(); int x, y; XMVECTOR moveVec = XMVectorZero(); XMVECTOR forward = _builder->GetEntityController()->Transform()->GetDirection(_camera); XMVECTOR right = _builder->GetEntityController()->Transform()->GetRight(_camera); XMVECTOR up = _builder->GetEntityController()->Transform()->GetUp(_camera); bool change = false; i->GetMouseDiff(x, y); if (x != 0) _builder->GetEntityController()->Transform()->RotateYaw(_camera, x * 0.1f); if (y != 0) _builder->GetEntityController()->Transform()->RotatePitch(_camera, y * 0.1f); if (i->IsKeyDown(VK_W)) { moveVec += forward; change = true; } if (i->IsKeyDown(VK_S)) { moveVec -= forward; change = true; } if (i->IsKeyDown(VK_A)) { moveVec -= right; change = true; } if (i->IsKeyDown(VK_D)) { moveVec += right; change = true; } //if (i->IsKeyDown(VK_SHIFT)) //{ // moveVec += up; // change = true; //} //if (i->IsKeyDown(VK_CONTROL)) //{ // moveVec -= up; // change = true; //} if (change) { if (i->IsKeyDown(VK_SHIFT) && _currentLight-_dashCost >= 0.0f && !_activeDash) { _activeDash = true; _lightDownBy += _dashCost; XMStoreFloat3(&_dashDir, XMVector3Normalize(moveVec)); _builder->Animation()->PlayAnimation(_camera, "dash", 2.0f); } else _builder->GetEntityController()->Transform()->MoveAlongVector(_camera, XMVector3Normalize(moveVec), _speedFactor*deltatime); } if (i->IsKeyPushed(VK_T)) { float offset = (_reservedLight * _maxLight / 20.0f)*BAR_MAXSIZE*_screenPercentWidth; _reservedLight = 0.5f; float delta = (_reservedLight * _maxLight / 20.0f)*BAR_MAXSIZE*_screenPercentWidth - offset; _lightDownBy += _maxLight*0.5f; _builder->Animation()->PlayAnimation(_lightReservedBar, "update", delta, offset); } if (i->IsKeyPushed(VK_Q)) { _ChangePower(); } if (i->IsMouseKeyDown(VK_LBUTTON)) { if (_weapons[_currentWep]->Shoot(_camera)) { _shotsFired++; } } if (!_weapons[_currentWep]->HasAmmo()) { _weapons[_currentWep]->setActive(false); _currentWep = Weapons::Basic; _weapons[_currentWep]->setActive(true); } int sde = 0; if (i->IsScrollUp(sde)) { Weapons c = _currentWep << 1; if (c._flags == 0) c._flags = 1; auto& find = _weapons.find(c); while (find == _weapons.end() || !find->second->HasAmmo()) { c._flags = c._flags << 1; if (c._flags == 0) c._flags = 1; find = _weapons.find(c); } if (!(c == _currentWep)) { _weapons[_currentWep]->setActive(false); _currentWep = c; _weapons[_currentWep]->setActive(true); } } if(i->IsScrollDown(sde)) { Weapons c = _currentWep >> 1; if (c._flags == 0) c._flags = 1 << (sizeof(unsigned int)*8-1); auto& find = _weapons.find(c); while (find == _weapons.end() || !find->second->HasAmmo()) { c._flags = c._flags >> 1; if (c._flags == 0) c._flags = 1 << (sizeof(unsigned int) * 8 - 1); find = _weapons.find(c); } if (!(c == _currentWep)) { _weapons[_currentWep]->setActive(false); _currentWep = c; _weapons[_currentWep]->setActive(true); } }
void Camera::Update() { int dMouseX = 0; int dMouseY = 0; if( InputManager::Instance()->IsMouseButtonDown(0)) { InputManager::Instance()->GetMouseMove(dMouseX, dMouseY); m_Yaw += dMouseX * m_RotationSpeed * XM_PI/180; m_Pitch += dMouseY * m_RotationSpeed * XM_PI/180; } CXMVECTOR Forward = XMVectorSet(0.0f, 0.0f, 1.0f, 1.0f); CXMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f); CXMVECTOR Right = XMVectorSet(1.0f, 0.0f, 0.0f, 1.0f); //XMMATRIX rotation = XMMatrixRotationAxis(Up, m_Yaw); XMMATRIX rotation = XMMatrixRotationRollPitchYaw(m_Pitch, m_Yaw, 0.0f); XMVECTOR position = XMLoadFloat3(&m_Position); //XMVECTOR quaternion = XMVectorSet(0.0f, m_Yaw, 0.0f, 1.0f); XMVECTOR transformedForward = XMVector3Transform(Forward, rotation); XMVector3Normalize(transformedForward); XMVECTOR transformedRight = XMVector3Transform(Right, rotation); XMVector3Normalize(transformedRight); // Compute view matrix. //XMFLOAT3 lookAt(m_Position); //lookAt.z+=1.0f; //XMVECTOR At = XMLoadFloat3(&lookAt); //XMVectorSet(0.0f, -1.0f, 0.0f, 1.0f); /*XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f);*/ if ( InputManager::Instance()->IsKeyDown(DIK_W)) { //m_Position.z += 1.0f; position += transformedForward * m_MovementSpeed; } if ( InputManager::Instance()->IsKeyDown(DIK_S)) { position -= transformedForward * m_MovementSpeed; } if ( InputManager::Instance()->IsKeyDown(DIK_A)) { position -= transformedRight * m_MovementSpeed; } if ( InputManager::Instance()->IsKeyDown(DIK_D)) { position += transformedRight * m_MovementSpeed; } if ( InputManager::Instance()->IsKeyDown(DIK_Q)) { position += Up * m_MovementSpeed; } if ( InputManager::Instance()->IsKeyDown(DIK_E)) { position -= Up * m_MovementSpeed; } CXMMATRIX view = XMMatrixTranspose(XMMatrixLookAtLH(position, transformedForward + position, Up)); XMStoreFloat4x4(&m_ViewMatrix, view); // Compute projection matrix. CXMMATRIX proj = XMMatrixTranspose(XMMatrixPerspectiveFovLH(XM_PIDIV2, Engine::Instance()->GetWidth()/(FLOAT)Engine::Instance()->GetHeight(), 0.01f, 10000.0f)); XMStoreFloat4x4(&m_ProjectionMatrix, proj); // Compute invert view projection matrix. CXMMATRIX invertViewProj = XMMatrixInverse(nullptr, XMMatrixMultiply(view, proj)); XMStoreFloat4x4(&m_InvertViewProjectionMatrix, invertViewProj); XMStoreFloat3(&m_Position, position); }
EngineState::EngineState() : #if defined(_PROFILE) | defined(_DEBUG) m_displayShadowMaps(false), m_displayShadowFrustum(false), m_displayShadowBuffer(false), #endif m_BackBufferDesc({ 1280, 720, DXGI_FORMAT_R16G16B16A16_FLOAT, { 1, 0 } }), m_Viewport({ 0.0f, 0.0f, static_cast<float>(m_BackBufferDesc.Width), static_cast<float>(m_BackBufferDesc.Height), 0.0f, 1.0f}), m_Light(-0.5f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f), m_LightDirection(XMVector3Normalize(XMVectorSet(1.f, 0.5f, 0.3f, 0.f))), m_fovy(XM_PI / 3.f), m_aspect(m_Viewport.Width / m_Viewport.Height), m_znear(0.1f), m_zfar(200.f), m_LightShafts(true), m_DepthOfField(true), m_Bloom(true), m_AmbientOcclusion(true), m_Fxaa(true), m_ShadowMapSize(2048), m_ShadowMapCount(3), m_ShadowMapQuality(1), m_ShadowMapType(2), m_fullScreen(false), m_vsync(true), m_refreshRate({60,1}) { NvGsaApplication app; NvGsaStatus status; const NvGsaNamedOption *options = NULL; size_t numOptions = 0; const NvGsaResolution *resolutions = NULL; size_t numResolutions = 0; NvGsaVersion runtimeVersion = GFSDK_GSA_GetVersion(); // Print the GSA compile time version wprintf(L"Compiled against GSA version: "); printGsaVersion(&NvGsaCurrentVersion); wprintf(L"\n"); // Print the GSA run time version wprintf(L"Running against GSA version: "); printGsaVersion(&runtimeVersion); wprintf(L"\n"); // Initialize the application LPWSTR *szArglist; int nArgs = 0; szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs); if (nArgs < 1 || !initApplication(&app, szArglist[0])) { wprintf(L"Failed to initialize the application, exiting!"); return; } GlobalFree(szArglist); // Initialize the GSA SDK status = GFSDK_GSA_InitializeSDK(&app, &NvGsaCurrentVersion); releaseApplication(&app); if (status != NV_GSA_STATUS_OK) { wprintf(L"Failed to initialize the GSA SDK, exiting!"); return; } if (initOptions(&options, &numOptions) && initResolutions(&resolutions, &numResolutions)) { //status = GFSDK_GSA_SaveConfigFile(NV_GSA_SAVE_ALL); NvGsaResolution currentResolution; size_t i; // Register the options for (i = 0; i < numOptions; ++i) { GFSDK_GSA_RegisterOption(&options[i]); } // Register the resolutions GFSDK_GSA_RegisterResolutions(resolutions, (int)numResolutions); // Load the config file status = GFSDK_GSA_LoadConfigFile(); if (status == NV_GSA_STATUS_FILENOTFOUND) { GFSDK_GSA_SetResolution(&resolutions[0]); } // Print and cycle the options for (i = 0; i < numOptions; ++i) { NvGsaVariant value; value.type = options[i].value.type; status = GFSDK_GSA_GetOptionValue(&value, options[i].name); if (status == NV_GSA_STATUS_OK) { switch (str2int(options[i].name)) { case str2int(L"Field_Of_View"): m_fovy = value.asFloat; break; case str2int(L"Near_Plane"): m_znear = value.asFloat; break; case str2int(L"Far_Plane"): m_zfar = value.asFloat; break; case str2int(L"LightShafts"): m_LightShafts = value.asBool; break; case str2int(L"DepthOfField"): m_DepthOfField = value.asBool; break; case str2int(L"Bloom"): m_Bloom = value.asBool; break; case str2int(L"AmbientOcclusion"): m_AmbientOcclusion = value.asBool; break; case str2int(L"Fxaa"): m_Fxaa = value.asBool; break; case str2int(L"FullScreen"): m_fullScreen = value.asBool; break; case str2int(L"V-Sync"): m_vsync = value.asBool; break; case str2int(L"ShadowMapSize"): switch (str2int(value.asEnum)) { case str2int(L"512"): m_ShadowMapSize = 512; break; case str2int(L"1024"): m_ShadowMapSize = 1024; break; case str2int(L"2048"): m_ShadowMapSize = 2048; break; case str2int(L"4096"): m_ShadowMapSize = 4096; break; } break; case str2int(L"ShadowMapCount"): m_ShadowMapCount = value.asInt; break; case str2int(L"ShadowMapQuality"): switch (str2int(value.asEnum)) { case str2int(L"Low_Hard"): m_ShadowMapQuality = 0; m_ShadowMapType = 0; break; case str2int(L"Medium_Hard"): m_ShadowMapQuality = 1; m_ShadowMapType = 0; break; case str2int(L"High_Hard"): m_ShadowMapQuality = 2; m_ShadowMapType = 0; break; case str2int(L"Low_PCF"): m_ShadowMapQuality = 0; m_ShadowMapType = 1; break; case str2int(L"Medium_PCF"): m_ShadowMapQuality = 1; m_ShadowMapType = 1; break; case str2int(L"High_PCF"): m_ShadowMapQuality = 2; m_ShadowMapType = 1; break; case str2int(L"Low_PCSS"): m_ShadowMapQuality = 0; m_ShadowMapType = 2; break; case str2int(L"Medium_PCSS"): m_ShadowMapQuality = 1; m_ShadowMapType = 2; break; case str2int(L"High_PCSS"): m_ShadowMapQuality = 2; m_ShadowMapType = 2; break; } break; } GFSDK_GSA_ReleaseVariant(&value); } } // Print and increment the resolution status = GFSDK_GSA_GetResolution(¤tResolution); if (status == NV_GSA_STATUS_OK) { m_refreshRate.Numerator = (UINT)round(currentResolution.refreshRate); WindowSizeChanged(currentResolution.width, currentResolution.height); } } // Cleanup releaseOptions(options); releaseResolutions(resolutions); m_Camera.SetProjParams(m_fovy, m_aspect, m_znear, m_zfar); m_Camera.SetViewParams(XMVectorSet(0.f, 0.f, 0.f, 1.f), XMVectorSet(0.f, 0.f, 1.f, 1.f)); }
void CalcTangentAndBinormal( SimpleVertexNormal& p0, SimpleVertexNormal& p1, SimpleVertexNormal& p2 ) { // 5次元→3次元頂点に XMVECTOR CP0[3] = { XMVectorSet(p0.Pos.x, p0.Tex.x, p0.Tex.y,1), XMVectorSet(p0.Pos.y, p0.Tex.x, p0.Tex.y,1), XMVectorSet(p0.Pos.z, p0.Tex.x, p0.Tex.y,1), }; XMVECTOR CP1[3] = { XMVectorSet(p1.Pos.x, p1.Tex.x, p1.Tex.y, 1), XMVectorSet(p1.Pos.y, p1.Tex.x, p1.Tex.y, 1), XMVectorSet(p1.Pos.z, p1.Tex.x, p1.Tex.y, 1), }; XMVECTOR CP2[3] = { XMVectorSet(p2.Pos.x, p2.Tex.x, p2.Tex.y, 1), XMVectorSet(p2.Pos.y, p2.Tex.x, p2.Tex.y, 1), XMVectorSet(p2.Pos.z, p2.Tex.x, p2.Tex.y, 1), }; // 平面パラメータからUV軸座標算出 float U[3], V[3]; for (int i = 0; i < 3; ++i) { XMVECTOR V1 = CP1[i] - CP0[i]; XMVECTOR V2 = CP2[i] - CP1[i]; XMVECTOR ABC; ABC = XMVector3Cross(V1, V2); if (ABC.x == 0.0f) { // やばいす! // ポリゴンかUV上のポリゴンが縮退してます! //_ASSERT(0); //memset(outTangent, 0, sizeof(D3DXVECTOR3)); //memset(outBinormal, 0, sizeof(D3DXVECTOR3)); p0.Binormal = XMFLOAT3(1, 0, 0); p1.Binormal = XMFLOAT3(1, 0, 0); p2.Binormal = XMFLOAT3(1, 0, 0); p0.Tangent = XMFLOAT3(0,1,0); p1.Tangent = XMFLOAT3(0,1,0); p2.Tangent = XMFLOAT3(0,1,0); return; } U[i] = -ABC.y / ABC.x; V[i] = -ABC.z / ABC.x; } XMVECTOR tan = XMVectorSet(U[0], U[1], U[2], 1); XMVECTOR bin = -XMVectorSet(V[0], V[1], V[2], 1); // 正規化します tan = XMVector3Normalize(tan); bin = XMVector3Normalize(bin); p0.Binormal = XMFLOAT3(bin.x, bin.y, bin.z); p1.Binormal = XMFLOAT3(bin.x, bin.y, bin.z); p2.Binormal = XMFLOAT3(bin.x, bin.y, bin.z); p0.Tangent = XMFLOAT3(tan.x, tan.y, tan.z); p1.Tangent = XMFLOAT3(tan.x, tan.y, tan.z); p2.Tangent = XMFLOAT3(tan.x, tan.y, tan.z); }
Vector Vector::normalize(const Vector& vec) { return Vector(XMVector3Normalize(vec.getXMVector())); }
void AmbientOcclusionApp::BuildVertexAmbientOcclusion( std::vector<Vertex::AmbientOcclusion>& vertices, const std::vector<UINT>& indices) { UINT vcount = vertices.size(); UINT tcount = indices.size()/3; std::vector<XMFLOAT3> positions(vcount); for(UINT i = 0; i < vcount; ++i) positions[i] = vertices[i].Pos; Octree octree; octree.Build(positions, indices); // For each vertex, count how many triangles contain the vertex. std::vector<int> vertexSharedCount(vcount); for(UINT i = 0; i < tcount; ++i) { UINT i0 = indices[i*3+0]; UINT i1 = indices[i*3+1]; UINT i2 = indices[i*3+2]; XMVECTOR v0 = XMLoadFloat3(&vertices[i0].Pos); XMVECTOR v1 = XMLoadFloat3(&vertices[i1].Pos); XMVECTOR v2 = XMLoadFloat3(&vertices[i2].Pos); XMVECTOR edge0 = v1 - v0; XMVECTOR edge1 = v2 - v0; XMVECTOR normal = XMVector3Normalize(XMVector3Cross(edge0, edge1)); XMVECTOR centroid = (v0 + v1 + v2)/3.0f; // Offset to avoid self intersection. centroid += 0.001f*normal; const int NumSampleRays = 32; float numUnoccluded = 0; for(int j = 0; j < NumSampleRays; ++j) { XMVECTOR randomDir = MathHelper::RandHemisphereUnitVec3(normal); // TODO: Technically we should not count intersections that are far // away as occluding the triangle, but this is OK for demo. if( !octree.RayOctreeIntersect(centroid, randomDir) ) { numUnoccluded++; } } float ambientAccess = numUnoccluded / NumSampleRays; // Average with vertices that share this face. vertices[i0].AmbientAccess += ambientAccess; vertices[i1].AmbientAccess += ambientAccess; vertices[i2].AmbientAccess += ambientAccess; vertexSharedCount[i0]++; vertexSharedCount[i1]++; vertexSharedCount[i2]++; } // Finish average by dividing by the number of samples we added. for(UINT i = 0; i < vcount; ++i) { vertices[i].AmbientAccess /= vertexSharedCount[i]; } }
//jingz //todo void Waves::Update(float dt) { static float t = 0.0f; // Accumulate time t += dt; if ( t>= m_fTimeStep) { for (UINT i = 1; i < m_uRows - 1;++i) { for (UINT j = 1; j < m_uCols - 1;++j) { // After this update we will be discarding the old previous // buffer, so overwrite that buffer with the new update. // Note how we can do this inplace (read/write to same element) // because we won't need prev_ij again and the assignment happens last. // Note j indexes x and i indexes z: h(x_j, z_i, t_k) // Moreover, our +z axis goes "down"; this is just to // keep consistent with our row indices going down. m_pPreSolution[i*m_uCols + j].y = m_fK1 * m_pPreSolution[i*m_uCols + j].y + m_fK2 * m_pCurSolution[i*m_uCols + j].y + m_fK3 * ( m_pCurSolution[(i + 1)*m_uCols + j].y + m_pCurSolution[(i - 1)*m_uCols + j].y + m_pCurSolution[i*m_uCols + j + 1].y + m_pCurSolution[i*m_uCols + j - 1].y ); } } std::swap(m_pCurSolution, m_pPreSolution); //t -= m_fTimeStep; t = 0.0f; //jingz 感觉原作者的代码不是给人看的,有种行列故意倒换的感觉 // // Compute normals using finite difference scheme. // for (UINT i = 1; i < m_uRows - 1;++i) { for (UINT j = 1; j < m_uCols - 1;++j) { float left = m_pCurSolution[i*m_uCols + j - 1].y; float right = m_pCurSolution[i*m_uCols + j + 1].y; float top = m_pCurSolution[(i-1)*m_uCols + j].y; float bottom = m_pCurSolution[(i+1)*m_uCols + j].y; m_pNormals[i*m_uCols + j].x = -right + left; m_pNormals[i*m_uCols + j].y = 2.0f*m_fSpatialStep; m_pNormals[i*m_uCols + j].z = bottom - top; XMVECTOR n = XMVector3Normalize(XMLoadFloat3((&m_pNormals[i*m_uCols + j]))); XMStoreFloat3(&m_pNormals[i*m_uCols + j], n); m_pTangents[i*m_uCols + j] = XMFLOAT3(2.0f*m_fSpatialStep, right - left, 0.0f); XMVECTOR t = XMVector3Normalize(XMLoadFloat3(&m_pTangents[i*m_uCols + j])); XMStoreFloat3(&m_pTangents[i*m_uCols + j], t); } } } }
void LightingApp::UpdateScene(float dt) { // Convert Spherical to Cartesian coordinates. float x = mRadius*sinf(mPhi)*cosf(mTheta); float z = mRadius*sinf(mPhi)*sinf(mTheta); float y = mRadius*cosf(mPhi); mEyePosW = XMFLOAT3(x, y, z); // Build the view matrix. XMVECTOR pos = XMVectorSet(x, y, z, 1.0f); XMVECTOR target = XMVectorZero(); XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); XMMATRIX V = XMMatrixLookAtLH(pos, target, up); XMStoreFloat4x4(&mView, V); // // Every quarter second, generate a random wave. // static float t_base = 0.0f; if( (mTimer.TotalTime() - t_base) >= 0.25f ) { t_base += 0.25f; DWORD i = 5 + rand() % (mWaves.RowCount()-10); DWORD j = 5 + rand() % (mWaves.ColumnCount()-10); float r = MathHelper::RandF(1.0f, 2.0f); mWaves.Disturb(i, j, r); } mWaves.Update(dt); // // Update the wave vertex buffer with the new solution. // D3D11_MAPPED_SUBRESOURCE mappedData; HR(md3dImmediateContext->Map(mWavesVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedData)); Vertex* v = reinterpret_cast<Vertex*>(mappedData.pData); for(UINT i = 0; i < mWaves.VertexCount(); ++i) { v[i].Pos = mWaves[i]; v[i].Normal = mWaves.Normal(i); } md3dImmediateContext->Unmap(mWavesVB, 0); // // Animate the lights. // // Circle light over the land surface. mPointLight.Position.x = 70.0f*cosf( 0.2f*mTimer.TotalTime() ); mPointLight.Position.z = 70.0f*sinf( 0.2f*mTimer.TotalTime() ); mPointLight.Position.y = MathHelper::Max(GetHillHeight(mPointLight.Position.x, mPointLight.Position.z), -3.0f) + 10.0f; // The spotlight takes on the camera position and is aimed in the // same direction the camera is looking. In this way, it looks // like we are holding a flashlight. mSpotLight.Position = mEyePosW; XMStoreFloat3(&mSpotLight.Direction, XMVector3Normalize(target - pos)); }
bool CollisionMesh::CheckCollisionsCustom(CollisionMesh &otherMesh) { bool collision = false; std::vector<XMFLOAT3> convexHull; std::vector<VPCNTDesc> vertices = GetVertices(); std::vector<VPCNTDesc> otherVertices = otherMesh.GetVertices(); XMMATRIX otherWorld = otherMesh.GetWorldTransform(); XMMATRIX world = GetWorldTransform(); XMFLOAT3 origin = XMFLOAT3(0.0f, 0.0f, 0.0f); // Create a vector to ease the inversion calculation (we want the opposite direction for the translation vector). XMVECTOR inverse = XMVectorSet(-1.0f, -1.0f, -1.0f, 0.0f); XMVECTOR ourOriginDisplacement = XMVector3Transform(XMVectorSet(origin.x, origin.y, origin.z, 0.0f), world); XMMATRIX ourOriginTransform = XMMatrixTranslationFromVector(XMVectorMultiply(ourOriginDisplacement, inverse)); // This is used for the purposes of moving the normals of the other object back to around (0, 0, 0). XMVECTOR theirOriginDisplacement = XMVector3Transform(XMVectorSet(origin.x, origin.y, origin.z, 0.0f), otherWorld); XMMATRIX theirOriginTransform = XMMatrixTranslationFromVector(XMVectorMultiply(theirOriginDisplacement, inverse)); XMMATRIX ourOriginTranslatedWorld = world * ourOriginTransform; XMMATRIX theirOriginTranslatedWorld = otherWorld * ourOriginTransform; XMMATRIX theirOriginTranslatedWorldNormalAdjustment = theirOriginTransform * otherWorld; // Pre-multiply the model's vertices so as to avoid transforming them during comparison. for (int vertIndex = 0; vertIndex < vertices.size(); vertIndex++) { XMStoreFloat3(&vertices[vertIndex].Position, XMVector3Transform(XMLoadFloat3(&vertices[vertIndex].Position), ourOriginTranslatedWorld)); XMStoreFloat3(&vertices[vertIndex].Normal, XMVector3Transform(XMLoadFloat3(&vertices[vertIndex].Normal), ourOriginTranslatedWorld)); } for (int otherVertIndex = 0; otherVertIndex < otherVertices.size(); otherVertIndex++) { XMStoreFloat3(&otherVertices[otherVertIndex].Position, XMVector3Transform(XMLoadFloat3(&otherVertices[otherVertIndex].Position), theirOriginTranslatedWorld)); XMStoreFloat3(&otherVertices[otherVertIndex].Normal, XMVector3Transform(XMLoadFloat3(&otherVertices[otherVertIndex].Normal), theirOriginTranslatedWorldNormalAdjustment)); } int potentialCollisions = 0; std::vector<XMFLOAT3> positions; // Now that the pre-multiplication is done, time to do our first-case checking: are we inside of it? for (int vertIndex = 0; vertIndex < vertices.size(); vertIndex++) { bool localCollision = true; XMVECTOR ourVertex = XMLoadFloat3(&vertices[vertIndex].Position); XMVECTOR ourNormal = XMLoadFloat3(&vertices[vertIndex].Normal); // For each vertex in our mesh, we'll check to see if it resides inside our other mesh. for (int otherVertIndex = 0; otherVertIndex < otherVertices.size(); otherVertIndex++) { XMVECTOR otherVertex = XMLoadFloat3(&otherVertices[otherVertIndex].Position); XMVECTOR otherNormal = XMLoadFloat3(&otherVertices[otherVertIndex].Normal); XMVECTOR difference = XMVectorSubtract(ourVertex, otherVertex); XMFLOAT3 differenceDotValue, normalDotValue; XMVECTOR diffLength = XMVector3Length(difference); XMVECTOR normLength = XMVector3Length(otherNormal); XMVECTOR magnitude = XMVectorMultiply(diffLength, normLength); XMStoreFloat3(&differenceDotValue, XMVectorDivide(XMVector3Dot(difference, otherNormal), magnitude)); // At this point, we should have the cosine of the angle. float angleInRads = acosf(differenceDotValue.x); float angleInDegs = XMConvertToDegrees(angleInRads); XMStoreFloat3(&normalDotValue, XMVector3Dot(ourNormal, otherNormal)); if (angleInDegs < 90.0f) { localCollision = false; } } if (localCollision) { positions.push_back(vertices[vertIndex].Position); } } if (positions.empty()) { // Time to do our second-case checking: is it inside of us? for (int otherVertIndex = 0; otherVertIndex < otherVertices.size(); otherVertIndex++) { bool localCollision = true; XMVECTOR otherVertex = XMLoadFloat3(&otherVertices[otherVertIndex].Position); XMVECTOR otherNormal = XMVector3Normalize(XMLoadFloat3(&otherVertices[otherVertIndex].Normal)); // For each vertex in our mesh, we'll check to see if it resides inside our other mesh. for (int vertIndex = 0; vertIndex < vertices.size(); vertIndex++) { XMVECTOR ourVertex = XMLoadFloat3(&vertices[vertIndex].Position); XMVECTOR ourNormal = XMVector3Normalize(XMLoadFloat3(&vertices[vertIndex].Normal)); XMVECTOR difference = XMVectorSubtract(otherVertex, ourVertex); XMFLOAT3 differenceDotValue, normalDotValue; XMVECTOR diffLength = XMVector3Length(difference); XMVECTOR normLength = XMVector3Length(ourNormal); XMVECTOR magnitude = XMVectorMultiply(diffLength, normLength); XMStoreFloat3(&differenceDotValue, XMVectorDivide(XMVector3Dot(difference, ourNormal), magnitude)); // At this point, we should have the cosine of the angle. float angleInRads = acosf(differenceDotValue.x); float angleInDegs = XMConvertToDegrees(angleInRads); XMStoreFloat3(&normalDotValue, XMVector3Dot(ourNormal, otherNormal)); if (angleInDegs < 90.0f) { localCollision = false; } } if (localCollision) { positions.push_back(otherVertices[otherVertIndex].Position); } } } if(positions.size()) { mDelegate->CollisionOccurred(otherMesh.mDelegate); otherMesh.mDelegate->CollisionOccurred(mDelegate); } return positions.size(); }
bool CollisionMesh::CheckCollisionsGJK1(CollisionMesh& otherMesh) { std::vector<XMFLOAT3> convexHull; bool foundOrigin = false; std::vector<VPCNTDesc> vertices = GetVertices(); std::vector<VPCNTDesc> otherVertices = otherMesh.GetVertices(); XMMATRIX otherWorld = otherMesh.GetWorldTransform(); XMMATRIX world = GetWorldTransform(); // Pre-multiply the model's vertices so as to avoid transforming them during comparison. for (int vertIndex = 0; vertIndex < vertices.size(); vertIndex++) { XMVECTOR vertexTransform = XMLoadFloat3(&vertices[vertIndex].Position); XMStoreFloat3(&vertices[vertIndex].Position, XMVector3Transform(vertexTransform, world)); } for (int otherVertIndex = 0; otherVertIndex < otherVertices.size(); otherVertIndex++) { XMVECTOR vertexTransform = XMLoadFloat3(&otherVertices[otherVertIndex].Position); XMStoreFloat3(&otherVertices[otherVertIndex].Position, XMVector3Transform(vertexTransform, otherWorld)); } // Now we get to the fun part; the subtraction. for (int vertIndex = 0; vertIndex < vertices.size() && !foundOrigin; vertIndex++) { XMFLOAT3 vertexValue = vertices[vertIndex].Position; XMVECTOR vertexTransform = XMLoadFloat3(&vertexValue); for (int otherVertIndex = 0; otherVertIndex < otherVertices.size() && !foundOrigin; otherVertIndex++) { XMVECTOR otherVertexTransform = XMLoadFloat3(&otherVertices[otherVertIndex].Position); XMFLOAT3 convexHullPoint; XMVECTOR difference = XMVectorSubtract(vertexTransform, otherVertexTransform); XMStoreFloat3(&convexHullPoint, difference); convexHull.push_back(convexHullPoint); foundOrigin = XMVector3Equal(difference, XMVectorZero()); } convexHull.push_back(vertexValue); } if (!foundOrigin) { XMFLOAT3 collisionLine = XMFLOAT3(0.0f, 1250.0f, 500.0f); printf("We ain't found shit!"); bool collision = true; int intersections = 0; for (int hullVertexIndex = 0; hullVertexIndex < convexHull.size() && convexHull.size() > 3; hullVertexIndex += 3) { int secondIndex = (hullVertexIndex + 1) % (convexHull.size() - 1); int thirdIndex = (hullVertexIndex + 2) % (convexHull.size() - 1); XMFLOAT3 firstVert = convexHull[hullVertexIndex]; XMFLOAT3 secondVert = convexHull[secondIndex]; XMFLOAT3 thirdVert = convexHull[thirdIndex]; XMFLOAT3 origin = XMFLOAT3(0.0f, 0.0f, 0.0f); // we need to check the normal. Calculate using cross product. XMVECTOR firstVector = XMVectorSet(secondVert.x - firstVert.x, secondVert.y - firstVert.y, secondVert.z - firstVert.z, 0.0f); XMVECTOR secondVector = XMVectorSet(thirdVert.x - secondVert.x, thirdVert.y - secondVert.y, thirdVert.z - secondVert.z, 0.0f); XMFLOAT3 normal; XMStoreFloat3(&normal, XMVector3Normalize(XMVector3Cross(firstVector, secondVector))); // check to ensure no parallels are detected. float firstDot = (normal.x * collisionLine.x) + (normal.y * collisionLine.y) + (normal.z * collisionLine.z); if (firstDot < 0) { float delta = -((normal.x * (origin.x - firstVert.x)) + (normal.y * (origin.y - firstVert.y)) + (normal.z * (origin.z - firstVert.y))) / firstDot; if (delta < 0) { break; } XMFLOAT3 pointToCheck = XMFLOAT3(origin.x - (collisionLine.x * delta), origin.y - (collisionLine.y * delta), origin.z * (collisionLine.z * delta)); bool firstCheck = CheckWinding(firstVert, secondVert, pointToCheck, normal); bool secondCheck = CheckWinding(secondVert, thirdVert, pointToCheck, normal); bool thirdCheck = CheckWinding(thirdVert, firstVert, pointToCheck, normal); if (firstCheck && secondCheck && thirdCheck) { intersections++; } else { collision = false; } } } if ((intersections % 2) == 1) { foundOrigin = true; } } return foundOrigin; }