diff options
| author | Marijn Tamis <[email protected]> | 2017-04-28 14:19:07 +0200 |
|---|---|---|
| committer | Marijn Tamis <[email protected]> | 2017-04-28 14:19:07 +0200 |
| commit | b350eb5f4d44e8448115796144375d79438d74ae (patch) | |
| tree | 8e102e8c28f45a1b87bd335ceee4f33c3d4ee7c2 /NvCloth/samples/SampleBase/utils | |
| parent | Add visual samples. (diff) | |
| download | nvcloth-b350eb5f4d44e8448115796144375d79438d74ae.tar.xz nvcloth-b350eb5f4d44e8448115796144375d79438d74ae.zip | |
NvCloth 1.1.0 Release. (22041545)
Diffstat (limited to 'NvCloth/samples/SampleBase/utils')
| -rw-r--r-- | NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp | 56 | ||||
| -rw-r--r-- | NvCloth/samples/SampleBase/utils/ClothMeshGenerator.h | 8 | ||||
| -rw-r--r-- | NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.cpp | 21 | ||||
| -rw-r--r-- | NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.h | 25 | ||||
| -rw-r--r-- | NvCloth/samples/SampleBase/utils/MeshGenerator.cpp | 545 | ||||
| -rw-r--r-- | NvCloth/samples/SampleBase/utils/MeshGenerator.h | 114 | ||||
| -rw-r--r-- | NvCloth/samples/SampleBase/utils/Utils.h | 26 |
7 files changed, 786 insertions, 9 deletions
diff --git a/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp b/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp index d75bb25..49f9ada 100644 --- a/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp +++ b/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp @@ -17,9 +17,8 @@ void ClothMeshData::Clear() mQuads.clear(); } -void ClothMeshData::GeneratePlaneCloth(float width, float height, int segmentsX, int segmentsY, bool createQuads, physx::PxMat44 transform, bool alternatingDiagonals) +void ClothMeshData::GeneratePlaneCloth(float width, float height, int segmentsX, int segmentsY, bool createQuads, physx::PxMat44 transform, bool alternatingDiagonals, int zigzag) { - /* GeneratePlaneCloth(x,y,2,2) generates: @@ -61,14 +60,30 @@ GeneratePlaneCloth(x,y,2,2) generates: { for(int x = 0; x < segmentsX + 1; x++) { - mVertices[x + y * (segmentsX + 1)] = transform.transform(topLeft + physx::PxVec3( ((float)x / (float)segmentsX) * width, - 0.f, - ((float)y / (float)segmentsY) * height)); + physx::PxVec3 pos; + switch(zigzag) + { + case 1: + pos = physx::PxVec3(((float)x / (float)segmentsX) * width, + sinf(y*0.5)/(float)segmentsY * height, + ((float)y / (float)segmentsY) * height); + break; + case 2: + pos = physx::PxVec3(((float)x / (float)segmentsX) * width, + ((float)(y&2) / (float)segmentsY) * height, + ((float)((y+1)&~1) / (float)segmentsY) * height); + default: + pos = physx::PxVec3(((float)x / (float)segmentsX) * width, + 0.f, + ((float)y / (float)segmentsY) * height); + } + + mVertices[x + y * (segmentsX + 1)] = transform.transform(topLeft + pos); + mInvMasses[x + y * (segmentsX + 1)] = 1.0f; - mMesh.vertices[x + y * (segmentsX + 1)].position = transform.transform(topLeft + physx::PxVec3(((float)x / (float)segmentsX) * width, - 0.f, - ((float)y / (float)segmentsY) * height)); + mMesh.vertices[x + y * (segmentsX + 1)].position = transform.transform(topLeft + pos); + mMesh.vertices[x + y * (segmentsX + 1)].normal = transform.transform(physx::PxVec3(0.f, 1.f, 0.f)); mMesh.vertices[x + y * (segmentsX + 1)].uv = physx::PxVec2(uvOx + uvSx*(float)x / (float)segmentsX, uvOy + uvSy*(1.0f - (float)y / (float)segmentsY)); @@ -190,4 +205,29 @@ nv::cloth::ClothMeshDesc ClothMeshData::GetClothMeshDesc() SimpleMesh ClothMeshData::GetRenderMesh() { return mMesh; +} + +void ClothMeshData::Merge(const ClothMeshData& other) +{ + uint32_t firstVertex = (uint32_t)mVertices.size(); + uint32_t firstTriangle = (uint32_t)mTriangles.size(); + uint32_t firstQuad = (uint32_t)mQuads.size(); + + mVertices.insert(mVertices.end(), other.mVertices.begin(), other.mVertices.end()); + mUvs.insert(mUvs.end(), other.mUvs.begin(), other.mUvs.end()); + mInvMasses.insert(mInvMasses.end(), other.mInvMasses.begin(), other.mInvMasses.end()); + + mMesh.vertices.insert(mMesh.vertices.end(), mMesh.vertices.begin(), mMesh.vertices.end()); + + for(const auto& t : other.mTriangles) + { + mTriangles.push_back(t + firstVertex); + } + for(const auto& q : other.mQuads) + { + mQuads.push_back(q + firstVertex); + mMesh.indices.push_back(mQuads.back().a); + mMesh.indices.push_back(mQuads.back().b); + mMesh.indices.push_back(mQuads.back().c); + } }
\ No newline at end of file diff --git a/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.h b/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.h index 0f57230..d6cf0fd 100644 --- a/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.h +++ b/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.h @@ -24,6 +24,8 @@ struct ClothMeshData Triangle(uint32_t _a, uint32_t _b, uint32_t _c) : a(_a), b(_b), c(_c){} uint32_t a, b, c; + + Triangle operator+(uint32_t offset)const { return Triangle(a + offset, b + offset, c + offset); }; }; struct Quad { @@ -31,6 +33,8 @@ struct ClothMeshData Quad(uint32_t _a, uint32_t _b, uint32_t _c, uint32_t _d) : a(_a), b(_b), c(_c), d(_d){} uint32_t a, b, c, d; + + Quad operator+(uint32_t offset)const { return Quad(a + offset, b + offset, c + offset, d + offset); }; }; std::vector<physx::PxVec3> mVertices; std::vector<physx::PxVec2> mUvs; @@ -41,7 +45,7 @@ struct ClothMeshData SimpleMesh mMesh; void Clear(); - void GeneratePlaneCloth(float width, float height, int segmentsX, int segmentsY, bool createQuads = false, physx::PxMat44 transform = physx::PxIdentity, bool alternatingDiagonals = true); + void GeneratePlaneCloth(float width, float height, int segmentsX, int segmentsY, bool createQuads = false, physx::PxMat44 transform = physx::PxIdentity, bool alternatingDiagonals = true, int zigzag = 0); void AttachClothPlaneByAngles(int segmentsX, int segmentsY, bool attachByWidth = true); void AttachClothPlaneBySide(int segmentsX, int segmentsY, bool attachByWidth = true); @@ -51,4 +55,6 @@ struct ClothMeshData nv::cloth::ClothMeshDesc GetClothMeshDesc(); SimpleMesh GetRenderMesh(); + + void Merge(const ClothMeshData& other); }; diff --git a/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.cpp b/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.cpp new file mode 100644 index 0000000..72e60e8 --- /dev/null +++ b/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.cpp @@ -0,0 +1,21 @@ +/* +* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, 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. +*/ + +#include "DebugLineRenderBuffer.h" + +void DebugLineRenderBuffer::addLine(physx::PxVec3 a, physx::PxVec3 b, unsigned int color) +{ + m_lines.push_back(PxDebugLine(a, b, color)); +} + +void DebugLineRenderBuffer::addLine(physx::PxMat44 t, physx::PxVec3 a, physx::PxVec3 b, unsigned int color) +{ + m_lines.push_back(PxDebugLine(t.transform(a), t.transform(b), color)); +}
\ No newline at end of file diff --git a/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.h b/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.h new file mode 100644 index 0000000..ce800d5 --- /dev/null +++ b/NvCloth/samples/SampleBase/utils/DebugLineRenderBuffer.h @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, 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. +*/ + +#pragma once +#include "DebugRenderBuffer.h" +#include <foundation/PxVec3.h> +#include <foundation/PxMat44.h> + +class DebugLineRenderBuffer : public DebugRenderBuffer +{ +public: + void clear() { m_lines.clear(); } + void addLine(physx::PxVec3 a, physx::PxVec3 b, unsigned int color); + void addVector(physx::PxVec3 start, physx::PxVec3 vec, unsigned int color) { addLine(start, start + vec, color); } + + void addLine(physx::PxMat44 t, physx::PxVec3 a, physx::PxVec3 b, unsigned int color); + void addVector(physx::PxMat44 t, physx::PxVec3 start, physx::PxVec3 vec, unsigned int color) { addLine(t, start, start + vec, color); } +};
\ No newline at end of file diff --git a/NvCloth/samples/SampleBase/utils/MeshGenerator.cpp b/NvCloth/samples/SampleBase/utils/MeshGenerator.cpp new file mode 100644 index 0000000..857daed --- /dev/null +++ b/NvCloth/samples/SampleBase/utils/MeshGenerator.cpp @@ -0,0 +1,545 @@ + + +#include "./MeshGenerator.h" +#include <foundation/PxVec2.h> +#include <utility> +#include "utils/Utils.h" + +namespace MeshGenerator +{ + +void Polygon::triangulate(std::vector<Polygon>& out) const +{ + for(int i = 2; i < (int)mPoints.size(); i++) + { + out.push_back(Polygon(mPoints[0], mPoints[i - 1], mPoints[i])); + } +} + +void Polygon::triangulate(std::vector<RenderVertex>& verts, std::vector<uint16_t>& indices) const +{ + physx::PxVec3 normal = calculateNormal(); + for(int i = 2; i < (int)mPoints.size(); i++) + { + indices.push_back((uint16_t)verts.size()); + verts.push_back(RenderVertex(mPoints[0].p,normal)); + indices.push_back((uint16_t)verts.size()); + verts.push_back(RenderVertex(mPoints[i - 1].p, normal)); + indices.push_back((uint16_t)verts.size()); + verts.push_back(RenderVertex(mPoints[i].p, normal)); + } +} + +void Polygon::triangulateWeld(std::vector<RenderVertex>& verts, std::vector<uint16_t>& indices) const +{ + auto addVertex = [&verts, &indices](RenderVertex v) + { + for(int i = 0; i < (int)verts.size(); i++) + { + if((verts[i].p - v.p).magnitudeSquared() < 0.001f) + { + return i; + } + } + verts.push_back(v); + return (uint16_t)verts.size()-1; + }; + + physx::PxVec3 weightedNormal = calculateNormal()*calculateArea(); + + for(int i = 2; i < (int)mPoints.size(); i++) + { + indices.push_back(addVertex(RenderVertex(mPoints[0].p, weightedNormal))); + indices.push_back(addVertex(RenderVertex(mPoints[i - 1].p, weightedNormal))); + indices.push_back(addVertex(RenderVertex(mPoints[i].p, weightedNormal))); + } +} + +void Polygon::triangulateForCollision(std::vector<physx::PxVec3>& verts) const +{ + for(int i = 2; i < (int)mPoints.size(); i++) + { + verts.push_back(mPoints[0].p); + verts.push_back(mPoints[i - 1].p); + verts.push_back(mPoints[i].p); + } +} + +physx::PxVec3 Polygon::calculateNormal() const +{ + physx::PxVec3 normal(0.0f, 0.0f, 0.0f); + for(int i = 2; i < (int)mPoints.size(); i++) + { + physx::PxVec3 p[3]; + p[0] = mPoints[0].p; + p[1] = mPoints[i - 1].p; + p[2] = mPoints[i].p; + normal += (p[1] - p[0]).cross(p[2] - p[0]); + } + normal.normalize(); + return normal; +} + +float Polygon::calculateArea() const +{ + float doubleArea = 0.0f; + for(int i = 2; i < (int)mPoints.size(); i++) + { + physx::PxVec3 p[3]; + p[0] = mPoints[0].p; + p[1] = mPoints[i - 1].p; + p[2] = mPoints[i].p; + doubleArea += (p[1] - p[0]).cross(p[2] - p[0]).magnitude(); + } + return doubleArea*0.5f; +} + +void Polygon::subdivideTriangle(std::vector<Polygon>& out) const +{ + if(!isTriangle()) + return; + + for(int i = 0; i < 3; i++) + { + out.push_back(Polygon(Point(mPoints[i].p), Point(0.5f*(mPoints[(i+1)%3].p + mPoints[i].p)), Point(0.5f*(mPoints[(i + 2) % 3].p + mPoints[i].p)))); + } + out.push_back(Polygon(Point(0.5f*(mPoints[0].p + mPoints[1].p)), Point(0.5f*(mPoints[1].p + mPoints[2].p)), Point(0.5f*(mPoints[2].p + mPoints[0].p)))); + +} + +float intersetcLinePlane(physx::PxVec3 a, physx::PxVec3 b, physx::PxVec4 plane) +{ + physx::PxVec3 planeNormal(plane.x, plane.y, plane.z); + float aprj = planeNormal.dot(a); + float bprj = planeNormal.dot(b); + + return (-plane.w - aprj) / (bprj - aprj); +} + +bool Polygon::pointPlaneSide(physx::PxVec3 p, physx::PxVec4 plane) const +{ + physx::PxVec3 planeNormal(plane.x, plane.y, plane.z); + return p.dot(planeNormal) + plane.w < 0; +} + +void Polygon::clip(physx::PxVec4 plane, bool flip) +{ + if(mPoints.size() < 3) + return; + + std::vector<Point> input = mPoints; + mPoints.clear(); + + Point S = input.back(); + for(int pointIndex = 0; pointIndex < (int)input.size(); pointIndex++) + { + if(pointPlaneSide(input[pointIndex].p, plane) != flip) + { + if(pointPlaneSide(S.p, plane) == flip) + { + float w = intersetcLinePlane(S.p, input[pointIndex].p, plane); + mPoints.push_back(S * (1.0f - w) + input[pointIndex] * w); + } + mPoints.push_back(input[pointIndex]); + } + else if(pointPlaneSide(S.p, plane) != flip) + { + float w = intersetcLinePlane(S.p, input[pointIndex].p, plane); + mPoints.push_back(S * (1.0f - w) + input[pointIndex] * w); + } + S = input[pointIndex]; + } +} + +void Mesh::addConvexPolygon(physx::PxVec4 plane, physx::PxVec4* planes, uint32_t mask, bool flip) +{ + physx::PxVec3 t1, t2, normal; + normal.x = plane.x; + normal.y = plane.y; + normal.z = plane.z; + computeBasis(normal, &t1, &t2); + Polygon poly; + for(int i = 0; i < 4; i++) + { + float xTable[4] = {-1.0f, 1.0f, 1.0f, -1.0f}; + float yTable[4] = {-1.0f, -1.0f, 1.0f, 1.0f}; + poly.mPoints.push_back(normal*-plane.w + 200.0f*t1 * xTable[i] + 200.0f*t2 * yTable[i]); + //polyTexcoord.push_back(vec2(0.0f, 10.0f) * xTable[i] + vec2(10.0f, 0.0f) * yTable[i]); + } + + for(int i = 0; i < 32; i++) + { + if((1 << i) & mask) + { + const physx::PxVec4 pl = planes[i]; + poly.clip(pl, flip); + } + } + + mPolygons.push_back(poly); +} + +void Mesh::generateRenderBuffers(RenderVertex** vertices, uint16_t** indices, int* vertexCount, int* indexCount) const +{ + std::vector<RenderVertex> verts; + std::vector<uint16_t> inds; + verts.reserve(mPolygons.size()*3); + verts.reserve(inds.size()*3); + + for(auto& p : mPolygons) + { + p.triangulate(verts, inds); + } + + *vertices = new RenderVertex[verts.size()]; + *indices = new uint16_t[inds.size()]; + + memcpy(*vertices, verts.data(), sizeof(RenderVertex)*verts.size()); + memcpy(*indices, inds.data(), sizeof(uint16_t)*inds.size()); + *vertexCount = (uint16_t)verts.size(); + *indexCount = (uint16_t)inds.size(); +} + +void Mesh::generateSmoothRenderBuffers(RenderVertex** vertices, uint16_t** indices, int* vertexCount, int* indexCount) const +{ + std::vector<RenderVertex> verts; + std::vector<uint16_t> inds; + verts.reserve(mPolygons.size() * 3); + verts.reserve(inds.size() * 3); + + for(auto& p : mPolygons) + { + p.triangulateWeld(verts, inds); + } + + for(auto& v : verts) + { + v.n.normalize(); + } + + *vertices = new RenderVertex[verts.size()]; + *indices = new uint16_t[inds.size()]; + + memcpy(*vertices, verts.data(), sizeof(RenderVertex)*verts.size()); + memcpy(*indices, inds.data(), sizeof(uint16_t)*inds.size()); + *vertexCount = (uint16_t)verts.size(); + *indexCount = (uint16_t)inds.size(); + +} + +int Mesh::generateTriangleList(physx::PxVec3** positions) +{ + std::vector<physx::PxVec3> verts; + verts.reserve(mPolygons.size() * 3); + + for(auto& p : mPolygons) + { + p.triangulateForCollision(verts); + } + + *positions = new physx::PxVec3[verts.size()]; + memcpy(*positions, verts.data(), sizeof(physx::PxVec3)*verts.size()); + return (int)verts.size(); +} + +void Mesh::applyTransfom(physx::PxMat44 transform) +{ + for(auto& trig : mPolygons) + for(auto& point : trig.mPoints) + { + point.p = transform.transform(point.p); + } +} + +void Mesh::merge(const Mesh& mesh) +{ + mPolygons.insert(mPolygons.end(), mesh.mPolygons.begin(), mesh.mPolygons.end()); +} + +Mesh generateTetrahedron(float radius) +{ + Mesh mesh; + Point p[4]; + for(int i = 0; i < 3; i++) + { + p[i] = Point(radius*physx::PxVec3(cosf((float)i / 3.0f*PxTwoPi), -sqrtf(2.0f / 3.0f)*0.5f*sqrtf(3), sinf((float)i / 3.0f*PxTwoPi))); + } + p[3] = Point(radius*physx::PxVec3(0, sqrtf(2.0f / 3.0f)*0.5f*sqrtf(3), 0)); + + mesh.mPolygons.push_back(Polygon(p[0], p[1], p[2])); + mesh.mPolygons.push_back(Polygon(p[3], p[1], p[0])); + mesh.mPolygons.push_back(Polygon(p[3], p[2], p[1])); + mesh.mPolygons.push_back(Polygon(p[3], p[0], p[2])); + + return mesh; +} + +Mesh generateIcosahedron(float radius, int subdivisions) +{ + Mesh mesh; + Point p[12]; + + //generate positions + float goldenRatio = (1.0f + sqrtf(5.0f)) * 0.5f; + float scale = radius / physx::PxVec2(goldenRatio, 1.0f).magnitude(); + for(int j = 0; j < 3; j++) + for(int i = 0; i < 4; i++) + { + float signA = i & 1 ? 1.0f : -1.0f; + float signB = i & 2 ? -1.0f : 1.0f; + physx::PxVec3 point(signA, signB * goldenRatio, 0.0f); + p[i + 4 * j] = physx::PxVec3(point[j % 3], point[(j + 1) % 3], point[(j + 2) % 3]) * scale; + } + + //generate triangles + uint16_t ti[20 * 3] = + { + 0, 7, 9, + 0, 9, 1, + 0, 1, 11, + 0, 11, 6, + 0, 6, 7, + + 1, 9, 5, + 9, 7, 8, + 7, 6, 2, + 6, 11, 10, + 11, 1, 4, + + 3, 5, 8, + 3, 8, 2, + 3, 2, 10, + 3, 10, 4, + 3, 4, 5, + + 8, 5, 9, + 2, 8, 7, + 10, 2, 6, + 4, 10, 11, + 5, 4, 1 + }; + + for(int i = 0; i < 20*3; i += 3) + { + mesh.mPolygons.push_back(Polygon(p[ti[i]], p[ti[i+1]], p[ti[i+2]])); + } + + bool projectToSphere = subdivisions > 0; + while(subdivisions > 0) + { + subdivisions--; + Mesh sub; + for(auto& trig : mesh.mPolygons) + { + trig.subdivideTriangle(sub.mPolygons); + } + std::swap(sub.mPolygons, mesh.mPolygons); + } + + if(projectToSphere) + { + for(auto& trig : mesh.mPolygons) + for(auto& point : trig.mPoints) + { + point.p = point.p.getNormalized() * radius; + } + } + + return mesh; +} + +Mesh generateCone(physx::PxVec4 a, physx::PxVec4 b, int segments, float grow, bool correctCone) +{ + Mesh mesh; + + if(a.w < b.w) + std::swap(a, b); + + physx::PxVec3 aCenter = a.getXYZ(); + physx::PxVec3 bCenter = b.getXYZ(); + float aRadius = a.w + grow; + float bRadius = b.w + grow; + + physx::PxVec3 basis[3]; + basis[2] = bCenter - aCenter; + basis[2].normalize(); + computeBasis(basis[2], &basis[0], &basis[1]); + + physx::PxVec3 pa = aCenter + aRadius*basis[0]; + physx::PxVec3 pb = bCenter + bRadius*basis[0]; + physx::PxVec3 dir = pb - pa; + + physx::PxVec3 n = basis[2].cross(dir); + physx::PxVec3 n2 = dir.cross(n); + physx::PxVec3 focusPoint = aCenter + ((pa - aCenter).dot(n2)) / basis[2].dot(n2) * basis[2]; + + if(correctCone) + { + { + float focusDistance = (focusPoint - aCenter).magnitude(); + physx::PxVec3 cCenter = (focusPoint + aCenter)*0.5f; + float cRadius = focusDistance*0.5f; + float d = (aCenter - cCenter).magnitude(); + float a = (aRadius*aRadius - cRadius*cRadius + d*d) / (2.0f*d); + float h = sqrtf(aRadius*aRadius - a*a); + physx::PxVec3 P3 = aCenter + a * (cCenter - aCenter) / d; + + aCenter = P3; + aRadius = h; + } + + { + float focusDistance = (focusPoint - bCenter).magnitude(); + physx::PxVec3 cCenter = (focusPoint + bCenter)*0.5f; + float cRadius = focusDistance*0.5f; + float d = (bCenter - cCenter).magnitude(); + float a = (bRadius*bRadius - cRadius*cRadius + d*d) / (2.0f*d); + float h = sqrtf(bRadius*bRadius - a*a); + physx::PxVec3 P3 = bCenter + a * (cCenter - bCenter) / d; + + bCenter = P3; + bRadius = h; + } + } + + + for(int i = 0; i < segments; i++) + { + float angle1 = (float)i / (float)segments*physx::PxTwoPi; + float angle2 = (float)(i+1) / (float)segments*physx::PxTwoPi; + + Polygon p; + p.addPoints(Point(aCenter + (cosf(angle1)*basis[0] + sinf(angle1)*basis[1])*aRadius)); + p.addPoints(Point(aCenter + (cosf(angle2)*basis[0] + sinf(angle2)*basis[1])*aRadius)); + p.addPoints(Point(bCenter + (cosf(angle2)*basis[0] + sinf(angle2)*basis[1])*bRadius)); + p.addPoints(Point(bCenter + (cosf(angle1)*basis[0] + sinf(angle1)*basis[1])*bRadius)); + + mesh.mPolygons.push_back(p); + } + + return mesh; +} + +Mesh generateCollisionConvex(physx::PxVec4* planes, uint32_t mask, float grow, bool flip) +{ + Mesh mesh; + if(grow != 0.0f) + { + physx::PxVec4* grownPlanes = new physx::PxVec4[32]; + for(int i = 0; i < 32; i++) + { + if((1 << i) & mask) + { + grownPlanes[i] = planes[i]; + grownPlanes[i].w -= grow; + } + } + planes = grownPlanes; + } + + for(int i = 0; i < 32; i++) + { + if((1 << i) & mask) + mesh.addConvexPolygon(planes[i], planes, mask ^ (1 << i), flip); + } + + if(grow != 0.0f) + delete[] planes; + + return mesh; +} + +Mesh generateCollisionCapsules(physx::PxVec4* spheres, int sphereCount, uint32_t* indices, int indexCount, float grow) +{ + Mesh finalMesh; + for(int i = 0; i < sphereCount; i++) + { + Mesh sphere = generateIcosahedron(spheres[i].w+ grow, 4); + sphere.applyTransfom(physx::PxTransform(spheres[i].getXYZ())); + finalMesh.merge(sphere); + } + + for(int i = 0; i < indexCount; i += 2) + { + finalMesh.merge(generateCone(spheres[indices[i]], spheres[indices[i + 1]], 32, grow, true)); + } + + return finalMesh; +} + +uint32_t generateConvexPolyhedronPlanes(int segmentsX, int segmentsY, physx::PxVec3 center, float radius, std::vector<physx::PxVec4>* planes) +{ + int offset = 0; + if(planes) + { + planes->reserve(planes->size() + segmentsX*segmentsY); + offset = (int)planes->size(); + } + + segmentsY += 1; + for(int i = 1; i < segmentsY; i++) + { + float angleY = (float)i / (float)segmentsY * physx::PxPi + physx::PxPiDivTwo; + for(int j = 0; j < segmentsX; j++) + { + float angleX = (float)j / (float)segmentsX * physx::PxTwoPi; + + physx::PxVec3 nx(cosf(angleX), 0.0f, sinf(angleX)); + physx::PxVec3 n = cosf(angleY) * nx + sinf(angleY)*physx::PxVec3(0.0f, 1.0f, 0.0f); + + physx::PxVec3 p = n*radius + center; + + if(planes) planes->push_back(constructPlaneFromPointNormal(p, n)); + } + } + uint64_t shift = (segmentsX * (segmentsY - 1) + offset); + uint64_t excludeMask = (((uint64_t)1 << offset) - 1); + uint64_t mask = (((uint64_t)1 << shift) - 1) & ~excludeMask; + return static_cast<uint32_t>(mask); +} + +MeshGeneratorRenderMesh::MeshGeneratorRenderMesh(const Mesh mesh) +{ + RenderVertex* vertices; + uint16_t* indices; + int vertexCount, indexCount; + mesh.generateRenderBuffers(&vertices, &indices, &vertexCount, &indexCount); + + std::vector<D3D11_INPUT_ELEMENT_DESC> layout; + layout.push_back({"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}); + layout.push_back({"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}); + + initialize(vertices, (uint32_t)vertexCount, sizeof(RenderVertex), layout, indices, indexCount); + + delete vertices; + delete indices; +} +MeshGeneratorRenderMesh::~MeshGeneratorRenderMesh() +{ + +} + +MeshGeneratorRenderMeshSmooth::MeshGeneratorRenderMeshSmooth(const Mesh mesh) +{ + RenderVertex* vertices; + uint16_t* indices; + int vertexCount, indexCount; + mesh.generateSmoothRenderBuffers(&vertices, &indices, &vertexCount, &indexCount); + + std::vector<D3D11_INPUT_ELEMENT_DESC> layout; + layout.push_back({"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}); + layout.push_back({"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}); + + initialize(vertices, (uint32_t)vertexCount, sizeof(RenderVertex), layout, indices, indexCount); + + delete vertices; + delete indices; +} +MeshGeneratorRenderMeshSmooth::~MeshGeneratorRenderMeshSmooth() +{ + +} + + + +}
\ No newline at end of file diff --git a/NvCloth/samples/SampleBase/utils/MeshGenerator.h b/NvCloth/samples/SampleBase/utils/MeshGenerator.h new file mode 100644 index 0000000..4f4b0c9 --- /dev/null +++ b/NvCloth/samples/SampleBase/utils/MeshGenerator.h @@ -0,0 +1,114 @@ +/* +* Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA CORPORATION and its licensors retain all intellectual property +* and proprietary rights in and to this software, 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. +*/ + +#ifndef MESH_GENERATOR_H +#define MESH_GENERATOR_H + +#include <vector> +#include "renderer/CustomRenderMesh.h" +#include <foundation/PxVec3.h> + +namespace MeshGenerator +{ + +struct Point +{ + Point(){} + Point(physx::PxVec3 _p):p(_p){} + physx::PxVec3 p; + + Point operator*(float f) const { return Point(p*f); } + Point operator+(Point pt) const { return Point(p+pt.p); } +}; + +struct RenderVertex +{ + RenderVertex() {} + RenderVertex(physx::PxVec3 _p, physx::PxVec3 _n):p(_p),n(_n) {} + physx::PxVec3 p; + physx::PxVec3 n; +}; + +struct Polygon +{ + Polygon() {} + template<typename P, typename... Args> Polygon(P p1, P p2, P p3, Args... args) + { + addPoints(p1, p2, p3, args...); + } + + std::vector<Point> mPoints; + + bool isTriangle()const { return mPoints.size() == 3; } + + template<typename P, typename... Args> void addPoints(P p, Args... args) + { + mPoints.push_back(p); + addPoints(args...); + } + template<typename P> void addPoints(P p) + { + mPoints.push_back(p); + } + + void triangulate(std::vector<Polygon>& out) const; + void triangulate(std::vector<RenderVertex>& verts, std::vector<uint16_t>& indices) const; + void triangulateWeld(std::vector<RenderVertex>& verts, std::vector<uint16_t>& indices) const; //normalize normals afterwards + void triangulateForCollision(std::vector<physx::PxVec3>& verts) const; + physx::PxVec3 calculateNormal() const; + float calculateArea() const; + void subdivideTriangle(std::vector<Polygon>& out) const; + bool Polygon::pointPlaneSide(physx::PxVec3 p, physx::PxVec4 plane) const; + void clip(physx::PxVec4 plane, bool flip = false); +}; + +struct Mesh +{ + std::vector<Polygon> mPolygons; + + bool isTriangleMesh()const { bool b = true; for(const auto& p : mPolygons) { b = b && p.isTriangle(); } return b; } + + void addConvexPolygon(physx::PxVec4 plane, physx::PxVec4* planes, uint32_t mask, bool flip); + + void generateRenderBuffers(RenderVertex** vertices, uint16_t** indices, int* vertexCount, int* indexCount) const; + void generateSmoothRenderBuffers(RenderVertex** vertices, uint16_t** indices, int* vertexCount, int* indexCount) const; + int generateTriangleList(physx::PxVec3** positions); + + void applyTransfom(physx::PxMat44 transform); + + void merge(const Mesh& mesh); +}; + +Mesh generateTetrahedron(float radius); +Mesh generateIcosahedron(float radius, int subdivisions); +Mesh generateCone(physx::PxVec4 a, physx::PxVec4 b, int segments, float grow, bool correctCone); +Mesh generateCollisionConvex(physx::PxVec4* planes, uint32_t mask, float grow, bool flip); +Mesh generateCollisionCapsules(physx::PxVec4* spheres, int sphereCount, uint32_t* indices, int indexCount, float grow); + +uint32_t generateConvexPolyhedronPlanes(int segmentsX, int segmentsY, physx::PxVec3 center, float radius, std::vector<physx::PxVec4>* planes); + +class MeshGeneratorRenderMesh : public CustomRenderMesh +{ +public: + MeshGeneratorRenderMesh(const Mesh mesh); + virtual ~MeshGeneratorRenderMesh(); +}; + +class MeshGeneratorRenderMeshSmooth : public CustomRenderMesh +{ +public: + MeshGeneratorRenderMeshSmooth(const Mesh mesh); + virtual ~MeshGeneratorRenderMeshSmooth(); +}; + + +}; + +#endif
\ No newline at end of file diff --git a/NvCloth/samples/SampleBase/utils/Utils.h b/NvCloth/samples/SampleBase/utils/Utils.h index 5e84e8e..1a5d5ee 100644 --- a/NvCloth/samples/SampleBase/utils/Utils.h +++ b/NvCloth/samples/SampleBase/utils/Utils.h @@ -3,6 +3,8 @@ #include <DeviceManager.h> #include <assert.h> +#include <foundation/PxVec3.h> +#include <foundation/PxVec4.h> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -80,8 +82,32 @@ static const char* strext(const char* str) return ext; } +//Math utilities static inline float lerp(float a, float b, float t) { return a + (b - a) * t; } +/** returns a PxVec4 containing [x,y,z,d] for plane equation ax + by + cz + d = 0. +* Where plane contains p and has normal n. +*/ +inline physx::PxVec4 constructPlaneFromPointNormal(physx::PxVec3 p, physx::PxVec3 n) +{ + n.normalize(); + return physx::PxVec4(n, -p.dot(n)); +} + +/** returns two vectors in b and c so that [a b c] form a basis. +* a needs to be a unit vector. +*/ +inline void computeBasis(const physx::PxVec3& a, physx::PxVec3* b, physx::PxVec3* c) +{ + if(fabsf(a.x) >= 0.57735f) + *b = physx::PxVec3(a.y, -a.x, 0.0f); + else + *b = physx::PxVec3(0.0f, a.z, -a.y); + + *b = b->getNormalized(); + *c = a.cross(*b); +} + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |