bool StaticModelGroup::DrawOcclusion(OcclusionBuffer* buffer) { // Make sure instance transforms are up-to-date GetWorldBoundingBox(); for (unsigned i = 0; i < numWorldTransforms_; ++i) { for (unsigned j = 0; j < batches_.Size(); ++j) { Geometry* geometry = GetLodGeometry(j, occlusionLodLevel_); if (!geometry) continue; // Check that the material is suitable for occlusion (default material always is) and set culling mode Material* material = batches_[j].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 || !indexData) continue; unsigned indexStart = geometry->GetIndexStart(); unsigned indexCount = geometry->GetIndexCount(); // Draw and check for running out of triangles if (!buffer->Draw(worldTransforms_[i], vertexData, vertexSize, indexData, indexSize, indexStart, indexCount)) return false; } } return true; }
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; const PODVector<VertexElement>* elements; geometry->GetRawData(vertexData, vertexSize, indexData, indexSize, elements); // Check for valid geometry data if (!vertexData || !elements || VertexBuffer::GetElementOffset(*elements, TYPE_VECTOR3, SEM_POSITION) != 0) continue; // Draw and check for running out of triangles success = buffer->AddTriangles(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); }
bool StaticModel::DrawOcclusion(OcclusionBuffer* buffer) { for (unsigned i = 0; i < batches_.size(); ++i) { Geometry* geometry = GetLodGeometry(i, occlusionLodLevel_); 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; const ea::vector<VertexElement>* elements; geometry->GetRawData(vertexData, vertexSize, indexData, indexSize, elements); // Check for valid geometry data if (!vertexData || !indexData || !elements || VertexBuffer::GetElementOffset(*elements, TYPE_VECTOR3, SEM_POSITION) != 0) continue; unsigned indexStart = geometry->GetIndexStart(); unsigned indexCount = geometry->GetIndexCount(); // Draw and check for running out of triangles if (!buffer->AddTriangles(node_->GetWorldTransform(), vertexData, vertexSize, indexData, indexSize, indexStart, indexCount)) return false; } return true; }
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; } } }