//---------------------------------------------------------------------------- void Node::MergeMeshes(MergeArray* pMergeArray) { WIRE_ASSERT(pMergeArray->GetQuantity() > 0); if (pMergeArray->GetQuantity() == 1) { return; } TPODArray<Transformation*> transformations(pMergeArray->GetQuantity()); TPODArray<UInt64> keys(pMergeArray->GetQuantity()); for (UInt i = 0; i < pMergeArray->GetQuantity(); i++) { UInt64 key = 0; enum { STATESET = 32, MATERIAL = 32, }; WIRE_ASSERT((STATESET + MATERIAL) <= sizeof(key) * 8); RenderObject* pRenderObject = (*pMergeArray)[i]; Material* pMaterial = pRenderObject->GetMaterial(); if (pMaterial) { key |= pMaterial->ID; } // If StateSetID is MAX_UINT, it wasn't initialized (call UpdateRS() // once or initialize manually) key |= static_cast<UInt64>(pRenderObject->GetStateSetID()) << (MATERIAL); keys.Append(key); } Object** pObjects = reinterpret_cast<Object**>(pMergeArray->GetArray()); VisibleSet::QuickSort(keys, pObjects, transformations.GetArray(), 0, pMergeArray->GetQuantity()-1); UInt vtxCount = 0; UInt idxCount = 0; Mesh* pMesh = NULL; for (UInt i = 0; i < pMergeArray->GetQuantity(); i++) { pMesh = (*pMergeArray)[i]->GetMesh(); vtxCount += pMesh->GetVertexCount(); idxCount += pMesh->GetIndexCount(); } const UInt vbCount = pMesh->GetVertexBuffers().GetQuantity(); Mesh::VertexBuffers vbs(vbCount); TArray<Float*> rawDst(vbCount); for (UInt j = 0; j < vbCount; j++) { VertexBuffer* pVB = WIRE_NEW VertexBuffer(pMesh-> GetVertexBuffer(j)->GetAttributes(), vtxCount); vbs.Append(pVB); rawDst.Append(pVB->GetData()); } IndexBuffer* pIB = WIRE_NEW IndexBuffer(idxCount); UShort* pRawIB = pIB->GetData(); Int offset = 0; for (UInt i = 0; i < pMergeArray->GetQuantity(); i++) { pMesh = (*pMergeArray)[i]->GetMesh(); for (UInt j = 0; j < vbCount; j++) { VertexBuffer* pMVB = pMesh->GetVertexBuffer(j); const UInt vtxCount = pMesh->GetVertexCount(); pMVB->ApplyForward(Transformation::IDENTITY, rawDst[j], vtxCount, pMesh->GetStartVertex()); const UInt vtxSize = pMVB->GetAttributes().GetVertexSize(); rawDst[j] += (vtxSize / sizeof(Float)) * vtxCount; } IndexBuffer* pMIB = pMesh->GetIndexBuffer(); offset -= pMesh->GetStartVertex(); const UInt startIdx = pMesh->GetStartIndex(); for (UInt j = startIdx; j < (startIdx + pMesh->GetIndexCount()); j++) { WIRE_ASSERT((((*pMIB)[j])+offset) < 0x10000); *pRawIB++ = static_cast<UShort>((((*pMIB)[j])+offset)); } offset += pMesh->GetVertexCount(); } UInt startIndex = 0; for (UInt i = 0; i < pMergeArray->GetQuantity(); i++) { pMesh = (*pMergeArray)[i]->GetMesh(); const UInt indexCount = pMesh->GetIndexCount(); Mesh* pMergedMesh = WIRE_NEW Mesh(vbs, pIB, startIndex, indexCount); startIndex += indexCount; (*pMergeArray)[i]->SetMesh(pMergedMesh); } }
//---------------------------------------------------------------------------- void Node::WarmUpRendering(Renderer* pRenderer) { #ifndef WIRE_WII // Wii does not need to warm up by submitting draw calls WIRE_ASSERT(pRenderer); UpdateGS(0, true, false); Vector3F cameraLocation = WorldBound->GetCenter(); cameraLocation.Z() += WorldBound->GetRadius(); Vector3F viewDirection = -Vector3F::UNIT_Z; Vector3F up = Vector3F::UNIT_Y; Vector3F right = viewDirection.Cross(up); CameraPtr spCamera = WIRE_NEW Camera; spCamera->SetFrame(cameraLocation, viewDirection, up, right); Float fieldOfView = 60.0F; Float aspectRatio = 2; Float nearPlane = 0.1F; Float farPlane = WorldBound->GetRadius() * 2.0F; spCamera->SetFrustum(fieldOfView, aspectRatio, nearPlane, farPlane); CullerSorting culler; culler.SetCamera(spCamera); culler.ComputeVisibleSet(this); pRenderer->PreDraw(spCamera); // draw scene to warm up batching buffers pRenderer->Draw(culler.GetVisibleSets()); // collect and draw all materials separately so none will be missed // by CULL_ALWAYS or Switch/LOD nodes. THashSet<Material*> materials; TStack<Node*> scene(1000); scene.Push(this); while (!scene.IsEmpty()) { Node* pNode = NULL; scene.Pop(pNode); RenderObject* pRenderObject = pNode->GetRenderObject(); if (pRenderObject && pRenderObject->GetMaterial()) { materials.Insert(pRenderObject->GetMaterial()); } for (UInt i = 0; i < pNode->GetQuantity(); i++) { Node* pChild = DynamicCast<Node>(pNode->GetChild(i)); if (pChild) { scene.Push(pChild); } } } RenderObjectPtr spCube = StandardMesh::CreateCube24(4, pRenderer-> GetMaxTextureStages(), true); THashSet<Material*>::Iterator it(&materials); Transformation transformation; transformation.SetTranslate(cameraLocation - Vector3F(0, 0, 3)); for (Material** pMaterial = it.GetFirst(); pMaterial; pMaterial = it.GetNext()) { spCube->SetMaterial(*pMaterial); pRenderer->Draw(spCube, transformation); } pRenderer->PostDraw(); #endif }