diff options
| author | Andrew Reidmeyer <[email protected]> | 2017-03-15 09:28:59 -0600 |
|---|---|---|
| committer | Andrew Reidmeyer <[email protected]> | 2017-03-15 09:28:59 -0600 |
| commit | f5f6a899903a309f1fc93b31c0297fc7b3b5cf46 (patch) | |
| tree | ed3dece338b579d5b51af494b2d543fb46c43fa3 /demo/DemoApp/mesh.cpp | |
| download | flow-f5f6a899903a309f1fc93b31c0297fc7b3b5cf46.tar.xz flow-f5f6a899903a309f1fc93b31c0297fc7b3b5cf46.zip | |
Initial 1.0.0 binary releasev1.0.0
Diffstat (limited to 'demo/DemoApp/mesh.cpp')
| -rw-r--r-- | demo/DemoApp/mesh.cpp | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/demo/DemoApp/mesh.cpp b/demo/DemoApp/mesh.cpp new file mode 100644 index 0000000..26acb2f --- /dev/null +++ b/demo/DemoApp/mesh.cpp @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2014-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 "mesh.h" + +#include <vector> + +struct Mesh +{ + std::vector<MeshVertex> m_vertices; + std::vector<MeshUint> m_indices; + + float m_bounds[6] = { 0.f, 0.f, 0.f, 0.f, 0.f, 0.f }; + + MeshContext* m_context = nullptr; + MeshIndexBuffer* m_indexBuffer = nullptr; + MeshVertexBuffer* m_vertexBuffer = nullptr; + + Mesh() {} + + void loadFromPLY(const char* filename); + + void computeBounds(); + + void normalize(); +}; + +Mesh* MeshCreate(MeshContext* context) +{ + Mesh* mesh = new Mesh; + + mesh->m_context = context; + + return mesh; +} + +void MeshLoadFromFile(Mesh* mesh, const char* filename) +{ + MeshIndexBufferRelease(mesh->m_indexBuffer); + MeshVertexBufferRelease(mesh->m_vertexBuffer); + + mesh->loadFromPLY(filename); + + mesh->computeBounds(); + + mesh->normalize(); + + mesh->m_vertexBuffer = MeshVertexBufferCreate(mesh->m_context, &mesh->m_vertices[0], (MeshUint)mesh->m_vertices.size()); + mesh->m_indexBuffer = MeshIndexBufferCreate(mesh->m_context, &mesh->m_indices[0], (MeshUint)mesh->m_indices.size()); +} + +void MeshGetData(Mesh* mesh, MeshData* data) +{ + data->numVertices = (MeshUint) mesh->m_vertices.size(); + data->positions = &mesh->m_vertices[0].x; + data->positionStride = sizeof(MeshVertex); + data->normals = &mesh->m_vertices[0].nx; + data->normalStride = sizeof(MeshVertex); + + data->numIndices = (MeshUint) mesh->m_indices.size(); + data->indices = &mesh->m_indices[0]; + + data->boundsMin[0] = mesh->m_bounds[0]; + data->boundsMin[1] = mesh->m_bounds[1]; + data->boundsMin[2] = mesh->m_bounds[2]; + data->boundsMax[0] = mesh->m_bounds[3]; + data->boundsMax[1] = mesh->m_bounds[4]; + data->boundsMax[2] = mesh->m_bounds[5]; +} + +void MeshDraw(Mesh* mesh, const MeshDrawParams* params) +{ + MeshContextDrawParams drawParams; + drawParams.params = params; + drawParams.indexBuffer = mesh->m_indexBuffer; + drawParams.vertexBuffer = mesh->m_vertexBuffer; + + MeshContextDraw(mesh->m_context, &drawParams); +} + +void MeshRelease(Mesh* mesh) +{ + if (mesh == nullptr) return; + + MeshIndexBufferRelease(mesh->m_indexBuffer); + MeshVertexBufferRelease(mesh->m_vertexBuffer); + + delete mesh; +} + +/// **************** Private functions ******************************* + +void Mesh::computeBounds() +{ + size_t imax = m_vertices.size(); + if (imax >= 1) + { + m_bounds[0] = m_bounds[3] = m_vertices[0].x; + m_bounds[1] = m_bounds[4] = m_vertices[0].y; + m_bounds[2] = m_bounds[5] = m_vertices[0].z; + + for (size_t i = 1; i < imax; i++) + { + m_bounds[0] = fminf(m_bounds[0], m_vertices[i].x); + m_bounds[3] = fmaxf(m_bounds[3], m_vertices[i].x); + m_bounds[1] = fminf(m_bounds[1], m_vertices[i].y); + m_bounds[4] = fmaxf(m_bounds[4], m_vertices[i].y); + m_bounds[2] = fminf(m_bounds[2], m_vertices[i].z); + m_bounds[5] = fmaxf(m_bounds[5], m_vertices[i].z); + } + } +} + +void Mesh::normalize() +{ + size_t imax = m_vertices.size(); + for (size_t i = 0; i < imax; i++) + { + float x, y, z, w; + x = m_vertices[i].nx; + y = m_vertices[i].ny; + z = m_vertices[i].nz; + w = sqrtf(x*x + y*y + z*z); + if (w > 0.f) + { + x /= w; + y /= w; + z /= w; + } + m_vertices[i].nx = x; + m_vertices[i].ny = y; + m_vertices[i].nz = z; + } +} + +/// ****************** PLY mesh support ******************************* + +namespace +{ + struct PLYLoader + { + enum ElementType + { + ELEM_VERTEX = 0, + ELEM_FACE, + ELEM_EDGE, + ELEM_INVALID + }; + + enum Format + { + FORMAT_ASCII = 0, + FORMAT_BINARY_LITTLE_ENDIAN, + FORMAT_BINARY_BIG_ENDIAN, + FORMAT_INVALID + }; + + // temporary variables + FILE* file = nullptr; + + static const int bufSize = 1024u; + char buf[bufSize]; + + ElementType elementType = ELEM_INVALID; + Format format = FORMAT_INVALID; + + int numElements[ELEM_INVALID] = { 0 }; + int numProperties[ELEM_INVALID] = { 0 }; + + int elementList[ELEM_INVALID] = { 0 }; + int elementListIdx = 0; + + // captured variables + std::vector<MeshVertex>& m_vertices; + std::vector<uint32_t>& m_indices; + + // capture in constructor + PLYLoader(Mesh& mesh) : + m_vertices(mesh.m_vertices), + m_indices(mesh.m_indices) + { + } + + // utility functions + void getline() + { + fgets(buf, bufSize, file); + }; + void getstr() + { + fscanf_s(file, "%s", buf, bufSize); + }; + int getint() + { + int i = 0; + fscanf_s(file, "%d", &i); + return i; + }; + bool match(const char* key) + { + return strncmp(buf, key, bufSize) == 0; + }; + + // temporary state + int elemType = ELEM_INVALID; + int elemNum = 0; + int elemProperties = 0; + + template<class getFloatType, class advanceFuncType> + void getVertices(getFloatType getFloat, advanceFuncType advanceFunc) + { + for (int i = 0; i < elemNum; i++) + { + float data[6]; + for (int j = 0; j < elemProperties; j++) + { + float val = getFloat(); + if (j < 6) data[j] = val; + } + m_vertices.push_back(MeshVertex{ + data[0], data[1], data[2], + data[3], data[4], data[5] + }); + advanceFunc(); + } + } + + template<class getCountType, class getIndexType, class advanceFuncType> + void getIndices(getCountType getCount, getIndexType getIndex, advanceFuncType advanceFunc) + { + for (int i = 0; i < elemNum; i++) + { + int count = getCount(); + int indices[4]; + if (count > 0) indices[0] = getIndex(); + if (count > 1) indices[1] = getIndex(); + if (count > 2) indices[2] = getIndex(); + if (count > 3) indices[3] = getIndex(); + + if (count >= 3) + { + m_indices.push_back(indices[0]); + m_indices.push_back(indices[1]); + m_indices.push_back(indices[2]); + } + if (count == 4) + { + m_indices.push_back(indices[2]); + m_indices.push_back(indices[3]); + m_indices.push_back(indices[0]); + } + advanceFunc(); + } + } + + // main phases + bool parseHeader() + { + // verify file format + getstr(); + if (match("ply")) + { + // extra header information + while (feof(file) == 0) + { + getstr(); + if (match("element")) + { + getstr(); + if (match("vertex")) { + elementType = ELEM_VERTEX; + } + else if (match("face")) { + elementType = ELEM_FACE; + } + else if (match("edge")) { + elementType = ELEM_EDGE; + } + unsigned int idx = (unsigned int)elementType; + if (idx < ELEM_INVALID) + { + numElements[idx] = getint(); + } + if (elementListIdx < ELEM_INVALID) + { + elementList[elementListIdx++] = elementType; + } + } + else if (match("format")) + { + getstr(); + if (match("ascii")) { + format = FORMAT_ASCII; + } + else if (match("binary_big_endian")) { + format = FORMAT_BINARY_BIG_ENDIAN; + } + else if (match("binary_little_endian")) { + format = FORMAT_BINARY_LITTLE_ENDIAN; + } + } + else if (match("property")) + { + unsigned int idx = (unsigned int)elementType; + if (idx < ELEM_INVALID) + { + numProperties[idx]++; + } + } + else if (match("end_header")) + { + break; + } + } // end read header + + // advance past newline + getline(); + return true; + } + return false; + } + + void loadData() + { + // read in each element type + for (int eidx = 0; eidx < elementListIdx; eidx++) + { + elemType = elementList[eidx]; + elemNum = numElements[elemType]; + elemProperties = numProperties[elemType]; + + if (elemType == ELEM_VERTEX) + { + // size vertex buffers + m_vertices.reserve(elemNum); + + if (format == FORMAT_ASCII) + { + getVertices( + [&]() + { + float val = 0.f; + fscanf_s(file, "%f", &val); + return val; + }, + [&]() + { + getline(); + } + ); + } + else if (format == FORMAT_BINARY_BIG_ENDIAN) + { + getVertices( + [&]() + { + char data0[4]; + fread(data0, sizeof(float), 1, file); + union + { + char data1[4]; + float val; + }; + data1[0] = data0[3]; + data1[1] = data0[2]; + data1[2] = data0[1]; + data1[3] = data0[0]; + return val; + }, + [&]() + { + } + ); + } + else if (format == FORMAT_BINARY_LITTLE_ENDIAN) + { + getVertices( + [&]() + { + float val = 0.f; + fread(&val, sizeof(float), 1, file); + return val; + }, + [&]() + { + } + ); + } + } + else if (elemType == ELEM_FACE) + { + // size vertex buffers + m_indices.reserve(3 * elemNum); + + if (format == FORMAT_ASCII) + { + getIndices( + [&]() + { + return getint(); + }, + [&]() + { + return getint(); + }, + [&]() + { + getline(); + } + ); + } + else if (format == FORMAT_BINARY_BIG_ENDIAN) + { + getIndices( + [&]() + { + int val = 0; + fread(&val, 1, 1, file); + return val; + }, + [&]() + { + char data0[4]; + fread(data0, sizeof(float), 1, file); + union + { + char data1[4]; + int val; + }; + data1[0] = data0[3]; + data1[1] = data0[2]; + data1[2] = data0[1]; + data1[3] = data0[0]; + return val; + }, + [&]() + { + } + ); + } + else if (format == FORMAT_BINARY_LITTLE_ENDIAN) + { + getIndices( + [&]() + { + int val = 0; + fread(&val, 1, 1, file); + return val; + }, + [&]() + { + int val; + fread(&val, sizeof(int), 1, file); + return val; + }, + [&]() + { + } + ); + } + } + else if (elemType == ELEM_EDGE) + { + + } + } + } + + // main entry point + void operator()(const char* filename) + { + fopen_s(&file, filename, "rb"); + if (file) + { + if (parseHeader()) + { + loadData(); + } + fclose(file); + } + } + }; +} + +void Mesh::loadFromPLY(const char* filename) +{ + PLYLoader loader(*this); + loader(filename); +}
\ No newline at end of file |