// This code contains NVIDIA Confidential Information and is disclosed to you // under a form of NVIDIA software license agreement provided separately to you. // // Notice // NVIDIA Corporation and its licensors retain all intellectual property and // proprietary rights in and to this software and related documentation and // any modifications thereto. Any use, reproduction, disclosure, or // distribution of this software and related documentation without an express // license agreement from NVIDIA Corporation is strictly prohibited. // // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. // // Information and code furnished is believed to be accurate and reliable. // However, NVIDIA Corporation assumes no responsibility for the consequences of use of such // information or for any infringement of patents or other rights of third parties that may // result from its use. No license is granted by implication or otherwise under any patent // or patent rights of NVIDIA Corporation. Details are subject to change without notice. // This code supersedes and replaces all information previously supplied. // NVIDIA Corporation products are not authorized for use as critical // components in life support devices or systems without express written approval of // NVIDIA Corporation. // // Copyright (c) 2016-2018 NVIDIA Corporation. All rights reserved. #define _CRT_SECURE_NO_WARNINGS #include "NvBlastExtAuthoringMeshImpl.h" #include "NvBlastExtAuthoringTypes.h" #include "NvBlastExtAuthoringPerlinNoise.h" #include #include "PxMath.h" #include #include using physx::PxVec2; using physx::PxVec3; using physx::PxBounds3; #define UV_SCALE 1.f namespace Nv { namespace Blast { MeshImpl::MeshImpl(const PxVec3* position, const PxVec3* normals, const PxVec2* uv, uint32_t verticesCount, const uint32_t* indices, uint32_t indicesCount) { mVertices.resize(verticesCount); for (uint32_t i = 0; i < mVertices.size(); ++i) { mVertices[i].p = position[i]; } if (normals != 0) { for (uint32_t i = 0; i < mVertices.size(); ++i) { mVertices[i].n = normals[i]; } } else { for (uint32_t i = 0; i < mVertices.size(); ++i) { mVertices[i].n = PxVec3(0, 0, 0); } } if (uv != 0) { for (uint32_t i = 0; i < mVertices.size(); ++i) { mVertices[i].uv[0] = uv[i]; } } else { for (uint32_t i = 0; i < mVertices.size(); ++i) { mVertices[i].uv[0] = PxVec2(0, 0); } } mEdges.resize(indicesCount); mFacets.resize(indicesCount / 3); mBounds.setEmpty(); for (uint32_t i = 0; i < verticesCount; ++i) { mBounds.include(mVertices[i].p); } int32_t facetId = 0; for (uint32_t i = 0; i < indicesCount; i += 3) { mEdges[i].s = indices[i]; mEdges[i].e = indices[i + 1]; mEdges[i + 1].s = indices[i + 1]; mEdges[i + 1].e = indices[i + 2]; mEdges[i + 2].s = indices[i + 2]; mEdges[i + 2].e = indices[i]; mFacets[facetId].firstEdgeNumber = i; mFacets[facetId].edgesCount = 3; mFacets[facetId].materialId = 0; //Unassigned for now mFacets[facetId].smoothingGroup = -1; facetId++; } } MeshImpl::MeshImpl(const Vertex* vertices, const Edge* edges, const Facet* facets, uint32_t posCount, uint32_t edgesCount, uint32_t facetsCount) { mVertices.resize(posCount); mEdges.resize(edgesCount); mFacets.resize(facetsCount); memcpy(mVertices.data(), vertices, sizeof(Vertex) * posCount); memcpy(mEdges.data(), edges, sizeof(Edge) * edgesCount); memcpy(mFacets.data(), facets, sizeof(Facet) * facetsCount); mBounds.setEmpty(); for (uint32_t i = 0; i < posCount; ++i) { mBounds.include(mVertices[i].p); } } float MeshImpl::getMeshVolume() { /** Check if mesh boundary consist only of triangles */ for (uint32_t i = 0; i < mFacets.size(); ++i) { if (mFacets[i].edgesCount != 3) { return 0.0f; } } float volume = 0; for (uint32_t i = 0; i < mFacets.size(); ++i) { int32_t offset = mFacets[i].firstEdgeNumber; PxVec3& a = mVertices[mEdges[offset].s].p; PxVec3& b = mVertices[mEdges[offset + 1].s].p; PxVec3& c = mVertices[mEdges[offset + 2].s].p; volume += (a.x * b.y * c.z - a.x * b.z * c.y - a.y * b.x * c.z + a.y * b.z * c.x + a.z * b.x * c.y - a.z * b.y * c.x); } return (1.0f / 6.0f) * std::abs(volume); } uint32_t MeshImpl::getFacetCount() const { return static_cast(mFacets.size()); } Vertex* MeshImpl::getVerticesWritable() { return mVertices.data(); } Edge* MeshImpl::getEdgesWritable() { return mEdges.data(); } const Vertex* MeshImpl::getVertices() const { return mVertices.data(); } const Edge* MeshImpl::getEdges() const { return mEdges.data(); } uint32_t MeshImpl::getEdgesCount() const { return static_cast(mEdges.size()); } uint32_t MeshImpl::getVerticesCount() const { return static_cast(mVertices.size()); } Facet* MeshImpl::getFacetsBufferWritable() { return mFacets.data(); } const Facet* MeshImpl::getFacetsBuffer() const { return mFacets.data(); } Facet* MeshImpl::getFacetWritable(int32_t facet) { return &mFacets[facet]; } const Facet* MeshImpl::getFacet(int32_t facet) const { return &mFacets[facet]; } MeshImpl::~MeshImpl() { } void MeshImpl::release() { delete this; } const PxBounds3& MeshImpl::getBoundingBox() const { return mBounds; } PxBounds3& MeshImpl::getBoundingBoxWritable() { return mBounds; } void MeshImpl::recalculateBoundingBox() { mBounds.setEmpty(); for (uint32_t i = 0; i < mVertices.size(); ++i) { mBounds.include(mVertices[i].p); } } void getTangents(const PxVec3& normal, PxVec3& t1, PxVec3& t2) { if (std::abs(normal.z) < 0.9) { t1 = normal.cross(PxVec3(0, 0, 1)); } else { t1 = normal.cross(PxVec3(1, 0, 0)); } t2 = t1.cross(normal); } Mesh* getCuttingBox(const PxVec3& point, const PxVec3& normal, float size, int64_t id, int32_t interiorMaterialId) { PxVec3 lNormal = normal.getNormalized(); PxVec3 t1, t2; getTangents(lNormal, t1, t2); std::vector positions(8); positions[0].p = point + (t1 + t2) * size; positions[1].p = point + (t2 - t1) * size; positions[2].p = point + (-t1 - t2) * size; positions[3].p = point + (t1 - t2) * size; positions[4].p = point + (t1 + t2 + lNormal) * size; positions[5].p = point + (t2 - t1 + lNormal) * size; positions[6].p = point + (-t1 - t2 + lNormal) * size; positions[7].p = point + (t1 - t2 + lNormal) * size; positions[0].n = -lNormal; positions[1].n = -lNormal; positions[2].n = -lNormal; positions[3].n = -lNormal; positions[4].n = -lNormal; positions[5].n = -lNormal; positions[6].n = -lNormal; positions[7].n = -lNormal; positions[0].uv[0] = PxVec2(0, 0); positions[1].uv[0] = PxVec2(UV_SCALE, 0); positions[2].uv[0] = PxVec2(UV_SCALE, UV_SCALE); positions[3].uv[0] = PxVec2(0, UV_SCALE); positions[4].uv[0] = PxVec2(0, 0); positions[5].uv[0] = PxVec2(UV_SCALE, 0); positions[6].uv[0] = PxVec2(UV_SCALE, UV_SCALE); positions[7].uv[0] = PxVec2(0, UV_SCALE); std::vector edges; std::vector facets; edges.push_back(Edge(0, 1)); edges.push_back(Edge(1, 2)); edges.push_back(Edge(2, 3)); edges.push_back(Edge(3, 0)); facets.push_back(Facet(0, 4, interiorMaterialId, id, -1)); edges.push_back(Edge(0, 3)); edges.push_back(Edge(3, 7)); edges.push_back(Edge(7, 4)); edges.push_back(Edge(4, 0)); facets.push_back(Facet(4, 4, interiorMaterialId, id, -1)); edges.push_back(Edge(3, 2)); edges.push_back(Edge(2, 6)); edges.push_back(Edge(6, 7)); edges.push_back(Edge(7, 3)); facets.push_back(Facet(8, 4, interiorMaterialId, id, -1)); edges.push_back(Edge(5, 6)); edges.push_back(Edge(6, 2)); edges.push_back(Edge(2, 1)); edges.push_back(Edge(1, 5)); facets.push_back(Facet(12, 4, interiorMaterialId, id, -1)); edges.push_back(Edge(4, 5)); edges.push_back(Edge(5, 1)); edges.push_back(Edge(1, 0)); edges.push_back(Edge(0, 4)); facets.push_back(Facet(16, 4, interiorMaterialId, id, -1)); edges.push_back(Edge(4, 7)); edges.push_back(Edge(7, 6)); edges.push_back(Edge(6, 5)); edges.push_back(Edge(5, 4)); facets.push_back(Facet(20, 4, interiorMaterialId, id, -1)); return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast(positions.size()), static_cast(edges.size()), static_cast(facets.size())); } void inverseNormalAndSetIndices(Mesh* mesh, int64_t id) { for (uint32_t i = 0; i < mesh->getVerticesCount(); ++i) { mesh->getVerticesWritable()[i].n *= -1.0f; } for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) { mesh->getFacetWritable(i)->userData = id; } } void MeshImpl::setMaterialId(const int32_t* materialId) { if (materialId != nullptr) { for (uint32_t i = 0; i < mFacets.size(); ++i) { mFacets[i].materialId = *materialId; ++materialId; } } } void MeshImpl::replaceMaterialId(int32_t oldMaterialId, int32_t newMaterialId) { for (uint32_t i = 0; i < mFacets.size(); ++i) { if (mFacets[i].materialId == oldMaterialId) { mFacets[i].materialId = newMaterialId; } } } void MeshImpl::setSmoothingGroup(const int32_t* smoothingGroups) { if (smoothingGroups != nullptr) { for (uint32_t i = 0; i < mFacets.size(); ++i) { mFacets[i].smoothingGroup = *smoothingGroups; ++smoothingGroups; } } } void setCuttingBox(const PxVec3& point, const PxVec3& normal, Mesh* mesh, float size, int64_t id) { PxVec3 t1, t2; PxVec3 lNormal = normal.getNormalized(); getTangents(lNormal, t1, t2); Vertex* positions = mesh->getVerticesWritable(); positions[0].p = point + (t1 + t2) * size; positions[1].p = point + (t2 - t1) * size; positions[2].p = point + (-t1 - t2) * size; positions[3].p = point + (t1 - t2) * size; positions[4].p = point + (t1 + t2 + lNormal) * size; positions[5].p = point + (t2 - t1 + lNormal) * size; positions[6].p = point + (-t1 - t2 + lNormal) * size; positions[7].p = point + (t1 - t2 + lNormal) * size; positions[0].n = -lNormal; positions[1].n = -lNormal; positions[2].n = -lNormal; positions[3].n = -lNormal; positions[4].n = -lNormal; positions[5].n = -lNormal; positions[6].n = -lNormal; positions[7].n = -lNormal; for (uint32_t i = 0; i < mesh->getFacetCount(); ++i) { mesh->getFacetWritable(i)->userData = id; } mesh->recalculateBoundingBox(); } bool MeshImpl::isValid() const { return mVertices.size() > 0 && mEdges.size() > 0 && mFacets.size() > 0; } Mesh* getNoisyCuttingBoxPair(const physx::PxVec3& point, const physx::PxVec3& normal, float size, float jaggedPlaneSize, uint32_t resolution, int32_t id, float amplitude, float frequency, int32_t octaves, int32_t seed, int32_t interiorMaterialId) { SimplexNoise nEval(amplitude, frequency, octaves, seed); PxVec3 t1, t2; PxVec3 lNormal = normal.getNormalized(); getTangents(lNormal, t1, t2); std::vector vertices ((resolution + 1) * (resolution + 1) + 12); PxVec3 cPosit = point + (t1 + t2) * jaggedPlaneSize; PxVec3 t1d = -t1 * 2.0f * jaggedPlaneSize / resolution; PxVec3 t2d = -t2 * 2.0f * jaggedPlaneSize / resolution; int32_t vrtId = 0; float invRes = 1.f / resolution; for (uint32_t i = 0; i < resolution + 1; ++i) { PxVec3 lcPosit = cPosit; for (uint32_t j = 0; j < resolution + 1; ++j) { vertices[vrtId].p = lcPosit; vertices[vrtId].uv[0].x = invRes * i * UV_SCALE; vertices[vrtId].uv[0].y = invRes * j * UV_SCALE; lcPosit += t1d; vrtId++; } cPosit += t2d; } for (uint32_t i = 1; i < resolution; ++i) { for (uint32_t j = 1; j < resolution; ++j) { PxVec3& pnt = vertices[i * (resolution + 1) + j].p; pnt += lNormal * nEval.sample(pnt); } } std::vector edges; std::vector facets; for (uint32_t i = 0; i < resolution; ++i) { for (uint32_t j = 0; j < resolution; ++j) { uint32_t start = edges.size(); edges.push_back(Edge(i * (resolution + 1) + j, i * (resolution + 1) + j + 1)); edges.push_back(Edge(i * (resolution + 1) + j + 1, (i + 1) * (resolution + 1) + j + 1)); edges.push_back(Edge((i + 1) * (resolution + 1) + j + 1, i * (resolution + 1) + j)); facets.push_back(Facet(start, 3, interiorMaterialId, id, -1)); start = edges.size(); edges.push_back(Edge(i * (resolution + 1) + j, (i + 1) * (resolution + 1) + j + 1)); edges.push_back(Edge((i + 1) * (resolution + 1) + j + 1, (i + 1) * (resolution + 1) + j)); edges.push_back(Edge((i + 1) * (resolution + 1) + j, (i) * (resolution + 1) + j)); facets.push_back(Facet(start, 3, interiorMaterialId, id, -1)); } } uint32_t offset = (resolution + 1) * (resolution + 1); vertices[0 + offset].p = point + (t1 + t2) * size; vertices[1 + offset].p = point + (t2 - t1) * size; vertices[2 + offset].p = point + (-t1 - t2) * size; vertices[3 + offset].p = point + (t1 - t2) * size; vertices[8 + offset].p = point + (t1 + t2) * jaggedPlaneSize; vertices[9 + offset].p = point + (t2 - t1) * jaggedPlaneSize; vertices[10 + offset].p = point + (-t1 - t2) * jaggedPlaneSize; vertices[11 + offset].p = point + (t1 - t2) * jaggedPlaneSize; vertices[4 + offset].p = point + (t1 + t2 + lNormal) * size; vertices[5 + offset].p = point + (t2 - t1 + lNormal) * size; vertices[6 + offset].p = point + (-t1 - t2 + lNormal) * size; vertices[7 + offset].p = point + (t1 - t2 + lNormal) * size; for (uint32_t i = 1; i < resolution; ++i) { for (uint32_t j = 1; j < resolution; ++j) { PxVec3 v1 = vertices[(resolution + 1) * (i + 1) + j].p - vertices[(resolution + 1) * i + j].p; PxVec3 v2 = vertices[(resolution + 1) * (i) + j + 1].p - vertices[(resolution + 1) * i + j].p; PxVec3 v3 = vertices[(resolution + 1) * (i - 1) + j].p - vertices[(resolution + 1) * i + j].p; PxVec3 v4 = vertices[(resolution + 1) * (i) + j - 1].p - vertices[(resolution + 1) * i + j].p; vertices[(resolution + 1) * i + j].n = v1.cross(v2) + v2.cross(v3) + v3.cross(v4) + v4.cross(v1); vertices[(resolution + 1) * i + j].n.normalize(); } } int32_t edgeOffset = edges.size(); edges.push_back(Edge(0 + offset, 1 + offset)); edges.push_back(Edge(1 + offset, 2 + offset)); edges.push_back(Edge(2 + offset, 3 + offset)); edges.push_back(Edge(3 + offset, 0 + offset)); edges.push_back(Edge(11 + offset, 10 + offset)); edges.push_back(Edge(10 + offset, 9 + offset)); edges.push_back(Edge(9 + offset, 8 + offset)); edges.push_back(Edge(8 + offset, 11 + offset)); facets.push_back(Facet(edgeOffset, 8, interiorMaterialId, id, -1)); edges.push_back(Edge(0 + offset, 3 + offset)); edges.push_back(Edge(3 + offset, 7 + offset)); edges.push_back(Edge(7 + offset, 4 + offset)); edges.push_back(Edge(4 + offset, 0 + offset)); facets.push_back(Facet(8 + edgeOffset, 4, interiorMaterialId, id, -1)); edges.push_back(Edge(3 + offset, 2 + offset)); edges.push_back(Edge(2 + offset, 6 + offset)); edges.push_back(Edge(6 + offset, 7 + offset)); edges.push_back(Edge(7 + offset, 3 + offset)); facets.push_back(Facet(12 + edgeOffset, 4, interiorMaterialId, id, -1)); edges.push_back(Edge(5 + offset, 6 + offset)); edges.push_back(Edge(6 + offset, 2 + offset)); edges.push_back(Edge(2 + offset, 1 + offset)); edges.push_back(Edge(1 + offset, 5 + offset)); facets.push_back(Facet(16 + edgeOffset, 4, interiorMaterialId, id, -1)); edges.push_back(Edge(4 + offset, 5 + offset)); edges.push_back(Edge(5 + offset, 1 + offset)); edges.push_back(Edge(1 + offset, 0 + offset)); edges.push_back(Edge(0 + offset, 4 + offset)); facets.push_back(Facet(20 + edgeOffset, 4, interiorMaterialId, id, -1)); edges.push_back(Edge(4 + offset, 7 + offset)); edges.push_back(Edge(7 + offset, 6 + offset)); edges.push_back(Edge(6 + offset, 5 + offset)); edges.push_back(Edge(5 + offset, 4 + offset)); facets.push_back(Facet(24 + edgeOffset, 4, interiorMaterialId, id, -1)); // return new MeshImpl(vertices.data(), edges.data(), facets.data(), vertices.size(), edges.size(), facets.size()); } Mesh* getBigBox(const PxVec3& point, float size, int32_t interiorMaterialId) { PxVec3 normal(0, 0, 1); normal.normalize(); PxVec3 t1, t2; getTangents(normal, t1, t2); std::vector positions(8); positions[0].p = point + (t1 + t2 - normal) * size; positions[1].p = point + (t2 - t1 - normal) * size; positions[2].p = point + (-t1 - t2 - normal) * size; positions[3].p = point + (t1 - t2 - normal) * size; positions[4].p = point + (t1 + t2 + normal) * size; positions[5].p = point + (t2 - t1 + normal) * size; positions[6].p = point + (-t1 - t2 + normal) * size; positions[7].p = point + (t1 - t2 + normal) * size; positions[0].uv[0] = PxVec2(0, 0); positions[1].uv[0] = PxVec2(UV_SCALE, 0); positions[2].uv[0] = PxVec2(UV_SCALE, UV_SCALE); positions[3].uv[0] = PxVec2(0, UV_SCALE); positions[4].uv[0] = PxVec2(0, 0); positions[5].uv[0] = PxVec2(UV_SCALE, 0); positions[6].uv[0] = PxVec2(UV_SCALE, UV_SCALE); positions[7].uv[0] = PxVec2(0, UV_SCALE); std::vector edges; std::vector facets; edges.push_back(Edge(0, 1)); edges.push_back(Edge(1, 2)); edges.push_back(Edge(2, 3)); edges.push_back(Edge(3, 0)); facets.push_back(Facet(0, 4, interiorMaterialId, 0, -1)); edges.push_back(Edge(0, 3)); edges.push_back(Edge(3, 7)); edges.push_back(Edge(7, 4)); edges.push_back(Edge(4, 0)); facets.push_back(Facet(4, 4, interiorMaterialId, 0, -1)); edges.push_back(Edge(3, 2)); edges.push_back(Edge(2, 6)); edges.push_back(Edge(6, 7)); edges.push_back(Edge(7, 3)); facets.push_back(Facet(8, 4, interiorMaterialId, 0, -1)); edges.push_back(Edge(5, 6)); edges.push_back(Edge(6, 2)); edges.push_back(Edge(2, 1)); edges.push_back(Edge(1, 5)); facets.push_back(Facet(12, 4, interiorMaterialId, 0, -1)); edges.push_back(Edge(4, 5)); edges.push_back(Edge(5, 1)); edges.push_back(Edge(1, 0)); edges.push_back(Edge(0, 4)); facets.push_back(Facet(16, 4, interiorMaterialId, 0, -1)); edges.push_back(Edge(4, 7)); edges.push_back(Edge(7, 6)); edges.push_back(Edge(6, 5)); edges.push_back(Edge(5, 4)); facets.push_back(Facet(20, 4, interiorMaterialId, 0, -1)); for (int i = 0; i < 8; ++i) positions[i].n = PxVec3(0, 0, 0); return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast(positions.size()), static_cast(edges.size()), static_cast(facets.size())); } Mesh* getCuttingCylinder(uint32_t pointCount, const physx::PxVec3* points, const physx::PxTransform& transform, float height, int64_t id, int32_t interiorMaterialId) { std::vector positions(pointCount * 2); std::vector edges(pointCount * 6); std::vector facets(pointCount + 2); for (uint32_t i = 0; i < pointCount; i++) { uint32_t i1 = i + pointCount; uint32_t i2 = i1 + 1; uint32_t i3 = i + 1; auto& p0 = positions[i]; auto& p1 = positions[i1]; p0.n = p1.n = PxVec3(0, 0, 0); p0.p = p1.p = points[i]; p0.p.z = -height; p1.p.z = height; p0.p = transform.transform(p0.p); p1.p = transform.transform(p1.p); p0.uv[0] = PxVec2(0.f, UV_SCALE * i / pointCount); p1.uv[0] = PxVec2(UV_SCALE, UV_SCALE * i / pointCount); int32_t edgeIdx = 4 * i; edges[edgeIdx + 0] = Edge(i, i3); edges[edgeIdx + 1] = Edge(i3, i2); edges[edgeIdx + 2] = Edge(i2, i1); edges[edgeIdx + 3] = Edge(i1, i); facets[i] = Facet(edgeIdx, 4, interiorMaterialId, id, -1); edges[5 * pointCount + i ] = Edge(i1, i2); edges[5 * pointCount - i - 1] = Edge(i3, i); } int32_t edgeIdx = 4 * (pointCount - 1); edges[edgeIdx + 0].e = 0; edges[edgeIdx + 1].s = 0; edges[edgeIdx + 1].e = pointCount; edges[edgeIdx + 2].s = pointCount; //top and bottom faces edges[4 * pointCount].s = 0; edges[6 * pointCount - 1].e = pointCount; facets[pointCount + 0] = Facet(4 * pointCount, pointCount, interiorMaterialId, 0, -1); facets[pointCount + 1] = Facet(5 * pointCount, pointCount, interiorMaterialId, 0, -1); return new MeshImpl(positions.data(), edges.data(), facets.data(), static_cast(positions.size()), static_cast(edges.size()), static_cast(facets.size())); } } // namespace Blast } // namespace Nv