diff --git a/source/core/core.js b/source/core/core.js index 1fd1ef4..17f93e9 100644 --- a/source/core/core.js +++ b/source/core/core.js @@ -2,3 +2,11 @@ OV = { }; + +OV.ValueOrDefault = function (val, def) +{ + if (val === undefined || val === null) { + return def; + } + return val; +}; diff --git a/source/import/importero3dv.js b/source/import/importero3dv.js index 174aae7..67c8b87 100644 --- a/source/import/importero3dv.js +++ b/source/import/importero3dv.js @@ -103,7 +103,8 @@ OV.ImporterO3dv = class extends OV.ImporterBase if (parameters.radius === undefined || parameters.height === undefined || parameters.segments === undefined) { return; } - const mesh = OV.GenerateCylinder (genParams, parameters.radius, parameters.height, parameters.segments); + let isSmooth = OV.ValueOrDefault (parameters.smooth, true); + const mesh = OV.GenerateCylinder (genParams, parameters.radius, parameters.height, parameters.segments, isSmooth); this.model.AddMesh (mesh); } } diff --git a/source/model/generator.js b/source/model/generator.js index f02efe6..8b695fa 100644 --- a/source/model/generator.js +++ b/source/model/generator.js @@ -41,6 +41,7 @@ OV.Generator = class if (this.params.name !== null) { this.mesh.SetName (this.params.name); } + this.curve = null; } GetMesh () @@ -57,15 +58,33 @@ OV.Generator = class return this.mesh.AddVertex (coord); } + SetCurve (curve) + { + this.curve = curve; + } + + ResetCurve () + { + this.curve = null; + } + AddTriangle (v0, v1, v2) { let triangle = new OV.Triangle (v0, v1, v2); if (this.params.material !== null) { triangle.SetMaterial (this.params.material); } + if (this.curve !== null) { + triangle.SetCurve (this.curve); + } return this.mesh.AddTriangle (triangle); } + AddTriangleInverted (v0, v1, v2) + { + this.AddTriangle (v0, v2, v1); + } + AddConvexPolygon (vertices) { for (let vertexIndex = 0; vertexIndex < vertices.length - 2; vertexIndex++) { @@ -76,53 +95,79 @@ OV.Generator = class ); } } + + AddConvexPolygonInverted (vertices) + { + for (let vertexIndex = 0; vertexIndex < vertices.length - 2; vertexIndex++) { + this.AddTriangleInverted ( + vertices[0], + vertices[vertexIndex + 1], + vertices[vertexIndex + 2] + ); + } + } }; - -OV.GenerateExtrude = function (genParams, vertices, height) +OV.GeneratorHelper = class { - let generator = new OV.Generator (genParams); - - let topPolygon = []; - let bottomPolygon = []; - for (let i = 0; i < vertices.length; i++) { - const vertex = vertices[i]; - generator.AddVertex (vertex.x, vertex.y, 0.0); - generator.AddVertex (vertex.x, vertex.y, height); - topPolygon.push (i * 2 + 1); - bottomPolygon.push (2 * vertices.length - (i + 1) * 2); + constructor (generator) + { + this.generator = generator; } - for (let i = 0; i < vertices.length; i++) { - const bottom = i * 2; - const bottomNext = (i < vertices.length - 1) ? bottom + 2 : 0; - const top = i * 2 + 1; - const topNext = (i < vertices.length - 1) ? top + 2 : 1; - generator.AddConvexPolygon ([ - bottom, - bottomNext, - topNext, - top - ]); + GenerateExtrude (vertices, height, isSmooth) + { + let topPolygon = []; + let bottomPolygon = []; + for (let i = 0; i < vertices.length; i++) { + const vertex = vertices[i]; + bottomPolygon.push (this.generator.AddVertex (vertex.x, vertex.y, 0.0)); + topPolygon.push (this.generator.AddVertex (vertex.x, vertex.y, height)); + } + if (isSmooth) { + this.generator.SetCurve (1); + } + this.GenerateSurfaceBetweenPolygons (bottomPolygon, topPolygon, isSmooth); + this.generator.ResetCurve (); + + this.generator.AddConvexPolygonInverted (bottomPolygon); + this.generator.AddConvexPolygon (topPolygon); } - generator.AddConvexPolygon (bottomPolygon); - generator.AddConvexPolygon (topPolygon); - return generator.GetMesh (); + GenerateSurfaceBetweenPolygons (startIndices, endIndices) + { + if (startIndices.length !== endIndices.length) { + return; + } + const vertexCount = startIndices.length; + for (let i = 0; i < vertexCount; i++) { + const index = i; + const nextIndex = (i < vertexCount - 1) ? index + 1 : 0; + this.generator.AddConvexPolygon ([ + startIndices[index], + startIndices[nextIndex], + endIndices[nextIndex], + endIndices[index] + ]); + } + } }; OV.GenerateCuboid = function (genParams, xSize, ySize, zSize) { + let generator = new OV.Generator (genParams); let vertices = [ new OV.Coord2D (0.0, 0.0), new OV.Coord2D (xSize, 0.0), new OV.Coord2D (xSize, ySize), new OV.Coord2D (0.0, ySize), ]; - return OV.GenerateExtrude (genParams, vertices, zSize); + let helper = new OV.GeneratorHelper (generator); + helper.GenerateExtrude (vertices, zSize, false); + return generator.GetMesh (); }; -OV.GenerateCylinder = function (genParams, radius, height, segments) +OV.GenerateCylinder = function (genParams, radius, height, segments, isSmooth) { function GetCylindricalCoord (radius, angle) { @@ -132,11 +177,14 @@ OV.GenerateCylinder = function (genParams, radius, height, segments) ); } + let generator = new OV.Generator (genParams); let baseVertices = []; const step = 2.0 * Math.PI / segments; for (let i = 0; i < segments; i++) { let cylindrical = GetCylindricalCoord (radius, i * step); baseVertices.push (cylindrical); } - return OV.GenerateExtrude (genParams, baseVertices, height); + let helper = new OV.GeneratorHelper (generator); + helper.GenerateExtrude (baseVertices, height, isSmooth); + return generator.GetMesh (); }; diff --git a/test/testfiles/o3dv/cylinder_non_smooth.o3dv b/test/testfiles/o3dv/cylinder_non_smooth.o3dv new file mode 100644 index 0000000..d7b3d24 --- /dev/null +++ b/test/testfiles/o3dv/cylinder_non_smooth.o3dv @@ -0,0 +1,13 @@ +{ + "meshes" : [ + { + "type" : "cylinder", + "parameters" : { + "radius" : 0.5, + "height" : 1.0, + "segments" : 20, + "smooth" : false + } + } + ] +} diff --git a/test/tests/generator_test.js b/test/tests/generator_test.js index 516c378..eb090c6 100644 --- a/test/tests/generator_test.js +++ b/test/tests/generator_test.js @@ -29,7 +29,7 @@ describe ('Generator', function () { }); it ('Cylinder with Default Parameters', function () { - const cylinder = OV.GenerateCylinder (null, 0.5, 1.0, 10); + const cylinder = OV.GenerateCylinder (null, 0.5, 1.0, 10, false); assert (OV.IsSolid (cylinder)); assert (OV.IsEqualEps (OV.CalculateVolume (cylinder), Math.PI * 0.5 * 0.5 * 1.0, 0.1)); }); diff --git a/test/tests/importero3dv_test.js b/test/tests/importero3dv_test.js index 86a947a..2f28d4c 100644 --- a/test/tests/importero3dv_test.js +++ b/test/tests/importero3dv_test.js @@ -119,6 +119,32 @@ describe ('O3dv Importer', function () { it ('cylinder.o3dv', function (done) { testFiles.ImportO3dvFile ('cylinder.o3dv', function (model) { + assert (OV.CheckModel (model)); + assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), { + name : '', + materials : [ + { name : '' } + ], + meshes : [ + { + name : '', + vertexCount : 40, + normalCount : 156, + uvCount : 0, + triangleCount : 76, + boundingBox : { + min : [-0.5, -0.5, 0], + max : [0.5, 0.5, 1] + } + } + ] + }); + done (); + }); + }); + + it ('cylinder_non_smooth.o3dv', function (done) { + testFiles.ImportO3dvFile ('cylinder_non_smooth.o3dv', function (model) { assert (OV.CheckModel (model)); assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), { name : '', @@ -141,5 +167,5 @@ describe ('O3dv Importer', function () { }); done (); }); - }); + }); });