Add sphere generator.

This commit is contained in:
kovacsv 2021-07-24 09:58:21 +02:00
parent 6169e39450
commit c1a9cae13f
11 changed files with 196 additions and 110 deletions

View File

@ -107,6 +107,14 @@ OV.ImporterO3dv = class extends OV.ImporterBase
let smooth = OV.ValueOrDefault (parameters.smooth, true);
const mesh = OV.GenerateCylinder (genParams, parameters.radius, parameters.height, segments, smooth);
this.model.AddMesh (mesh);
} else if (meshContent.type === 'sphere') {
if (parameters.radius === undefined) {
return;
}
let segments = OV.ValueOrDefault (parameters.segments, 20);
let smooth = OV.ValueOrDefault (parameters.smooth, true);
const mesh = OV.GenerateSphere (genParams, parameters.radius, segments, smooth);
this.model.AddMesh (mesh);
}
}
};

View File

@ -58,6 +58,16 @@ OV.Generator = class
return this.mesh.AddVertex (coord);
}
AddVertices (vertices)
{
let indices = [];
for (let i = 0; i < vertices.length; i++) {
let vertex = vertices[i];
indices.push (this.AddVertex (vertex.x, vertex.y, vertex.z));
}
return indices;
}
SetCurve (curve)
{
this.curve = curve;
@ -115,7 +125,7 @@ OV.GeneratorHelper = class
this.generator = generator;
}
GenerateExtrude (vertices, height, smooth)
GenerateExtrude (vertices, height, curve)
{
let topPolygon = [];
let bottomPolygon = [];
@ -124,12 +134,9 @@ OV.GeneratorHelper = class
bottomPolygon.push (this.generator.AddVertex (vertex.x, vertex.y, 0.0));
topPolygon.push (this.generator.AddVertex (vertex.x, vertex.y, height));
}
if (smooth) {
this.generator.SetCurve (1);
}
this.GenerateSurfaceBetweenPolygons (bottomPolygon, topPolygon, smooth);
this.generator.SetCurve (curve);
this.GenerateSurfaceBetweenPolygons (bottomPolygon, topPolygon);
this.generator.ResetCurve ();
this.generator.AddConvexPolygonInverted (bottomPolygon);
this.generator.AddConvexPolygon (topPolygon);
}
@ -151,6 +158,20 @@ OV.GeneratorHelper = class
]);
}
}
GenerateTriangleFan (startIndices, endIndex)
{
const vertexCount = startIndices.length;
for (let i = 0; i < vertexCount; i++) {
const index = i;
const nextIndex = (i < vertexCount - 1) ? index + 1 : 0;
this.generator.AddTriangle (
endIndex,
startIndices[index],
startIndices[nextIndex]
);
}
}
};
OV.GenerateCuboid = function (genParams, xSize, ySize, zSize)
@ -163,7 +184,7 @@ OV.GenerateCuboid = function (genParams, xSize, ySize, zSize)
new OV.Coord2D (0.0, ySize),
];
let helper = new OV.GeneratorHelper (generator);
helper.GenerateExtrude (vertices, zSize, false);
helper.GenerateExtrude (vertices, zSize, null);
return generator.GetMesh ();
};
@ -177,6 +198,10 @@ OV.GenerateCylinder = function (genParams, radius, height, segments, smooth)
);
}
if (segments < 3) {
return null;
}
let generator = new OV.Generator (genParams);
let baseVertices = [];
const step = 2.0 * Math.PI / segments;
@ -185,6 +210,54 @@ OV.GenerateCylinder = function (genParams, radius, height, segments, smooth)
baseVertices.push (cylindrical);
}
let helper = new OV.GeneratorHelper (generator);
helper.GenerateExtrude (baseVertices, height, smooth);
helper.GenerateExtrude (baseVertices, height, smooth ? 1 : null);
return generator.GetMesh ();
};
OV.GenerateSphere = function (genParams, radius, segments, smooth)
{
function GetSphericalCoord (radius, theta, phi)
{
return new OV.Coord3D (
radius * Math.sin (theta) * Math.cos (phi),
radius * Math.sin (theta) * Math.sin (phi),
radius * Math.cos (theta)
);
}
if (segments < 3) {
return null;
}
let generator = new OV.Generator (genParams);
let helper = new OV.GeneratorHelper (generator);
generator.SetCurve (smooth ? 1 : null);
let allLevelVertices = [];
let levels = segments + 1;
const levelStep = Math.PI / segments;
const cylindricalStep = 2.0 * Math.PI / segments;
for (let levelIndex = 1; levelIndex < levels - 1; levelIndex++) {
let levelVertices = [];
let theta = levelIndex * levelStep;
for (let cylindricalIndex = 0; cylindricalIndex < segments; cylindricalIndex++) {
let phi = cylindricalIndex * cylindricalStep;
let vertex = GetSphericalCoord (radius, theta, -phi);
levelVertices.push (generator.AddVertex (vertex.x, vertex.y, vertex.z));
}
if (levelIndex > 1) {
helper.GenerateSurfaceBetweenPolygons (allLevelVertices[allLevelVertices.length - 1], levelVertices);
}
allLevelVertices.push (levelVertices);
}
let topVertex = generator.AddVertex (0.0, 0.0, radius);
let bottomVertex = generator.AddVertex (0.0, 0.0, -radius);
helper.GenerateTriangleFan (allLevelVertices[0].slice ().reverse (), topVertex);
helper.GenerateTriangleFan (allLevelVertices[allLevelVertices.length - 1], bottomVertex);
generator.ResetCurve ();
return generator.GetMesh ();
};

View File

@ -1,20 +0,0 @@
{
"materials" : [
{
"name" : "Material",
"color" : [200, 0, 0]
}
],
"meshes" : [
{
"name" : "Cube",
"material" : 0,
"type" : "cuboid",
"parameters" : {
"size_x" : 1.0,
"size_y" : 1.0,
"size_z" : 1.0
}
}
]
}

View File

@ -1,13 +0,0 @@
{
"meshes" : [
{
"type" : "cylinder",
"parameters" : {
"radius" : 0.5,
"height" : 1.0,
"segments" : 20,
"smooth" : false
}
}
]
}

View File

@ -1,12 +0,0 @@
{
"meshes" : [
{
"type" : "cylinder",
"parameters" : {
"radius" : 0.5,
"height" : 1.0,
"segments" : 50
}
}
]
}

View File

@ -0,0 +1,45 @@
{
"meshes" : [
{
"type" : "cylinder",
"parameters" : {
"radius" : 0.5,
"height" : 1.0
}
},
{
"type" : "cylinder",
"parameters" : {
"radius" : 0.8,
"height" : 1.2
},
"transformation" : {
"translation" : [2.0, 0.0, 0.0]
}
},
{
"type" : "cylinder",
"parameters" : {
"radius" : 0.5,
"height" : 1.0,
"smooth" : false,
"segments" : 5
},
"transformation" : {
"translation" : [2.0, 2.0, 0.0]
}
},
{
"type" : "cylinder",
"parameters" : {
"radius" : 0.5,
"height" : 1.0,
"smooth" : false,
"segments" : 10
},
"transformation" : {
"translation" : [0.0, 2.0, 0.0]
}
}
]
}

View File

@ -0,0 +1,10 @@
{
"meshes" : [
{
"type" : "sphere",
"parameters" : {
"radius" : 0.5
}
}
]
}

View File

@ -0,0 +1,41 @@
{
"meshes" : [
{
"type" : "sphere",
"parameters" : {
"radius" : 0.5
}
},
{
"type" : "sphere",
"parameters" : {
"radius" : 0.8
},
"transformation" : {
"translation" : [2.0, 0.0, 0.0]
}
},
{
"type" : "sphere",
"parameters" : {
"radius" : 0.5,
"smooth" : false,
"segments" : 5
},
"transformation" : {
"translation" : [2.0, 2.0, 0.0]
}
},
{
"type" : "sphere",
"parameters" : {
"radius" : 0.5,
"smooth" : false,
"segments" : 10
},
"transformation" : {
"translation" : [0.0, 2.0, 0.0]
}
}
]
}

View File

@ -29,8 +29,14 @@ describe ('Generator', function () {
});
it ('Cylinder with Default Parameters', function () {
const cylinder = OV.GenerateCylinder (null, 0.5, 1.0, 10, false);
const cylinder = OV.GenerateCylinder (null, 0.5, 1.0, 25, false);
assert (OV.IsSolid (cylinder));
assert (OV.IsEqualEps (OV.CalculateVolume (cylinder), Math.PI * 0.5 * 0.5 * 1.0, 0.1));
});
});
it ('Sphere with Default Parameters', function () {
const cylinder = OV.GenerateSphere (null, 0.5, 20, false);
assert (OV.IsSolid (cylinder));
assert (OV.IsEqualEps (OV.CalculateVolume (cylinder), Math.PI * 0.5 * 0.5 * 0.5 * 4.0 / 3.0, 0.1));
});
});

View File

@ -29,34 +29,8 @@ describe ('O3dv Importer', function () {
});
});
it ('cube_with_material.o3dv', function (done) {
testFiles.ImportO3dvFile ('cube_with_material.o3dv', function (model) {
assert (OV.CheckModel (model));
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
name : '',
materials : [
{ name : 'Material' }
],
meshes : [
{
name : 'Cube',
vertexCount : 8,
normalCount : 12,
uvCount : 0,
triangleCount : 12,
boundingBox : {
min : [0, 0, 0],
max : [1, 1, 1]
}
}
]
});
done ();
});
});
it ('cube_transformation.o3dv', function (done) {
testFiles.ImportO3dvFile ('cube_transformation.o3dv', function (model) {
it ('transformation.o3dv', function (done) {
testFiles.ImportO3dvFile ('transformation.o3dv', function (model) {
assert (OV.CheckModel (model));
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
name : '',
@ -141,31 +115,5 @@ describe ('O3dv Importer', function () {
});
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 : '',
materials : [
{ name : '' }
],
meshes : [
{
name : '',
vertexCount : 40,
normalCount : 76,
uvCount : 0,
triangleCount : 76,
boundingBox : {
min : [-0.5, -0.5, 0],
max : [0.5, 0.5, 1]
}
}
]
});
done ();
});
});
});
});