TEST(Matrix, Translate) { Matrix4 trans; trans.CreateTranslation(Vector3(5.0f, 10.0f, -4.0f)); Vector3 v(Vector3::Zero); v.Transform(trans); EXPECT_NEAR(5.0f, v.GetX(), 0.01f); EXPECT_NEAR(10.0f, v.GetY(), 0.01f); EXPECT_NEAR(-4.0f, v.GetZ(), 0.01f); }
void SpaceShooter::UpdatePlayerShip() { if ( InputManager::Get().GetKeyState( Key::W ) ) { mPlayerObject->MoveForward(); playerJetParticles->SetEmitterState( true ); } else { mPlayerObject->StopAcceleration(); playerJetParticles->SetEmitterState( false ); } if ( InputManager::Get().GetKeyState( Key::A ) ) { mPlayerObject->RotateLeft(); } if ( InputManager::Get().GetKeyState( Key::D ) ) { mPlayerObject->RotateRight(); } // Update player's particles Matrix4 jetFuelTranspose = Matrix4::Identity; Matrix4 jetFuelOffset; jetFuelOffset.CreateTranslation( Vector3(0.f, 0.f, -5.5f) ); Matrix4 jetFuelRotation; jetFuelRotation.CreateFromQuaternion( mPlayerObject->GetRotation() ); Matrix4 jetFuelTranslation; jetFuelTranslation.CreateTranslation( mPlayerObject->GetTranslation() ); jetFuelTranspose.Multiply( jetFuelTranslation ); jetFuelTranspose.Multiply( jetFuelRotation ); jetFuelTranspose.Multiply( jetFuelOffset ); playerJetParticles->SetTranslationMatrix( jetFuelTranspose ); }
void EditorBodyControl::ApplyTransform(float32 x, float32 y, float32 z) { if (!InModificationMode()) return; Entity *selectedNode = scene->GetProxy(); if(selectedNode) { Matrix4 modification; modification.Identity(); Matrix4 t1, t2; t1.CreateTranslation(-selectedNode->GetWorldTransform().GetTranslationVector()); t2.CreateTranslation(selectedNode->GetWorldTransform().GetTranslationVector()); switch (GetModificationMode()) { case ResourceEditor::MODIFY_MOVE: modification.CreateTranslation(Vector3(x, y, z)); break; case ResourceEditor::MODIFY_ROTATE: modification.CreateRotation(Vector3(1, 0, 0), DegToRad(x)); modification *= Matrix4::MakeRotation(Vector3(0, 1, 0), DegToRad(y)); modification *= Matrix4::MakeRotation(Vector3(0, 0, 1), DegToRad(z)); modification = (t1 * modification) * t2; break; case ResourceEditor::MODIFY_SCALE: modification.CreateScale(Vector3(1, 1, 1) + Vector3(x + y + z, x + y + z, x + y + z) / 100.f); modification = (t1 * modification) * t2; break; default: break; } Matrix4 originalTransform = selectedNode->GetLocalTransform(); modification = originalTransform * modification; if (IsLandscapeRelative()) { modification = modification * GetLandscapeOffset(modification); } CommandsManager::Instance()->ExecuteAndRelease(new CommandTransformObject(selectedNode, originalTransform, modification), scene); } }
void ModificationPopUp::OnFloatPropertyChanged(PropertyList *forList, const String &forKey, float newValue) { if (selection) { Matrix4 modification; modification.Identity(); modification.CreateTranslation(Vector3(forList->GetFloatPropertyValue("x"), forList->GetFloatPropertyValue("y"), forList->GetFloatPropertyValue("z"))); selection->SetLocalTransform(selection->GetLocalTransform() * modification); forList->SetFloatPropertyValue("x", 0.0f); forList->SetFloatPropertyValue("y", 0.0f); forList->SetFloatPropertyValue("z", 0.0f); } }
void EditorBodyControl::UpdateArrowsNode(Entity* node) { ArrowsNode* arrowsNode = GetArrowsNode(false); if (node && arrowsNode) { if (node == arrowsNode) { arrowsNode->SetVisible(false); return; } Matrix4 nodeWT = node->GetWorldTransform(); Matrix4 arrowsNodeTransform; arrowsNodeTransform.CreateTranslation(nodeWT.GetTranslationVector()); arrowsNode->SetLocalTransform(arrowsNodeTransform); arrowsNode->SetVisible(true); arrowsNode->SetActive(InModificationMode()); } }
Matrix4 EditorBodyControl::GetLandscapeOffset(const Matrix4& transform) { Matrix4 resTransform; resTransform.Identity(); Landscape* landscape = FindLandscape(scene); if(!landscape) return resTransform; Vector3 p = Vector3(0, 0, 0) * transform; Vector3 result; bool res = landscape->PlacePoint(p, result); if (res) { Vector3 offset = result - p; resTransform.CreateTranslation(offset); } return resTransform; }
GameObject* Terrain::CreateGameObject(const char* diffuseTxt_filename, const char* normalTxt_filename, const char* heightTxt_filemane) { std::vector<float2> texture_coordinate = calculateTextureCoordiate(); std::vector<float2> boundsY = CalcAllPatchBoundsY(); const int iNumVertices = m_initInfo.HeightmapWidth / 8 * (m_initInfo.HeightmapHeight) / 8 * 4; const int iNumIndices = iNumVertices; VertexTerrain* vertices = new VertexTerrain[iNumVertices]; unsigned int* indices = new unsigned int[iNumIndices]; // Translate the terrain, so that the mid-point of terrain is at (0, 0, 0) Matrix4 translate; translate.CreateTranslation(Vector3(-GetWidth() / 2.0f, 0.0f, -GetDepth() / 2.0f)); // Initialize the index to the vertex buffer. int indexCounter = 0; // Load the vertex and index array with the terrain data. for (int j = 0; j < m_initInfo.HeightmapHeight - 8; j += 8) { for (int i = 0; i < m_initInfo.HeightmapWidth - 8; i += 8) { const int index_bl = m_initInfo.HeightmapWidth * j + i; const int index_br = m_initInfo.HeightmapWidth * j + (i + 8); const int index_ul = m_initInfo.HeightmapWidth * (j + 8) + i; const int index_ur = m_initInfo.HeightmapWidth * (j + 8) + (i + 8); const float2 bl_uv( texture_coordinate[index_bl].x, texture_coordinate[index_bl].y ); const float2 br_uv( (texture_coordinate[index_br].x == 0.0f ? 1.0f : texture_coordinate[index_br].x), texture_coordinate[index_br].y ); const float2 ul_uv( texture_coordinate[index_ul].x, (texture_coordinate[index_ul].y == 1.0f ? 0.0f : texture_coordinate[index_ul].y) ); const float2 ur_uv( (texture_coordinate[index_ur].x == 0.0f ? 1.0f : texture_coordinate[index_ur].x), (texture_coordinate[index_ur].y == 1.0f ? 0.0f : texture_coordinate[index_ur].y) ); Vector3 bl(i * m_initInfo.CellSpacing, m_HeightMap[index_bl] * m_initInfo.CellSpacing, j* m_initInfo.CellSpacing); Vector3 br((i + 8)* m_initInfo.CellSpacing, m_HeightMap[index_br] * m_initInfo.CellSpacing, j* m_initInfo.CellSpacing); Vector3 ul(i* m_initInfo.CellSpacing, m_HeightMap[index_ul] * m_initInfo.CellSpacing, (j + 8)* m_initInfo.CellSpacing); Vector3 ur((i + 8)* m_initInfo.CellSpacing, m_HeightMap[index_ur] * m_initInfo.CellSpacing, (j + 8)* m_initInfo.CellSpacing); const int patch_id = j + (i / m_initInfo.CellsPerPatch); // bottom left { vertices[indexCounter].m_pos = bl; vertices[indexCounter].m_UV[0] = bl_uv.x; vertices[indexCounter].m_UV[1] = bl_uv.y; vertices[indexCounter].m_boundsY[0] = boundsY[patch_id].x; vertices[indexCounter].m_boundsY[1] = boundsY[patch_id].y; indices[indexCounter] = indexCounter; indexCounter++; } // bottom right { vertices[indexCounter].m_pos = br; vertices[indexCounter].m_UV[0] = br_uv.x; vertices[indexCounter].m_UV[1] = br_uv.y; vertices[indexCounter].m_boundsY[0] = boundsY[patch_id].x; vertices[indexCounter].m_boundsY[1] = boundsY[patch_id].y; indices[indexCounter] = indexCounter; indexCounter++; } // upper left { vertices[indexCounter].m_pos = ul; vertices[indexCounter].m_UV[0] = ul_uv.x; vertices[indexCounter].m_UV[1] = ul_uv.y; vertices[indexCounter].m_boundsY[0] = boundsY[patch_id].x; vertices[indexCounter].m_boundsY[1] = boundsY[patch_id].y; indices[indexCounter] = indexCounter; indexCounter++; } // upper right { vertices[indexCounter].m_pos = ur; vertices[indexCounter].m_UV[0] = ur_uv.x; vertices[indexCounter].m_UV[1] = ur_uv.y; vertices[indexCounter].m_boundsY[0] = boundsY[patch_id].x; vertices[indexCounter].m_boundsY[1] = boundsY[patch_id].y; indices[indexCounter] = indexCounter; indexCounter++; } } } std::string diffuseTxt_filepath = std::string("../Assets/") + diffuseTxt_filename; std::string normalTxt_filepath = std::string("../Assets/") + normalTxt_filename; std::string heightTxt_filepath = std::string("../Assets/") + heightTxt_filemane; MeshData* meshData = new MeshData(vertices, iNumVertices, indices, iNumIndices, sizeof(VertexTerrain)); meshData->SetBoundingBox(AABB(Vector3(0, 0, 0), Vector3(m_initInfo.HeightmapHeight, 0, m_initInfo.HeightmapWidth))); Handle hMeshComp(sizeof(MeshComponent)); new (hMeshComp) MeshComponent(meshData); SceneGraph::GetInstance()->AddComponent((MeshComponent*) hMeshComp.Raw()); RenderPass* renderPass = new RenderPass; renderPass->SetVertexShader("../DEngine/Shaders/VS_terrain.hlsl"); renderPass->SetHullShader("../DEngine/Shaders/HS_terrain.hlsl"); renderPass->SetDomainShader("../DEngine/Shaders/DS_terrain.hlsl"); renderPass->SetPixelShader("../DEngine/Shaders/PS_terrain.hlsl"); Handle hTexture1(sizeof(Texture)); new (hTexture1) Texture(Texture::SHADER_RESOURCES, 1, diffuseTxt_filepath.c_str()); Handle hTexture2(sizeof(Texture)); new (hTexture2) Texture(Texture::SHADER_RESOURCES, 1, normalTxt_filepath.c_str()); Handle hTexture3(sizeof(Texture)); new (hTexture3) Texture(Texture::SHADER_RESOURCES, 1, heightTxt_filepath.c_str()); renderPass->AddTexture(hTexture1); renderPass->AddTexture(hTexture2); renderPass->AddTexture(hTexture3); renderPass->SetTopology(D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST); renderPass->SetBlendState(State::NULL_STATE); renderPass->SetRenderTargets(D3D11Renderer::GetInstance()->m_pRTVArray, 2); renderPass->SetDepthStencilView(D3D11Renderer::GetInstance()->m_depth->GetDSV()); renderPass->SetDepthStencilState(State::DEFAULT_DEPTH_STENCIL_DSS); renderPass->SetRasterizerState(State::CULL_BACK_RS); ((MeshComponent*) hMeshComp.Raw())->m_pMeshData->m_Material.AddPassToTechnique(renderPass); GameObject* terrain = new GameObject; terrain->AddComponent((Component*) hMeshComp.Raw()); delete[] vertices; delete[] indices; return terrain; }
void EditorBodyControl::PrepareModMatrix(const Vector2 & point) { float32 winx = point.x - touchStart.x; float32 winy = point.y - touchStart.y; Matrix4 modification; modification.Identity(); ArrowsNode* arrowsNode = GetArrowsNode(false); if (!arrowsNode) return; if (GetModificationMode() == ResourceEditor::MODIFY_MOVE) { Vector3 from, dir; GetCursorVectors(&from, &dir, point); Vector3 currPoint; bool result = GetIntersectionVectorWithPlane(from, dir, planeNormal, rotationCenter, currPoint); if (result) { if (arrowsNode) { switch (arrowsNode->GetModAxis()) { case ArrowsNode::AXIS_X: currPoint.y = startDragPoint.y; currPoint.z = startDragPoint.z; break; case ArrowsNode::AXIS_Y: currPoint.x = startDragPoint.x; currPoint.z = startDragPoint.z; break; case ArrowsNode::AXIS_Z: currPoint.x = startDragPoint.x; currPoint.y = startDragPoint.y; break; default: break; } modification.CreateTranslation(currPoint - startDragPoint); } } } else if (GetModificationMode() == ResourceEditor::MODIFY_ROTATE) { Matrix4 d; switch (arrowsNode->GetModAxis()) { case ArrowsNode::AXIS_X: case ArrowsNode::AXIS_Y: modification.CreateRotation(vect[arrowsNode->GetModAxis()], winy / 100.0f); break; case ArrowsNode::AXIS_Z: modification.CreateRotation(vect[arrowsNode->GetModAxis()], winx / 100.0f); break; case ArrowsNode::AXIS_XY: modification.CreateRotation(vect[ArrowsNode::AXIS_X], winx / 100.0f); d.CreateRotation(vect[ArrowsNode::AXIS_Y], winy / 100.0f); modification *= d; break; case ArrowsNode::AXIS_YZ: modification.CreateRotation(vect[ArrowsNode::AXIS_Y], winx / 100.0f); d.CreateRotation(vect[ArrowsNode::AXIS_Z], winy / 100.0f); modification *= d; break; case ArrowsNode::AXIS_XZ: modification.CreateRotation(vect[ArrowsNode::AXIS_X], winx / 100.0f); d.CreateRotation(vect[ArrowsNode::AXIS_Z], winy / 100.0f); modification *= d; break; default: break; } modification = (translate1 * modification) * translate2; } else if (GetModificationMode() == ResourceEditor::MODIFY_SCALE) { float kf = winx / 100.0f; if (kf < -1.0) kf = - kf - 2.0; modification.CreateScale(Vector3(1,1,1) + Vector3(1,1,1) * kf); modification = (translate1 * modification) * translate2; } currTransform = startTransform * modification; }
void SceneNode::Update(float32 timeElapsed) { inUpdate = true; // TODO - move node update to render because any of objects can change params of other objects if (nodeAnimations.size() != 0) { Quaternion blendedRotation; Vector3 blendedTranslation; float32 accumWeight = 0.0f; std::deque<SceneNodeAnimation*>::const_iterator end = nodeAnimations.end(); for (std::deque<SceneNodeAnimation*>::iterator it = nodeAnimations.begin(); it != end; ++it) { SceneNodeAnimation * animation = *it; SceneNodeAnimationKey & key = animation->Intepolate(animation->GetCurrentTime()); if (accumWeight == 0.0f) { blendedTranslation = key.translation; blendedRotation = key.rotation; accumWeight = animation->weight; }else { float32 factor = animation->weight / (accumWeight + animation->weight); accumWeight += accumWeight; blendedTranslation.Lerp(blendedTranslation, key.translation, factor); blendedRotation.Slerp(blendedRotation, key.rotation, factor); } //key.GetMatrix(localTransform); } Matrix4 localTransformTrans; Matrix4 localTransformRot; Matrix4 localTransformFinal; localTransformTrans.CreateTranslation(blendedTranslation); localTransformRot = blendedRotation.GetMatrix(); localTransform = localTransformRot * localTransformTrans; // if (nodeAnimations.size() != 1) // { // printf("-- blended node: %s\n", name.c_str()); // std::deque<SceneNodeAnimation*>::const_iterator end = nodeAnimations.end(); // for (std::deque<SceneNodeAnimation*>::iterator it = nodeAnimations.begin(); it != end; ++it) // { // SceneNodeAnimation * animation = *it; // printf(">>> blend: %s wei: %f inDelay: %f\n", animation->GetParent()->name.c_str(), animation->weight, animation->delayTime); // } // } } // update world transform only in case if if (!(flags & NODE_WORLD_MATRIX_ACTUAL)) { if (parent) { worldTransform = localTransform * parent->worldTransform; }else { worldTransform = localTransform; } // need propagate changes to child nodes flags |= NODE_WORLD_MATRIX_ACTUAL; uint32 size = (uint32)childs.size(); for (uint32 c = 0; c < size; ++c) { childs[c]->InvalidateLocalTransform(); childs[c]->Update(timeElapsed); } } else { uint32 size = (uint32)childs.size(); for (uint32 c = 0; c < size; ++c) { childs[c]->Update(timeElapsed); } } //printf("- node: %s tr: %f %f %f\n", name.c_str(), localTransform.data[12], localTransform.data[13], localTransform.data[14]); inUpdate = false; if (!removedCache.empty()) { for (std::deque<SceneNode*>::iterator t = removedCache.begin(); t != removedCache.end(); ++t) { RemoveNode(*t); } removedCache.clear(); } }