diff --git a/sandbox/embed_selfhost_fullscreen.html b/sandbox/embed_selfhost_fullscreen.html index aa422b0..9523c96 100644 --- a/sandbox/embed_selfhost_fullscreen.html +++ b/sandbox/embed_selfhost_fullscreen.html @@ -28,6 +28,7 @@ + diff --git a/sandbox/embed_selfhost_multiple.html b/sandbox/embed_selfhost_multiple.html index f667d31..97aae2f 100644 --- a/sandbox/embed_selfhost_multiple.html +++ b/sandbox/embed_selfhost_multiple.html @@ -30,6 +30,7 @@ + diff --git a/sandbox/embed_selfhost_single.html b/sandbox/embed_selfhost_single.html index 062dc2f..305cc9d 100644 --- a/sandbox/embed_selfhost_single.html +++ b/sandbox/embed_selfhost_single.html @@ -28,6 +28,7 @@ + diff --git a/sandbox/embed_selfhost_single_scroll.html b/sandbox/embed_selfhost_single_scroll.html index 47b7388..915c37e 100644 --- a/sandbox/embed_selfhost_single_scroll.html +++ b/sandbox/embed_selfhost_single_scroll.html @@ -28,6 +28,7 @@ + diff --git a/source/model/modelutils.js b/source/model/modelutils.js index a19d39b..ade114f 100644 --- a/source/model/modelutils.js +++ b/source/model/modelutils.js @@ -212,3 +212,41 @@ OV.GetMeshBoundingBox = function (mesh) } return calculator.GetBox (); }; + +OV.GetModelBoundingBox = function (model) +{ + let calculator = new OV.BoundingBoxCalculator3D (); + for (let i = 0; i < model.MeshCount (); i++) { + let mesh = model.GetMesh (i); + for (let j = 0; j < mesh.VertexCount (); j++) { + let vertex = mesh.GetVertex (j); + calculator.AddPoint (vertex); + } + } + return calculator.GetBox (); +}; + +OV.GetModelTopology = function (model) +{ + function GetVertexIndex (vertex, octree, topology) + { + let index = octree.FindPoint (vertex); + if (index === null) { + index = topology.AddVertex (); + octree.AddPoint (vertex, index); + } + return index; + } + + let boundingBox = OV.GetModelBoundingBox (model); + let octree = new OV.Octree (boundingBox); + let topology = new OV.Topology (); + + OV.EnumerateModelTriangles (model, function (v0, v1, v2) { + let v0Index = GetVertexIndex (v0, octree, topology); + let v1Index = GetVertexIndex (v1, octree, topology); + let v2Index = GetVertexIndex (v2, octree, topology); + topology.AddTriangle (v0Index, v1Index, v2Index); + }); + return topology; +}; diff --git a/source/model/topology.js b/source/model/topology.js new file mode 100644 index 0000000..4209841 --- /dev/null +++ b/source/model/topology.js @@ -0,0 +1,138 @@ +OV.TopologyVertex = class +{ + constructor () + { + this.edges = []; + this.triangles = []; + } +}; + +OV.TopologyEdge = class +{ + constructor (vertex1, vertex2) + { + this.vertex1 = vertex1; + this.vertex2 = vertex2; + this.triangles = []; + } +}; + +OV.TopologyTriangleEdge = class +{ + constructor (edge, reversed) + { + this.edge = edge; + this.reversed = reversed; + } +}; + +OV.TopologyTriangle = class +{ + constructor () + { + this.triEdge1 = null; + this.triEdge2 = null; + this.triEdge3 = null; + } +}; + +OV.Topology = class +{ + constructor () + { + this.vertices = []; + this.edges = []; + this.triangleEdges = []; + this.triangles = []; + this.edgeStartToEndVertexMap = {}; + } + + AddVertex () + { + this.vertices.push (new OV.TopologyVertex ()); + return this.vertices.length - 1; + } + + AddTriangle (vertex1, vertex2, vertex3) + { + function AddTriangleToVertex (vertices, vertexIndex, triangleIndex) + { + let vertex = vertices[vertexIndex]; + vertex.triangles.push (triangleIndex); + } + + function AddEdgeToVertex (vertices, triangleEdges, vertexIndex, triangleEdgeIndex) + { + let vertex = vertices[vertexIndex]; + let triangleEdge = triangleEdges[triangleEdgeIndex]; + vertex.edges.push (triangleEdge.edge); + } + + function AddTriangleToEdge (edges, triangleEdges, triangleEdgeIndex, triangleIndex) + { + let triangleEdge = triangleEdges[triangleEdgeIndex]; + let edge = edges[triangleEdge.edge]; + edge.triangles.push (triangleIndex); + } + + let triangleIndex = this.triangles.length; + let triangle = new OV.TopologyTriangle (); + triangle.triEdge1 = this.AddTriangleEdge (vertex1, vertex2); + triangle.triEdge2 = this.AddTriangleEdge (vertex2, vertex3); + triangle.triEdge3 = this.AddTriangleEdge (vertex3, vertex1); + + AddTriangleToVertex (this.vertices, vertex1, triangleIndex); + AddTriangleToVertex (this.vertices, vertex2, triangleIndex); + AddTriangleToVertex (this.vertices, vertex3, triangleIndex); + + AddEdgeToVertex (this.vertices, this.triangleEdges, vertex1, triangle.triEdge1); + AddEdgeToVertex (this.vertices, this.triangleEdges, vertex2, triangle.triEdge2); + AddEdgeToVertex (this.vertices, this.triangleEdges, vertex3, triangle.triEdge3); + + AddTriangleToEdge (this.edges, this.triangleEdges, triangle.triEdge1, triangleIndex); + AddTriangleToEdge (this.edges, this.triangleEdges, triangle.triEdge2, triangleIndex); + AddTriangleToEdge (this.edges, this.triangleEdges, triangle.triEdge3, triangleIndex); + + this.triangles.push (triangle); + } + + AddTriangleEdge (vertex1, vertex2) + { + let startVertex = vertex1; + let endVertex = vertex2; + let reversed = false; + if (vertex2 < vertex1) { + startVertex = vertex2; + endVertex = vertex1; + reversed = true; + } + + let edgeIndex = this.AddEdge (startVertex, endVertex); + this.triangleEdges.push (new OV.TopologyTriangleEdge (edgeIndex, reversed)); + return this.triangleEdges.length - 1; + } + + AddEdge (startVertex, endVertex) + { + if (this.edgeStartToEndVertexMap[startVertex] === undefined) { + this.edgeStartToEndVertexMap[startVertex] = []; + } + + let endVertices = this.edgeStartToEndVertexMap[startVertex]; + for (let i = 0; i < endVertices.length; i++) { + let endVertexItem = endVertices[i]; + if (endVertexItem.endVertex === endVertex) { + return endVertexItem.edgeIndex; + } + } + + let edgeIndex = this.edges.length; + endVertices.push ({ + endVertex : endVertex, + edgeIndex : edgeIndex + }); + + this.edges.push (new OV.TopologyEdge (startVertex, endVertex)); + return edgeIndex; + } +}; diff --git a/test/tests/modelutils_test.js b/test/tests/modelutils_test.js index 3a3d2e2..563dcbd 100644 --- a/test/tests/modelutils_test.js +++ b/test/tests/modelutils_test.js @@ -128,7 +128,7 @@ describe ('Model Utils', function () { return Math.sqrt (areaSquare); } - var model = testUtils.GetCubeModel (); + var model = testUtils.GetModelWithOneMesh (testUtils.GetCubeMesh ()); let surface = 0.0; let volume = 0.0; for (let i = 0; i < model.MeshCount (); i++) { @@ -146,4 +146,54 @@ describe ('Model Utils', function () { assert (OV.IsEqual (volume, 1.0)); assert (OV.IsEqual (surface, 6.0)); }); + + it ('Tetrahedron Topology Calculation', function () { + let tetrahedron = testUtils.GetModelWithOneMesh (testUtils.GetTetrahedronMesh ()); + let topology = OV.GetModelTopology (tetrahedron); + assert.strictEqual (topology.vertices.length, 4); + assert.strictEqual (topology.edges.length, 6); + assert.strictEqual (topology.triangleEdges.length, 4 * 3); + assert.strictEqual (topology.triangles.length, 4); + for (let i = 0; i < topology.vertices.length; i++) { + assert.strictEqual (topology.vertices[i].edges.length, 3); + assert.strictEqual (topology.vertices[i].triangles.length, 3); + } + for (let i = 0; i < topology.edges.length; i++) { + assert.strictEqual (topology.edges[i].triangles.length, 2); + } + }); + + it ('Cube Topology Calculation', function () { + let cube = testUtils.GetModelWithOneMesh (testUtils.GetCubeMesh ()); + let topology = OV.GetModelTopology (cube); + assert.strictEqual (topology.vertices.length, 8); + assert.strictEqual (topology.edges.length, 12 + 6); + assert.strictEqual (topology.triangleEdges.length, 6 * 2 * 3); + assert.strictEqual (topology.triangles.length, 6 * 2); + + let verticesWith4Triangles = 0; + let verticesWith5Triangles = 0; + let verticesWith4Edges = 0; + let verticesWith5Edges = 0; + for (let i = 0; i < topology.vertices.length; i++) { + if (topology.vertices[i].triangles.length == 4) { + verticesWith4Triangles += 1; + } else if (topology.vertices[i].triangles.length == 5) { + verticesWith5Triangles += 1; + } + if (topology.vertices[i].edges.length == 4) { + verticesWith4Edges += 1; + } else if (topology.vertices[i].edges.length == 5) { + verticesWith5Edges += 1; + } + } + assert.strictEqual (verticesWith4Triangles, 4); + assert.strictEqual (verticesWith5Triangles, 4); + assert.strictEqual (verticesWith4Edges, 4); + assert.strictEqual (verticesWith5Edges, 4); + + for (let i = 0; i < topology.edges.length; i++) { + assert.strictEqual (topology.edges[i].triangles.length, 2); + } + }); }); diff --git a/test/utils/testutils.js b/test/utils/testutils.js index 6a38c46..8d247aa 100644 --- a/test/utils/testutils.js +++ b/test/utils/testutils.js @@ -163,12 +163,28 @@ module.exports = return cube; }, - GetCubeModel () + GetTetrahedronMesh () + { + var tetrahedron = new OV.Mesh (); + + let a = 1.0; + tetrahedron.AddVertex (new OV.Coord3D (+a, +a, +a)); + tetrahedron.AddVertex (new OV.Coord3D (-a, -a, +a)); + tetrahedron.AddVertex (new OV.Coord3D (-a, +a, -a)); + tetrahedron.AddVertex (new OV.Coord3D (+a, -a, -a)); + tetrahedron.AddTriangle (new OV.Triangle (0, 1, 3)); + tetrahedron.AddTriangle (new OV.Triangle (0, 2, 1)); + tetrahedron.AddTriangle (new OV.Triangle (0, 3, 2)); + tetrahedron.AddTriangle (new OV.Triangle (1, 2, 3)); + + return tetrahedron; + }, + + GetModelWithOneMesh (mesh) { var model = new OV.Model (); - var cube = this.GetCubeMesh (); - model.AddMesh (cube); + model.AddMesh (mesh); OV.FinalizeModel (model, function () { new OV.Material () }); return model; - } + } } diff --git a/tools/config.json b/tools/config.json index a3954ed..d44a042 100644 --- a/tools/config.json +++ b/tools/config.json @@ -24,6 +24,7 @@ "source/model/mesh.js", "source/model/meshbuffer.js", "source/model/model.js", + "source/model/topology.js", "source/model/modelutils.js", "source/model/modelfinalization.js", "source/import/importerutils.js", diff --git a/website/embed.html b/website/embed.html index 115ccbe..356f0da 100644 --- a/website/embed.html +++ b/website/embed.html @@ -37,6 +37,7 @@ + diff --git a/website/index.html b/website/index.html index bebe7a4..80cecc0 100644 --- a/website/index.html +++ b/website/index.html @@ -37,6 +37,7 @@ +