/*---------------------------------------------------------------------------*/ unsigned int NifCollisionUtility::getGeometryFromPackedNiTriStrips(bhkPackedNiTriStripsShapeRef pShape, vector<hkGeometry>& geometryMap, vector<Matrix44>& transformAry) { hkPackedNiTriStripsDataRef pData (DynamicCast<hkPackedNiTriStripsData>(pShape->GetData())); float factor(0.1f); //@TODO: modify factor depending on _nifVersion if necessary if (pData != NULL) { hkGeometry tmpGeo; hkArray<hkVector4>& vertAry (tmpGeo.m_vertices); hkArray<hkGeometry::Triangle>& triAry (tmpGeo.m_triangles); vector<OblivionSubShape> subShapes(pData->GetSubShapes()); vector<Vector3> vertices (pData->GetVertices()); vector<hkTriangle> triangles(pData->GetHavokTriangles()); hkTriangle& triangle (triangles[0]); Vector3 tVector; unsigned int verOffset(0); unsigned int triIndex (0); unsigned int material (_defaultMaterial); // convert each sub-shape for (auto pIter=subShapes.begin(), pEnd=subShapes.end(); pIter != pEnd; ++pIter) { // reset arrays vertAry.clear(); triAry.clear(); // get vertices for (unsigned int idx(verOffset), idxMax(verOffset+pIter->numVertices); idx < idxMax; ++idx) { tVector = vertices[idx]; // scale final vertex tVector *= factor; // add vertex to tmp. array vertAry.pushBack(hkVector4(tVector.x, tVector.y, tVector.z)); } // for (unsigned int idx(verOffset), idxMax(verOffset+pIter->numVertices); idx < idxMax; ++idx) // get triangles for (; triIndex < triangles.size(); ++triIndex) { // check vertex bounds triangle = triangles[triIndex]; if ((triangle.triangle.v1 >= (pIter->numVertices + verOffset)) || (triangle.triangle.v2 >= (pIter->numVertices + verOffset)) || (triangle.triangle.v3 >= (pIter->numVertices + verOffset)) ) { break; } hkGeometry::Triangle tTri; tTri.set(triangle.triangle.v1-verOffset, triangle.triangle.v2-verOffset, triangle.triangle.v3-verOffset, material); triAry.pushBack(tTri); } // for (; triIndex < triangles.size(); ++triIndex) // re-order triangles points to match same winding if (_reorderTriangles) { reorderTriangles(triAry); } // add geometry to result array geometryMap.push_back(tmpGeo); // increase vertex offset verOffset += pIter->numVertices; } // for (auto pIter=subShapes.begin(), pEnd=subShapes.end(); pIter != pEnd; ++pIter) } // if (pData != NULL) return geometryMap.size(); }
bool CollisionImport::ImportPackedNiTriStripsShape(INode *rbody, bhkRigidBodyRef body, bhkPackedNiTriStripsShapeRef shape, INode *parent, Matrix3& tm) { if (hkPackedNiTriStripsDataRef data = shape->GetData()) { Matrix3 ltm(true); vector<Vector3> verts = data->GetVertices(); vector<Triangle> tris = data->GetTriangles(); vector<Vector3> norms = data->GetNormals(); vector<Niflib::OblivionSubShape> subshapes = (ni.IsFallout3() || ni.IsSkyrim()) ? shape->GetSubShapes() : data->GetSubShapes(); if (subshapes.size() == 0) { // Is this possible? INode *inode = ImportCollisionMesh(verts, tris, norms, tm, parent); CreatebhkCollisionModifier(inode, bv_type_packed, HavokMaterial(NP_DEFAULT_HVK_MATERIAL), OL_UNIDENTIFIED, 0); ImportBase(body, shape, parent, inode, ltm); AddShape(rbody, inode); } else { unsigned int voff = 0; unsigned int toff = 0; INodeTab nodes; for (int i = 0, n = subshapes.size(); i<n; ++i) { Niflib::OblivionSubShape& s = subshapes[i]; vector<Vector3> subverts; vector<Triangle> subtris; vector<Vector3> subnorms; subverts.reserve(s.numVertices); for (unsigned int v=voff; v < (voff + s.numVertices); ++v) { subverts.push_back( verts[v] ); } unsigned int vend = (voff + s.numVertices ); // TODO: Fix algorithm. I do not know how to split the triangles here // Basically, greedily take all triangles until next subshape // This is not correct but seems to work with most meshes tested. subtris.reserve( s.numVertices / 2 ); subnorms.reserve( s.numVertices / 2 ); while ( toff < tris.size() ){ Triangle t = tris[toff]; if ( t.v1 >= vend || t.v2 >= vend || t.v3 >= vend ) break; // remove offset for mesh t.v1 -= voff; t.v2 -= voff; t.v3 -= voff; subtris.push_back( t ); subnorms.push_back( norms[toff] ); ++toff; } voff += s.numVertices; INode *inode = ImportCollisionMesh(subverts, subtris, subnorms, tm, parent); CreatebhkCollisionModifier(inode, bv_type_packed, HavokMaterial(s.material), s.layer, s.colFilter); ImportBase(body, shape, parent, inode, ltm); if (n > 1) inode->SetName( FormatText("%s:%d", "OblivionSubShape", i).data() ); nodes.Append(1, &inode); } // TODO: Group nodes on import if ( nodes.Count() > 1 ) { TSTR shapeName = "bhkPackedNiTriStripsShape"; INode *group = ni.gi->GroupNodes(&nodes, &shapeName, 0); AddShape(rbody, group); } else if ( nodes.Count() == 1 ) { AddShape(rbody, nodes[0]); } } return true; } return false; }