bool CustomGeometry::DrawOcclusion(OcclusionBuffer* buffer) { bool success = true; for (unsigned i = 0; i < batches_.Size(); ++i) { Geometry* geometry = GetLodGeometry(i, 0); if (!geometry) continue; // Check that the material is suitable for occlusion (default material always is) and set culling mode Material* material = batches_[i].material_; if (material) { if (!material->GetOcclusion()) continue; buffer->SetCullMode(material->GetCullMode()); } else buffer->SetCullMode(CULL_CCW); const unsigned char* vertexData; unsigned vertexSize; const unsigned char* indexData; unsigned indexSize; unsigned elementMask; geometry->GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask); // Check for valid geometry data if (!vertexData) continue; // Draw and check for running out of triangles success = buffer->Draw(node_->GetWorldTransform(), vertexData, vertexSize, geometry->GetVertexStart(), geometry->GetVertexCount()); if (!success) break; } return success; }
ConvexData::ConvexData(CustomGeometry* custom) { PODVector<Vector3> vertices; unsigned numGeometries = custom->GetNumGeometries(); for (unsigned i = 0; i < numGeometries; ++i) { Geometry* geom = custom->GetLodGeometry(i, 0); if (!geom) { LOGWARNING("Skipping null geometry for convex hull collision"); continue; } const unsigned char* vertexData; const unsigned char* indexData; unsigned vertexSize; unsigned indexSize; unsigned elementMask; geom->GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask); if (!vertexData) { LOGWARNING("Skipping geometry with no CPU-side geometry data for convex hull collision - no vertex data"); continue; } unsigned vertexStart = geom->GetVertexStart(); unsigned vertexCount = geom->GetVertexCount(); // Copy vertex data for (unsigned j = 0; j < vertexCount; ++j) { const Vector3& v = *((const Vector3*)(&vertexData[(vertexStart + j) * vertexSize])); vertices.Push(v); } } BuildHull(vertices); }
SharedPtr<Model> Model::Clone(const String& cloneName) const { SharedPtr<Model> ret(new Model(context_)); ret->SetName(cloneName); ret->boundingBox_ = boundingBox_; ret->skeleton_ = skeleton_; ret->geometryBoneMappings_ = geometryBoneMappings_; ret->geometryCenters_ = geometryCenters_; ret->morphs_ = morphs_; ret->morphRangeStarts_ = morphRangeStarts_; ret->morphRangeCounts_ = morphRangeCounts_; // Deep copy vertex/index buffers HashMap<VertexBuffer*, VertexBuffer*> vbMapping; for (Vector<SharedPtr<VertexBuffer> >::ConstIterator i = vertexBuffers_.Begin(); i != vertexBuffers_.End(); ++i) { VertexBuffer* origBuffer = *i; SharedPtr<VertexBuffer> cloneBuffer; if (origBuffer) { cloneBuffer = new VertexBuffer(context_); cloneBuffer->SetSize(origBuffer->GetVertexCount(), origBuffer->GetElementMask(), origBuffer->IsDynamic()); cloneBuffer->SetShadowed(origBuffer->IsShadowed()); if (origBuffer->IsShadowed()) cloneBuffer->SetData(origBuffer->GetShadowData()); else { void* origData = origBuffer->Lock(0, origBuffer->GetVertexCount()); if (origData) cloneBuffer->SetData(origData); else URHO3D_LOGERROR("Failed to lock original vertex buffer for copying"); } vbMapping[origBuffer] = cloneBuffer; } ret->vertexBuffers_.Push(cloneBuffer); } HashMap<IndexBuffer*, IndexBuffer*> ibMapping; for (Vector<SharedPtr<IndexBuffer> >::ConstIterator i = indexBuffers_.Begin(); i != indexBuffers_.End(); ++i) { IndexBuffer* origBuffer = *i; SharedPtr<IndexBuffer> cloneBuffer; if (origBuffer) { cloneBuffer = new IndexBuffer(context_); cloneBuffer->SetSize(origBuffer->GetIndexCount(), origBuffer->GetIndexSize() == sizeof(unsigned), origBuffer->IsDynamic()); cloneBuffer->SetShadowed(origBuffer->IsShadowed()); if (origBuffer->IsShadowed()) cloneBuffer->SetData(origBuffer->GetShadowData()); else { void* origData = origBuffer->Lock(0, origBuffer->GetIndexCount()); if (origData) cloneBuffer->SetData(origData); else URHO3D_LOGERROR("Failed to lock original index buffer for copying"); } ibMapping[origBuffer] = cloneBuffer; } ret->indexBuffers_.Push(cloneBuffer); } // Deep copy all the geometry LOD levels and refer to the copied vertex/index buffers ret->geometries_.Resize(geometries_.Size()); for (unsigned i = 0; i < geometries_.Size(); ++i) { ret->geometries_[i].Resize(geometries_[i].Size()); for (unsigned j = 0; j < geometries_[i].Size(); ++j) { SharedPtr<Geometry> cloneGeometry; Geometry* origGeometry = geometries_[i][j]; if (origGeometry) { cloneGeometry = new Geometry(context_); cloneGeometry->SetIndexBuffer(ibMapping[origGeometry->GetIndexBuffer()]); unsigned numVbs = origGeometry->GetNumVertexBuffers(); for (unsigned k = 0; k < numVbs; ++k) { cloneGeometry->SetVertexBuffer(k, vbMapping[origGeometry->GetVertexBuffer(k)]); } cloneGeometry->SetDrawRange(origGeometry->GetPrimitiveType(), origGeometry->GetIndexStart(), origGeometry->GetIndexCount(), origGeometry->GetVertexStart(), origGeometry->GetVertexCount(), false); cloneGeometry->SetLodDistance(origGeometry->GetLodDistance()); } ret->geometries_[i][j] = cloneGeometry; } } // Deep copy the morph data (if any) to allow modifying it for (Vector<ModelMorph>::Iterator i = ret->morphs_.Begin(); i != ret->morphs_.End(); ++i) { ModelMorph& morph = *i; for (HashMap<unsigned, VertexBufferMorph>::Iterator j = morph.buffers_.Begin(); j != morph.buffers_.End(); ++j) { VertexBufferMorph& vbMorph = j->second_; if (vbMorph.dataSize_) { SharedArrayPtr<unsigned char> cloneData(new unsigned char[vbMorph.dataSize_]); memcpy(cloneData.Get(), vbMorph.morphData_.Get(), vbMorph.dataSize_); vbMorph.morphData_ = cloneData; } } } ret->SetMemoryUse(GetMemoryUse()); return ret; }
void DecalSet::GetFaces(Vector<PODVector<DecalVertex> >& faces, Drawable* target, unsigned batchIndex, const Frustum& frustum, const Vector3& decalNormal, float normalCutoff) { // Try to use the most accurate LOD level if possible Geometry* geometry = target->GetLodGeometry(batchIndex, 0); if (!geometry || geometry->GetPrimitiveType() != TRIANGLE_LIST) return; const unsigned char* positionData = 0; const unsigned char* normalData = 0; const unsigned char* skinningData = 0; const unsigned char* indexData = 0; unsigned positionStride = 0; unsigned normalStride = 0; unsigned skinningStride = 0; unsigned indexStride = 0; IndexBuffer* ib = geometry->GetIndexBuffer(); if (ib) { indexData = ib->GetShadowData(); indexStride = ib->GetIndexSize(); } // For morphed models positions, normals and skinning may be in different buffers for (unsigned i = 0; i < geometry->GetNumVertexBuffers(); ++i) { VertexBuffer* vb = geometry->GetVertexBuffer(i); if (!vb) continue; unsigned elementMask = vb->GetElementMask(); unsigned char* data = vb->GetShadowData(); if (!data) continue; if (elementMask & MASK_POSITION) { positionData = data; positionStride = vb->GetVertexSize(); } if (elementMask & MASK_NORMAL) { normalData = data + vb->GetElementOffset(SEM_NORMAL); normalStride = vb->GetVertexSize(); } if (elementMask & MASK_BLENDWEIGHTS) { skinningData = data + vb->GetElementOffset(SEM_BLENDWEIGHTS); skinningStride = vb->GetVertexSize(); } } // Positions and indices are needed if (!positionData) { // As a fallback, try to get the geometry's raw vertex/index data const PODVector<VertexElement>* elements; geometry->GetRawData(positionData, positionStride, indexData, indexStride, elements); if (!positionData) { URHO3D_LOGWARNING("Can not add decal, target drawable has no CPU-side geometry data"); return; } } if (indexData) { unsigned indexStart = geometry->GetIndexStart(); unsigned indexCount = geometry->GetIndexCount(); // 16-bit indices if (indexStride == sizeof(unsigned short)) { const unsigned short* indices = ((const unsigned short*)indexData) + indexStart; const unsigned short* indicesEnd = indices + indexCount; while (indices < indicesEnd) { GetFace(faces, target, batchIndex, indices[0], indices[1], indices[2], positionData, normalData, skinningData, positionStride, normalStride, skinningStride, frustum, decalNormal, normalCutoff); indices += 3; } } else // 32-bit indices { const unsigned* indices = ((const unsigned*)indexData) + indexStart; const unsigned* indicesEnd = indices + indexCount; while (indices < indicesEnd) { GetFace(faces, target, batchIndex, indices[0], indices[1], indices[2], positionData, normalData, skinningData, positionStride, normalStride, skinningStride, frustum, decalNormal, normalCutoff); indices += 3; } } } else { // Non-indexed geometry unsigned indices = geometry->GetVertexStart(); unsigned indicesEnd = indices + geometry->GetVertexCount(); while (indices + 2 < indicesEnd) { GetFace(faces, target, batchIndex, indices, indices + 1, indices + 2, positionData, normalData, skinningData, positionStride, normalStride, skinningStride, frustum, decalNormal, normalCutoff); indices += 3; } } }