Merge branch 'dev'
This commit is contained in:
commit
92b993f5f4
@ -21,6 +21,7 @@
|
||||
"globals" : {
|
||||
"OV" : true,
|
||||
"THREE" : false,
|
||||
"rhino3dm" : false,
|
||||
"TextEncoder" : false,
|
||||
"TextDecoder" : false,
|
||||
"XMLHttpRequest" : false,
|
||||
|
||||
34
README.md
34
README.md
@ -23,6 +23,7 @@ The repository is separated into two parts. See more information in the [Develop
|
||||
- stl (text and binary)
|
||||
- ply (text and binary)
|
||||
- gltf (text and binary)
|
||||
- 3dm (experimental)
|
||||
- off (text only)
|
||||
|
||||
### Export
|
||||
@ -31,24 +32,29 @@ The repository is separated into two parts. See more information in the [Develop
|
||||
- stl (text and binary)
|
||||
- ply (text and binary)
|
||||
- gltf (text and binary)
|
||||
- 3dm (experimental)
|
||||
- off (text only)
|
||||
|
||||
## Features
|
||||
|
||||
- Load model:
|
||||
- Select files from a file browser dialog
|
||||
- Drag and drop files from your computer
|
||||
- Specify files by web url
|
||||
- Specify files by web url in hash parameters
|
||||
- Select files from a file browser dialog.
|
||||
- Drag and drop files from your computer.
|
||||
- Specify files by web url.
|
||||
- Specify files by web url in hash parameters.
|
||||
- Explore model:
|
||||
- Orbit, pan, zoom
|
||||
- Set up direction
|
||||
- Fit to window
|
||||
- Orbit, pan, zoom.
|
||||
- Set up direction.
|
||||
- Fit to window.
|
||||
- Investigate model:
|
||||
- List used and missing files
|
||||
- List all materials and meshes
|
||||
- Show/hide and zoom to a specific mesh
|
||||
- List materials used by a specific mesh
|
||||
- Show model information (model size, vertex and polygon count)
|
||||
- Export model to various format
|
||||
- Embed viewer in your website
|
||||
- List used and missing files.
|
||||
- List all materials and meshes.
|
||||
- Show/hide and zoom to a specific mesh.
|
||||
- List materials used by a specific mesh.
|
||||
- Show model information (model size, vertex and polygon count).
|
||||
- Export model to various format.
|
||||
- Embed viewer in your website.
|
||||
|
||||
## External Libraries
|
||||
|
||||
Online 3D Viewer uses these wonderful libraries: [jquery](https://github.com/jquery/jquery), [three.js](https://github.com/mrdoob/three.js), [rhino3dm](https://github.com/mcneel/rhino3dm).
|
||||
|
||||
21
libs/rhino3dm.license.txt
Normal file
21
libs/rhino3dm.license.txt
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Robert McNeel & Associates
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
8
libs/rhino3dm.min.js
vendored
Normal file
8
libs/rhino3dm.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
libs/rhino3dm.wasm
Normal file
BIN
libs/rhino3dm.wasm
Normal file
Binary file not shown.
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "online-3d-viewer",
|
||||
"description": "Online 3D Viewer",
|
||||
"version": "0.7.7",
|
||||
"version": "0.7.8",
|
||||
"repository": "github:kovacsv/Online3DViewer",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
|
||||
@ -11,16 +11,32 @@ OV.Exporter = class
|
||||
];
|
||||
}
|
||||
|
||||
Export (model, format, extension)
|
||||
AddExporter (exporter)
|
||||
{
|
||||
let files = [];
|
||||
this.exporters.push (exporter);
|
||||
}
|
||||
|
||||
Export (model, format, extension, callbacks)
|
||||
{
|
||||
let exporter = null;
|
||||
for (let i = 0; i < this.exporters.length; i++) {
|
||||
let exporter = this.exporters[i];
|
||||
if (exporter.CanExport (format, extension)) {
|
||||
exporter.Export (model, format, files);
|
||||
let currentExporter = this.exporters[i];
|
||||
if (currentExporter.CanExport (format, extension)) {
|
||||
exporter = currentExporter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return files;
|
||||
if (exporter === null) {
|
||||
callbacks.onError ();
|
||||
return;
|
||||
}
|
||||
|
||||
exporter.Export (model, format, function (files) {
|
||||
if (files.length === 0) {
|
||||
callbacks.onError ();
|
||||
} else {
|
||||
callbacks.onSuccess (files);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -39,12 +39,15 @@ OV.ExporterBase = class
|
||||
return false;
|
||||
}
|
||||
|
||||
Export (model, format, files)
|
||||
Export (model, format, onFinish)
|
||||
{
|
||||
this.ExportContent (model, format, files);
|
||||
let files = [];
|
||||
this.ExportContent (model, format, files, function () {
|
||||
onFinish (files);
|
||||
});
|
||||
}
|
||||
|
||||
ExportContent (model, format, files)
|
||||
ExportContent (model, format, files, onFinish)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@ -20,13 +20,14 @@ OV.ExporterGltf = class extends OV.ExporterBase
|
||||
return (format === OV.FileFormat.Text && extension === 'gltf') || (format === OV.FileFormat.Binary && extension === 'glb');
|
||||
}
|
||||
|
||||
ExportContent (model, format, files)
|
||||
ExportContent (model, format, files, onFinish)
|
||||
{
|
||||
if (format === OV.FileFormat.Text) {
|
||||
this.ExportAsciiContent (model, files);
|
||||
} else if (format === OV.FileFormat.Binary) {
|
||||
this.ExportBinaryContent (model, files);
|
||||
}
|
||||
onFinish ();
|
||||
}
|
||||
|
||||
ExportAsciiContent (model, files)
|
||||
@ -195,9 +196,8 @@ OV.ExporterGltf = class extends OV.ExporterBase
|
||||
let writer = new OV.BinaryWriter (mainBufferSize, true);
|
||||
for (let meshIndex = 0; meshIndex < meshDataArr.length; meshIndex++) {
|
||||
let meshData = meshDataArr[meshIndex];
|
||||
let primitives = meshData.buffer.primitives;
|
||||
for (let primitiveIndex = 0; primitiveIndex < primitives.length; primitiveIndex++) {
|
||||
let primitive = primitives[primitiveIndex];
|
||||
for (let primitiveIndex = 0; primitiveIndex < meshData.buffer.PrimitiveCount (); primitiveIndex++) {
|
||||
let primitive = meshData.buffer.GetPrimitive (primitiveIndex);
|
||||
let offset = writer.GetPosition ();
|
||||
for (let i = 0; i < primitive.indices.length; i++) {
|
||||
writer.WriteUnsignedInteger32 (primitive.indices[i]);
|
||||
@ -408,6 +408,7 @@ OV.ExporterGltf = class extends OV.ExporterBase
|
||||
roughnessFactor : 1.0
|
||||
},
|
||||
emissiveFactor : ColorToRGB (material.emissive),
|
||||
doubleSided : true,
|
||||
alphaMode : 'OPAQUE'
|
||||
};
|
||||
|
||||
|
||||
@ -1,115 +1,116 @@
|
||||
OV.ExporterObj = class extends OV.ExporterBase
|
||||
{
|
||||
constructor ()
|
||||
{
|
||||
super ();
|
||||
}
|
||||
constructor ()
|
||||
{
|
||||
super ();
|
||||
}
|
||||
|
||||
CanExport (format, extension)
|
||||
{
|
||||
return format === OV.FileFormat.Text && extension === 'obj';
|
||||
}
|
||||
|
||||
ExportContent (model, format, files)
|
||||
{
|
||||
function WriteTexture (mtlWriter, keyword, texture, files)
|
||||
{
|
||||
if (texture === null || !texture.IsValid ()) {
|
||||
return;
|
||||
}
|
||||
let fileName = OV.GetFileName (texture.name);
|
||||
mtlWriter.WriteArrayLine ([keyword, fileName]);
|
||||
ExportContent (model, format, files, onFinish)
|
||||
{
|
||||
function WriteTexture (mtlWriter, keyword, texture, files)
|
||||
{
|
||||
if (texture === null || !texture.IsValid ()) {
|
||||
return;
|
||||
}
|
||||
let fileName = OV.GetFileName (texture.name);
|
||||
mtlWriter.WriteArrayLine ([keyword, fileName]);
|
||||
|
||||
let fileIndex = files.findIndex (function (file) {
|
||||
return file.GetName () === fileName;
|
||||
});
|
||||
if (fileIndex === -1) {
|
||||
let textureFile = new OV.ExportedFile (fileName);
|
||||
textureFile.SetContent (texture.buffer);
|
||||
files.push (textureFile);
|
||||
}
|
||||
}
|
||||
let fileIndex = files.findIndex (function (file) {
|
||||
return file.GetName () === fileName;
|
||||
});
|
||||
if (fileIndex === -1) {
|
||||
let textureFile = new OV.ExportedFile (fileName);
|
||||
textureFile.SetContent (texture.buffer);
|
||||
files.push (textureFile);
|
||||
}
|
||||
}
|
||||
|
||||
let mtlFile = new OV.ExportedFile ('model.mtl');
|
||||
let objFile = new OV.ExportedFile ('model.obj');
|
||||
let mtlFile = new OV.ExportedFile ('model.mtl');
|
||||
let objFile = new OV.ExportedFile ('model.obj');
|
||||
|
||||
files.push (mtlFile);
|
||||
files.push (objFile);
|
||||
files.push (mtlFile);
|
||||
files.push (objFile);
|
||||
|
||||
let mtlWriter = new OV.TextWriter ();
|
||||
mtlWriter.WriteLine (this.GetHeaderText ());
|
||||
for (let materialIndex = 0; materialIndex < model.MaterialCount (); materialIndex++) {
|
||||
let material = model.GetMaterial (materialIndex);
|
||||
mtlWriter.WriteArrayLine (['newmtl', this.GetExportedMaterialName (material.name)]);
|
||||
mtlWriter.WriteArrayLine (['Ka', material.ambient.r / 255.0, material.ambient.g / 255.0, material.ambient.b / 255.0]);
|
||||
mtlWriter.WriteArrayLine (['Kd', material.diffuse.r / 255.0, material.diffuse.g / 255.0, material.diffuse.b / 255.0]);
|
||||
mtlWriter.WriteArrayLine (['Ks', material.specular.r / 255.0, material.specular.g / 255.0, material.specular.b / 255.0]);
|
||||
mtlWriter.WriteArrayLine (['Ns', material.shininess * 100.0]);
|
||||
mtlWriter.WriteArrayLine (['d', material.opacity]);
|
||||
WriteTexture (mtlWriter, 'map_Kd', material.diffuseMap, files);
|
||||
WriteTexture (mtlWriter, 'map_Ks', material.specularMap, files);
|
||||
WriteTexture (mtlWriter, 'bump', material.bumpMap, files);
|
||||
}
|
||||
mtlFile.SetContent (mtlWriter.GetText ());
|
||||
let mtlWriter = new OV.TextWriter ();
|
||||
mtlWriter.WriteLine (this.GetHeaderText ());
|
||||
for (let materialIndex = 0; materialIndex < model.MaterialCount (); materialIndex++) {
|
||||
let material = model.GetMaterial (materialIndex);
|
||||
mtlWriter.WriteArrayLine (['newmtl', this.GetExportedMaterialName (material.name)]);
|
||||
mtlWriter.WriteArrayLine (['Ka', material.ambient.r / 255.0, material.ambient.g / 255.0, material.ambient.b / 255.0]);
|
||||
mtlWriter.WriteArrayLine (['Kd', material.diffuse.r / 255.0, material.diffuse.g / 255.0, material.diffuse.b / 255.0]);
|
||||
mtlWriter.WriteArrayLine (['Ks', material.specular.r / 255.0, material.specular.g / 255.0, material.specular.b / 255.0]);
|
||||
mtlWriter.WriteArrayLine (['Ns', material.shininess * 1000.0]);
|
||||
mtlWriter.WriteArrayLine (['d', material.opacity]);
|
||||
WriteTexture (mtlWriter, 'map_Kd', material.diffuseMap, files);
|
||||
WriteTexture (mtlWriter, 'map_Ks', material.specularMap, files);
|
||||
WriteTexture (mtlWriter, 'bump', material.bumpMap, files);
|
||||
}
|
||||
mtlFile.SetContent (mtlWriter.GetText ());
|
||||
|
||||
let objWriter = new OV.TextWriter ();
|
||||
objWriter.WriteLine (this.GetHeaderText ());
|
||||
objWriter.WriteArrayLine (['mtllib', mtlFile.GetName ()]);
|
||||
let vertexOffset = 0;
|
||||
let normalOffset = 0;
|
||||
let uvOffset = 0;
|
||||
let usedMaterialName = null;
|
||||
for (let meshIndex = 0; meshIndex < model.MeshCount (); meshIndex++) {
|
||||
let mesh = model.GetMesh (meshIndex);
|
||||
objWriter.WriteArrayLine (['g', this.GetExportedMeshName (mesh.GetName ())]);
|
||||
for (let vertexIndex = 0; vertexIndex < mesh.VertexCount (); vertexIndex++) {
|
||||
let vertex = mesh.GetVertex (vertexIndex);
|
||||
objWriter.WriteArrayLine (['v', vertex.x, vertex.y, vertex.z]);
|
||||
}
|
||||
for (let normalIndex = 0; normalIndex < mesh.NormalCount (); normalIndex++) {
|
||||
let normal = mesh.GetNormal (normalIndex);
|
||||
objWriter.WriteArrayLine (['vn', normal.x, normal.y, normal.z]);
|
||||
}
|
||||
for (let textureUVIndex = 0; textureUVIndex < mesh.TextureUVCount (); textureUVIndex++) {
|
||||
let uv = mesh.GetTextureUV (textureUVIndex);
|
||||
objWriter.WriteArrayLine (['vt', uv.x, uv.y]);
|
||||
}
|
||||
for (let triangleIndex = 0; triangleIndex < mesh.TriangleCount (); triangleIndex++) {
|
||||
let triangle = mesh.GetTriangle (triangleIndex);
|
||||
let v0 = triangle.v0 + vertexOffset + 1;
|
||||
let v1 = triangle.v1 + vertexOffset + 1;
|
||||
let v2 = triangle.v2 + vertexOffset + 1;
|
||||
let n0 = triangle.n0 + normalOffset + 1;
|
||||
let n1 = triangle.n1 + normalOffset + 1;
|
||||
let n2 = triangle.n2 + normalOffset + 1;
|
||||
if (triangle.mat !== null) {
|
||||
let material = model.GetMaterial (triangle.mat);
|
||||
let materialName = this.GetExportedMaterialName (material.name);
|
||||
if (materialName !== usedMaterialName) {
|
||||
objWriter.WriteArrayLine (['usemtl', materialName]);
|
||||
usedMaterialName = materialName;
|
||||
}
|
||||
}
|
||||
let u0 = '';
|
||||
let u1 = '';
|
||||
let u2 = '';
|
||||
if (triangle.HasTextureUVs ()) {
|
||||
u0 = triangle.u0 + uvOffset + 1;
|
||||
u1 = triangle.u1 + uvOffset + 1;
|
||||
u2 = triangle.u2 + uvOffset + 1;
|
||||
}
|
||||
objWriter.WriteArrayLine (['f', [v0, u0, n0].join ('/'), [v1, u1, n1].join ('/'), [v2, u2, n2].join ('/')]);
|
||||
}
|
||||
vertexOffset += mesh.VertexCount ();
|
||||
normalOffset += mesh.NormalCount ();
|
||||
uvOffset += mesh.TextureUVCount ();
|
||||
}
|
||||
let objWriter = new OV.TextWriter ();
|
||||
objWriter.WriteLine (this.GetHeaderText ());
|
||||
objWriter.WriteArrayLine (['mtllib', mtlFile.GetName ()]);
|
||||
let vertexOffset = 0;
|
||||
let normalOffset = 0;
|
||||
let uvOffset = 0;
|
||||
let usedMaterialName = null;
|
||||
for (let meshIndex = 0; meshIndex < model.MeshCount (); meshIndex++) {
|
||||
let mesh = model.GetMesh (meshIndex);
|
||||
objWriter.WriteArrayLine (['g', this.GetExportedMeshName (mesh.GetName ())]);
|
||||
for (let vertexIndex = 0; vertexIndex < mesh.VertexCount (); vertexIndex++) {
|
||||
let vertex = mesh.GetVertex (vertexIndex);
|
||||
objWriter.WriteArrayLine (['v', vertex.x, vertex.y, vertex.z]);
|
||||
}
|
||||
for (let normalIndex = 0; normalIndex < mesh.NormalCount (); normalIndex++) {
|
||||
let normal = mesh.GetNormal (normalIndex);
|
||||
objWriter.WriteArrayLine (['vn', normal.x, normal.y, normal.z]);
|
||||
}
|
||||
for (let textureUVIndex = 0; textureUVIndex < mesh.TextureUVCount (); textureUVIndex++) {
|
||||
let uv = mesh.GetTextureUV (textureUVIndex);
|
||||
objWriter.WriteArrayLine (['vt', uv.x, uv.y]);
|
||||
}
|
||||
for (let triangleIndex = 0; triangleIndex < mesh.TriangleCount (); triangleIndex++) {
|
||||
let triangle = mesh.GetTriangle (triangleIndex);
|
||||
let v0 = triangle.v0 + vertexOffset + 1;
|
||||
let v1 = triangle.v1 + vertexOffset + 1;
|
||||
let v2 = triangle.v2 + vertexOffset + 1;
|
||||
let n0 = triangle.n0 + normalOffset + 1;
|
||||
let n1 = triangle.n1 + normalOffset + 1;
|
||||
let n2 = triangle.n2 + normalOffset + 1;
|
||||
if (triangle.mat !== null) {
|
||||
let material = model.GetMaterial (triangle.mat);
|
||||
let materialName = this.GetExportedMaterialName (material.name);
|
||||
if (materialName !== usedMaterialName) {
|
||||
objWriter.WriteArrayLine (['usemtl', materialName]);
|
||||
usedMaterialName = materialName;
|
||||
}
|
||||
}
|
||||
let u0 = '';
|
||||
let u1 = '';
|
||||
let u2 = '';
|
||||
if (triangle.HasTextureUVs ()) {
|
||||
u0 = triangle.u0 + uvOffset + 1;
|
||||
u1 = triangle.u1 + uvOffset + 1;
|
||||
u2 = triangle.u2 + uvOffset + 1;
|
||||
}
|
||||
objWriter.WriteArrayLine (['f', [v0, u0, n0].join ('/'), [v1, u1, n1].join ('/'), [v2, u2, n2].join ('/')]);
|
||||
}
|
||||
vertexOffset += mesh.VertexCount ();
|
||||
normalOffset += mesh.NormalCount ();
|
||||
uvOffset += mesh.TextureUVCount ();
|
||||
}
|
||||
|
||||
objFile.SetContent (objWriter.GetText ());
|
||||
}
|
||||
objFile.SetContent (objWriter.GetText ());
|
||||
onFinish ();
|
||||
}
|
||||
|
||||
GetHeaderText ()
|
||||
{
|
||||
return '# exported by https://3dviewer.net';
|
||||
}
|
||||
GetHeaderText ()
|
||||
{
|
||||
return '# exported by https://3dviewer.net';
|
||||
}
|
||||
};
|
||||
|
||||
@ -10,7 +10,7 @@ OV.ExporterOff = class extends OV.ExporterBase
|
||||
return format === OV.FileFormat.Text && extension === 'off';
|
||||
}
|
||||
|
||||
ExportContent (model, format, files)
|
||||
ExportContent (model, format, files, onFinish)
|
||||
{
|
||||
let offFile = new OV.ExportedFile ('model.off');
|
||||
files.push (offFile);
|
||||
@ -29,5 +29,6 @@ OV.ExporterOff = class extends OV.ExporterBase
|
||||
});
|
||||
|
||||
offFile.SetContent (offWriter.GetText ());
|
||||
onFinish ();
|
||||
}
|
||||
};
|
||||
|
||||
@ -10,13 +10,14 @@ OV.ExporterPly = class extends OV.ExporterBase
|
||||
return (format === OV.FileFormat.Text || format === OV.FileFormat.Binary) && extension === 'ply';
|
||||
}
|
||||
|
||||
ExportContent (model, format, files)
|
||||
ExportContent (model, format, files, onFinish)
|
||||
{
|
||||
if (format === OV.FileFormat.Text) {
|
||||
this.ExportText (model, files);
|
||||
} else {
|
||||
this.ExportBinary (model, files);
|
||||
}
|
||||
onFinish ();
|
||||
}
|
||||
|
||||
ExportText (model, files)
|
||||
|
||||
@ -10,13 +10,14 @@ OV.ExporterStl = class extends OV.ExporterBase
|
||||
return (format === OV.FileFormat.Text || format === OV.FileFormat.Binary) && extension === 'stl';
|
||||
}
|
||||
|
||||
ExportContent (model, format, files)
|
||||
ExportContent (model, format, files, onFinish)
|
||||
{
|
||||
if (format === OV.FileFormat.Text) {
|
||||
this.ExportText (model, files);
|
||||
} else {
|
||||
this.ExportBinary (model, files);
|
||||
}
|
||||
onFinish ();
|
||||
}
|
||||
|
||||
ExportText (model, files)
|
||||
|
||||
96
source/external/rhino.exporter.js
vendored
Normal file
96
source/external/rhino.exporter.js
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
OV.Exporter3dm = class extends OV.ExporterBase
|
||||
{
|
||||
constructor ()
|
||||
{
|
||||
super ();
|
||||
this.rhino = null;
|
||||
}
|
||||
|
||||
CanExport (format, extension)
|
||||
{
|
||||
return format === OV.FileFormat.Binary && extension === '3dm';
|
||||
}
|
||||
|
||||
ExportContent (model, format, files, onFinish)
|
||||
{
|
||||
if (this.rhino === null) {
|
||||
let obj = this;
|
||||
rhino3dm ().then (function (rhino) {
|
||||
obj.rhino = rhino;
|
||||
obj.ExportRhinoContent (model, files, onFinish);
|
||||
});
|
||||
} else {
|
||||
this.ExportRhinoContent (model, files, onFinish);
|
||||
}
|
||||
}
|
||||
|
||||
ExportRhinoContent (model, files, onFinish)
|
||||
{
|
||||
function ColorToRhinoColor (color)
|
||||
{
|
||||
return {
|
||||
r : color.r,
|
||||
g : color.g,
|
||||
b : color.b,
|
||||
a : 255
|
||||
};
|
||||
}
|
||||
|
||||
let rhinoFile = new OV.ExportedFile ('model.3dm');
|
||||
files.push (rhinoFile);
|
||||
|
||||
let rhinoDoc = new this.rhino.File3dm ();
|
||||
for (let meshIndex = 0; meshIndex < model.MeshCount (); meshIndex++) {
|
||||
let mesh = model.GetMesh (meshIndex);
|
||||
let meshBuffer = OV.ConvertMeshToMeshBuffer (mesh);
|
||||
for (let primitiveIndex = 0; primitiveIndex < meshBuffer.PrimitiveCount (); primitiveIndex++) {
|
||||
let primitive = meshBuffer.GetPrimitive (primitiveIndex);
|
||||
let threeJson = {
|
||||
data : {
|
||||
attributes : {
|
||||
position : {
|
||||
itemSize : 3,
|
||||
type : 'Float32Array',
|
||||
array : primitive.vertices
|
||||
},
|
||||
normal : {
|
||||
itemSize : 3,
|
||||
type : 'Float32Array',
|
||||
array : primitive.normals
|
||||
}
|
||||
},
|
||||
index : {
|
||||
type : 'Uint16Array',
|
||||
array : primitive.indices
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let material = model.GetMaterial (primitive.material);
|
||||
let rhinoMaterial = new this.rhino.Material ();
|
||||
rhinoMaterial.name = this.GetExportedMaterialName (material.name);
|
||||
rhinoMaterial.ambientColor = ColorToRhinoColor (material.ambient);
|
||||
rhinoMaterial.diffuseColor = ColorToRhinoColor (material.diffuse);
|
||||
rhinoMaterial.specularColor = ColorToRhinoColor (material.specular);
|
||||
rhinoMaterial.transparency = 1.0 - material.opacity;
|
||||
|
||||
let rhinoMaterialIndex = rhinoDoc.materials ().count ();
|
||||
rhinoDoc.materials ().add (rhinoMaterial);
|
||||
|
||||
let rhinoMesh = new this.rhino.Mesh.createFromThreejsJSON (threeJson);
|
||||
let rhinoAttributes = new this.rhino.ObjectAttributes ();
|
||||
rhinoAttributes.name = this.GetExportedMeshName (mesh.GetName ());
|
||||
rhinoAttributes.materialSource = this.rhino.ObjectMaterialSource.MaterialFromObject;
|
||||
rhinoAttributes.materialIndex = rhinoMaterialIndex;
|
||||
rhinoDoc.objects ().add (rhinoMesh, rhinoAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
let writeOptions = new this.rhino.File3dmWriteOptions ();
|
||||
writeOptions.version = 6;
|
||||
let rhinoDocBuffer = rhinoDoc.toByteArray (writeOptions);
|
||||
|
||||
rhinoFile.SetContent (rhinoDocBuffer);
|
||||
onFinish ();
|
||||
}
|
||||
};
|
||||
323
source/external/rhino.importer.js
vendored
Normal file
323
source/external/rhino.importer.js
vendored
Normal file
@ -0,0 +1,323 @@
|
||||
OV.Importer3dm = class extends OV.ImporterBase
|
||||
{
|
||||
constructor ()
|
||||
{
|
||||
super ();
|
||||
this.rhino = null;
|
||||
}
|
||||
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return extension === '3dm';
|
||||
}
|
||||
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {
|
||||
'3dm' : OV.FileFormat.Binary
|
||||
};
|
||||
}
|
||||
|
||||
GetUpDirection ()
|
||||
{
|
||||
return OV.Direction.Z;
|
||||
}
|
||||
|
||||
ClearContent ()
|
||||
{
|
||||
this.instanceObjects = null;
|
||||
this.instanceDefinitions = null;
|
||||
}
|
||||
|
||||
ResetContent ()
|
||||
{
|
||||
this.instanceObjects = {};
|
||||
this.instanceDefinitions = {};
|
||||
}
|
||||
|
||||
ImportContent (fileContent, onFinish)
|
||||
{
|
||||
if (this.rhino === null) {
|
||||
let obj = this;
|
||||
rhino3dm ().then (function (rhino) {
|
||||
obj.rhino = rhino;
|
||||
obj.ImportRhinoContent (fileContent);
|
||||
onFinish ();
|
||||
});
|
||||
} else {
|
||||
this.ImportRhinoContent (fileContent);
|
||||
onFinish ();
|
||||
}
|
||||
}
|
||||
|
||||
ImportRhinoContent (fileContent)
|
||||
{
|
||||
let rhinoDoc = this.rhino.File3dm.fromByteArray (fileContent);
|
||||
if (rhinoDoc === null) {
|
||||
this.SetError ();
|
||||
this.SetMessage ('Failed to read Rhino file.');
|
||||
return;
|
||||
}
|
||||
this.ImportRhinoDocument (rhinoDoc);
|
||||
if (OV.IsModelEmpty (this.model)) {
|
||||
this.SetError ();
|
||||
this.SetMessage ('The model doesn\'t contain any 3D meshes. Try to save the model while you are in shaded view in Rhino.');
|
||||
}
|
||||
}
|
||||
|
||||
ImportRhinoDocument (rhinoDoc)
|
||||
{
|
||||
this.InitRhinoInstances (rhinoDoc);
|
||||
this.ImportRhinoGeometry (rhinoDoc);
|
||||
}
|
||||
|
||||
InitRhinoInstances (rhinoDoc)
|
||||
{
|
||||
let rhinoObjects = rhinoDoc.objects ();
|
||||
for (let i = 0; i < rhinoObjects.count; i++) {
|
||||
let rhinoObject = rhinoObjects.get (i);
|
||||
let rhinoAttributes = rhinoObject.attributes ();
|
||||
if (rhinoAttributes.isInstanceDefinitionObject) {
|
||||
this.instanceObjects[rhinoAttributes.id] = rhinoObject;
|
||||
}
|
||||
}
|
||||
let rhinoInstanceDefinitions = rhinoDoc.instanceDefinitions ();
|
||||
for (let i = 0; i < rhinoInstanceDefinitions.count (); i++) {
|
||||
let rhinoInstanceDefinition = rhinoInstanceDefinitions.get (i);
|
||||
this.instanceDefinitions[rhinoInstanceDefinition.id] = rhinoInstanceDefinition;
|
||||
}
|
||||
}
|
||||
|
||||
ImportRhinoGeometry (rhinoDoc)
|
||||
{
|
||||
let rhinoObjects = rhinoDoc.objects ();
|
||||
for (let i = 0; i < rhinoObjects.count; i++) {
|
||||
let rhinoObject = rhinoObjects.get (i);
|
||||
this.ImportRhinoGeometryObject (rhinoDoc, rhinoObject, []);
|
||||
}
|
||||
}
|
||||
|
||||
ImportRhinoGeometryObject (rhinoDoc, rhinoObject, rhinoInstanceReferences)
|
||||
{
|
||||
let rhinoGeometry = rhinoObject.geometry ();
|
||||
let rhinoAttributes = rhinoObject.attributes ();
|
||||
|
||||
let objectType = rhinoGeometry.objectType;
|
||||
if (rhinoAttributes.isInstanceDefinitionObject && rhinoInstanceReferences.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let rhinoMesh = null;
|
||||
let deleteMesh = false;
|
||||
|
||||
if (objectType === this.rhino.ObjectType.Mesh) {
|
||||
rhinoMesh = rhinoGeometry;
|
||||
deleteMesh = false;
|
||||
} else if (objectType === this.rhino.ObjectType.Extrusion) {
|
||||
rhinoMesh = rhinoGeometry.getMesh (this.rhino.MeshType.Any);
|
||||
deleteMesh = true;
|
||||
} else if (objectType === this.rhino.ObjectType.Brep) {
|
||||
rhinoMesh = new this.rhino.Mesh ();
|
||||
let faces = rhinoGeometry.faces ();
|
||||
for (let i = 0; i < faces.count; i++) {
|
||||
let face = faces.get (i);
|
||||
let mesh = face.getMesh (this.rhino.MeshType.Any);
|
||||
if (mesh) {
|
||||
rhinoMesh.append (mesh);
|
||||
mesh.delete ();
|
||||
}
|
||||
face.delete ();
|
||||
}
|
||||
faces.delete ();
|
||||
rhinoMesh.compact ();
|
||||
deleteMesh = true;
|
||||
} else if (objectType === this.rhino.ObjectType.SubD) {
|
||||
rhinoGeometry.subdivide (3);
|
||||
rhinoMesh = this.rhino.Mesh.createFromSubDControlNet (rhinoGeometry);
|
||||
deleteMesh = true;
|
||||
} else if (objectType === this.rhino.ObjectType.InstanceReference) {
|
||||
let parentDefinitionId = rhinoGeometry.parentIdefId;
|
||||
let instanceDefinition = this.instanceDefinitions[parentDefinitionId];
|
||||
if (instanceDefinition !== undefined) {
|
||||
let instanceObjectIds = instanceDefinition.getObjectIds ();
|
||||
for (let i = 0; i < instanceObjectIds.length; i++) {
|
||||
let instanceObjectId = instanceObjectIds[i];
|
||||
let instanceObject = this.instanceObjects[instanceObjectId];
|
||||
if (instanceObject !== undefined) {
|
||||
rhinoInstanceReferences.push (rhinoObject);
|
||||
this.ImportRhinoGeometryObject (rhinoDoc, instanceObject, rhinoInstanceReferences);
|
||||
rhinoInstanceReferences.pop ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rhinoMesh !== null) {
|
||||
this.ImportRhinoMesh (rhinoDoc, rhinoMesh, rhinoObject, rhinoInstanceReferences);
|
||||
if (deleteMesh) {
|
||||
rhinoMesh.delete ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImportRhinoMesh (rhinoDoc, rhinoMesh, rhinoObject, rhinoInstanceReferences)
|
||||
{
|
||||
let rhinoAttributes = rhinoObject.attributes ();
|
||||
|
||||
let mesh = new OV.Mesh ();
|
||||
mesh.SetName (rhinoAttributes.name);
|
||||
|
||||
let materialIndex = this.GetMaterialIndex (rhinoDoc, rhinoObject, rhinoInstanceReferences);
|
||||
let threeJson = rhinoMesh.toThreejsJSON ();
|
||||
let vertices = threeJson.data.attributes.position.array;
|
||||
for (let i = 0; i < vertices.length; i += 3) {
|
||||
let x = vertices[i];
|
||||
let y = vertices[i + 1];
|
||||
let z = vertices[i + 2];
|
||||
mesh.AddVertex (new OV.Coord3D (x, y, z));
|
||||
}
|
||||
let hasNormals = (threeJson.data.attributes.normal !== undefined);
|
||||
if (hasNormals) {
|
||||
let normals = threeJson.data.attributes.normal.array;
|
||||
for (let i = 0; i < normals.length; i += 3) {
|
||||
let x = normals[i];
|
||||
let y = normals[i + 1];
|
||||
let z = normals[i + 2];
|
||||
mesh.AddNormal (new OV.Coord3D (x, y, z));
|
||||
}
|
||||
}
|
||||
let hasUVs = (threeJson.data.attributes.uv !== undefined);
|
||||
if (hasUVs) {
|
||||
let uvs = threeJson.data.attributes.uv.array;
|
||||
for (let i = 0; i < uvs.length; i += 2) {
|
||||
let x = uvs[i];
|
||||
let y = uvs[i + 1];
|
||||
mesh.AddTextureUV (new OV.Coord2D (x, y));
|
||||
}
|
||||
}
|
||||
let indices = threeJson.data.index.array;
|
||||
for (let i = 0; i < indices.length; i += 3) {
|
||||
let v0 = indices[i];
|
||||
let v1 = indices[i + 1];
|
||||
let v2 = indices[i + 2];
|
||||
let triangle = new OV.Triangle (v0, v1, v2);
|
||||
if (hasNormals) {
|
||||
triangle.SetNormals (v0, v1, v2);
|
||||
}
|
||||
if (hasUVs) {
|
||||
triangle.SetTextureUVs (v0, v1, v2);
|
||||
}
|
||||
if (materialIndex !== null) {
|
||||
triangle.SetMaterial (materialIndex);
|
||||
}
|
||||
mesh.AddTriangle (triangle);
|
||||
}
|
||||
if (rhinoInstanceReferences.length !== 0) {
|
||||
let matrix = new OV.Matrix ().CreateIdentity ();
|
||||
for (let i = rhinoInstanceReferences.length - 1; i >= 0; i--) {
|
||||
let rhinoInstanceReference = rhinoInstanceReferences[i];
|
||||
let rhinoInstanceReferenceGeometry = rhinoInstanceReference.geometry ();
|
||||
let rhinoInstanceReferenceMatrix = rhinoInstanceReferenceGeometry.xform.toFloatArray (false);
|
||||
let transformationMatrix = new OV.Matrix (rhinoInstanceReferenceMatrix);
|
||||
matrix = matrix.MultiplyMatrix (transformationMatrix);
|
||||
}
|
||||
let transformation = new OV.Transformation (matrix);
|
||||
OV.TransformMesh (mesh, transformation);
|
||||
}
|
||||
this.model.AddMesh (mesh);
|
||||
}
|
||||
|
||||
GetMaterialIndex (rhinoDoc, rhinoObject, rhinoInstanceReferences)
|
||||
{
|
||||
function GetRhinoMaterial (rhino, rhinoObject, rhinoInstanceReferences)
|
||||
{
|
||||
let rhinoAttributes = rhinoObject.attributes ();
|
||||
if (rhinoAttributes.materialSource === rhino.ObjectMaterialSource.MaterialFromObject) {
|
||||
let materialIndex = rhinoAttributes.materialIndex;
|
||||
if (materialIndex > -1) {
|
||||
return rhinoDoc.materials ().get (materialIndex);
|
||||
}
|
||||
} else if (rhinoAttributes.materialSource === rhino.ObjectMaterialSource.MaterialFromLayer) {
|
||||
let layerIndex = rhinoAttributes.layerIndex;
|
||||
if (layerIndex > 0) {
|
||||
let layer = rhinoDoc.layers ().get (layerIndex);
|
||||
let layerMaterialIndex = layer.renderMaterialIndex;
|
||||
if (layerMaterialIndex > -1) {
|
||||
return rhinoDoc.materials ().get (layerMaterialIndex);
|
||||
}
|
||||
}
|
||||
} else if (rhinoAttributes.materialSource === rhino.ObjectMaterialSource.MaterialFromParent) {
|
||||
if (rhinoInstanceReferences.length !== 0) {
|
||||
return GetRhinoMaterial (rhino, rhinoInstanceReferences[0], []);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function FindMatchingMaterial (model, rhinoMaterial)
|
||||
{
|
||||
function SetColor (color, rhinoColor)
|
||||
{
|
||||
color.Set (rhinoColor.r, rhinoColor.g, rhinoColor.b);
|
||||
}
|
||||
|
||||
function IsBlack (rhinoColor)
|
||||
{
|
||||
return rhinoColor.r === 0 && rhinoColor.g === 0 && rhinoColor.b === 0;
|
||||
}
|
||||
|
||||
function IsWhite (rhinoColor)
|
||||
{
|
||||
return rhinoColor.r === 255 && rhinoColor.g === 255 && rhinoColor.b === 255;
|
||||
}
|
||||
|
||||
let material = new OV.Material ();
|
||||
if (rhinoMaterial === null) {
|
||||
material.diffuse.Set (255, 255, 255);
|
||||
} else {
|
||||
material.name = rhinoMaterial.name;
|
||||
SetColor (material.ambient, rhinoMaterial.ambientColor);
|
||||
SetColor (material.diffuse, rhinoMaterial.diffuseColor);
|
||||
SetColor (material.specular, rhinoMaterial.specularColor);
|
||||
material.opacity = 1.0 - rhinoMaterial.transparency;
|
||||
material.transparent = OV.IsLower (material.opacity, 1.0);
|
||||
// material.shininess = rhinoMaterial.shine / 255.0;
|
||||
if (IsBlack (material.diffuse) && !IsWhite (rhinoMaterial.reflectionColor)) {
|
||||
SetColor (material.diffuse, rhinoMaterial.reflectionColor);
|
||||
}
|
||||
if (IsBlack (material.diffuse) && !IsWhite (rhinoMaterial.transparentColor)) {
|
||||
SetColor (material.diffuse, rhinoMaterial.transparentColor);
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < model.MaterialCount (); i++) {
|
||||
let current = model.GetMaterial (i);
|
||||
if (current.name !== material.name) {
|
||||
continue;
|
||||
}
|
||||
if (!OV.ColorIsEqual (current.ambient, material.ambient)) {
|
||||
continue;
|
||||
}
|
||||
if (!OV.ColorIsEqual (current.diffuse, material.diffuse)) {
|
||||
continue;
|
||||
}
|
||||
if (!OV.ColorIsEqual (current.specular, material.specular)) {
|
||||
continue;
|
||||
}
|
||||
if (!OV.IsEqual (current.opacity, material.opacity)) {
|
||||
continue;
|
||||
}
|
||||
if (current.transparent !== material.transparent) {
|
||||
continue;
|
||||
}
|
||||
if (!OV.IsEqual (current.shininess, material.shininess)) {
|
||||
continue;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
return model.AddMaterial (material);
|
||||
}
|
||||
|
||||
let rhinoMaterial = GetRhinoMaterial (this.rhino, rhinoObject, rhinoInstanceReferences);
|
||||
return FindMatchingMaterial (this.model, rhinoMaterial);
|
||||
}
|
||||
};
|
||||
2
source/external/three.converter.js
vendored
2
source/external/three.converter.js
vendored
@ -39,7 +39,7 @@ OV.ConvertModelToThreeMeshes = function (model, callbacks)
|
||||
color : diffuseColor,
|
||||
specular : specularColor,
|
||||
emissive : emissiveColor,
|
||||
shininess : material.shininess * 10.0,
|
||||
shininess : material.shininess * 100.0,
|
||||
opacity : material.opacity,
|
||||
transparent : material.transparent,
|
||||
alphaTest : material.alphaTest,
|
||||
|
||||
5
source/external/three.model.loader.js
vendored
5
source/external/three.model.loader.js
vendored
@ -3,6 +3,7 @@ OV.ThreeModelLoader = class
|
||||
constructor ()
|
||||
{
|
||||
this.importer = new OV.Importer ();
|
||||
this.importer.AddImporter (new OV.Importer3dm ());
|
||||
this.callbacks = null;
|
||||
this.inProgress = false;
|
||||
}
|
||||
@ -57,10 +58,10 @@ OV.ThreeModelLoader = class
|
||||
this.callbacks.onImportStart ();
|
||||
OV.RunTaskAsync (function () {
|
||||
obj.importer.Import (settings, {
|
||||
success : function (importResult) {
|
||||
onSuccess : function (importResult) {
|
||||
obj.OnModelImported (importResult);
|
||||
},
|
||||
error : function (importError) {
|
||||
onError : function (importError) {
|
||||
obj.callbacks.onLoadError (importError);
|
||||
obj.inProgress = false;
|
||||
}
|
||||
|
||||
@ -1,218 +1,218 @@
|
||||
OV.File = class
|
||||
{
|
||||
constructor (file, source)
|
||||
{
|
||||
this.source = source;
|
||||
if (source === OV.FileSource.Url) {
|
||||
this.fileUrl = file;
|
||||
this.fileObject = null;
|
||||
this.name = OV.GetFileName (file);
|
||||
this.extension = OV.GetFileExtension (file);
|
||||
} else if (source === OV.FileSource.File) {
|
||||
this.fileUrl = null;
|
||||
this.fileObject = file;
|
||||
this.name = OV.GetFileName (file.name);
|
||||
this.extension = OV.GetFileExtension (file.name);
|
||||
}
|
||||
this.content = null;
|
||||
}
|
||||
constructor (file, source)
|
||||
{
|
||||
this.source = source;
|
||||
if (source === OV.FileSource.Url) {
|
||||
this.fileUrl = file;
|
||||
this.fileObject = null;
|
||||
this.name = OV.GetFileName (file);
|
||||
this.extension = OV.GetFileExtension (file);
|
||||
} else if (source === OV.FileSource.File) {
|
||||
this.fileUrl = null;
|
||||
this.fileObject = file;
|
||||
this.name = OV.GetFileName (file.name);
|
||||
this.extension = OV.GetFileExtension (file.name);
|
||||
}
|
||||
this.content = null;
|
||||
}
|
||||
};
|
||||
|
||||
OV.FileList = class
|
||||
{
|
||||
constructor (importers)
|
||||
{
|
||||
this.files = [];
|
||||
this.importers = importers;
|
||||
}
|
||||
constructor (importers)
|
||||
{
|
||||
this.files = [];
|
||||
this.importers = importers;
|
||||
}
|
||||
|
||||
FillFromFileUrls (fileList)
|
||||
{
|
||||
this.Fill (fileList, OV.FileSource.Url);
|
||||
}
|
||||
FillFromFileUrls (fileList)
|
||||
{
|
||||
this.Fill (fileList, OV.FileSource.Url);
|
||||
}
|
||||
|
||||
FillFromFileObjects (fileList)
|
||||
{
|
||||
this.Fill (fileList, OV.FileSource.File);
|
||||
}
|
||||
FillFromFileObjects (fileList)
|
||||
{
|
||||
this.Fill (fileList, OV.FileSource.File);
|
||||
}
|
||||
|
||||
ExtendFromFileList (files)
|
||||
{
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
let file = files[i];
|
||||
if (!this.ContainsFileByPath (file.name)) {
|
||||
this.files.push (file);
|
||||
}
|
||||
}
|
||||
}
|
||||
ExtendFromFileList (files)
|
||||
{
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
let file = files[i];
|
||||
if (!this.ContainsFileByPath (file.name)) {
|
||||
this.files.push (file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GetFiles ()
|
||||
{
|
||||
return this.files;
|
||||
}
|
||||
GetFiles ()
|
||||
{
|
||||
return this.files;
|
||||
}
|
||||
|
||||
GetContent (onReady)
|
||||
{
|
||||
let obj = this;
|
||||
let taskRunner = new OV.TaskRunner ();
|
||||
taskRunner.Run (this.files.length, {
|
||||
runTask : function (index, complete) {
|
||||
obj.GetFileContent (obj.files[index], complete);
|
||||
},
|
||||
onReady : onReady
|
||||
});
|
||||
}
|
||||
GetContent (onReady)
|
||||
{
|
||||
let obj = this;
|
||||
let taskRunner = new OV.TaskRunner ();
|
||||
taskRunner.Run (this.files.length, {
|
||||
runTask : function (index, complete) {
|
||||
obj.GetFileContent (obj.files[index], complete);
|
||||
},
|
||||
onReady : onReady
|
||||
});
|
||||
}
|
||||
|
||||
ContainsFileByPath (filePath)
|
||||
{
|
||||
return this.FindFileByPath (filePath) !== null;
|
||||
}
|
||||
ContainsFileByPath (filePath)
|
||||
{
|
||||
return this.FindFileByPath (filePath) !== null;
|
||||
}
|
||||
|
||||
FindFileByPath (filePath)
|
||||
{
|
||||
let fileName = OV.GetFileName (filePath).toLowerCase ();
|
||||
for (let fileIndex = 0; fileIndex < this.files.length; fileIndex++) {
|
||||
let file = this.files[fileIndex];
|
||||
if (file.name.toLowerCase () === fileName) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
FindFileByPath (filePath)
|
||||
{
|
||||
let fileName = OV.GetFileName (filePath).toLowerCase ();
|
||||
for (let fileIndex = 0; fileIndex < this.files.length; fileIndex++) {
|
||||
let file = this.files[fileIndex];
|
||||
if (file.name.toLowerCase () === fileName) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
HasMainFile ()
|
||||
{
|
||||
return this.GetMainFile () !== null;
|
||||
}
|
||||
HasMainFile ()
|
||||
{
|
||||
return this.GetMainFile () !== null;
|
||||
}
|
||||
|
||||
GetMainFile ()
|
||||
{
|
||||
for (let fileIndex = 0; fileIndex < this.files.length; fileIndex++) {
|
||||
let file = this.files[fileIndex];
|
||||
let importer = this.FindImporter (file);
|
||||
if (importer !== null) {
|
||||
return {
|
||||
file : file,
|
||||
importer : importer
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
GetMainFile ()
|
||||
{
|
||||
for (let fileIndex = 0; fileIndex < this.files.length; fileIndex++) {
|
||||
let file = this.files[fileIndex];
|
||||
let importer = this.FindImporter (file);
|
||||
if (importer !== null) {
|
||||
return {
|
||||
file : file,
|
||||
importer : importer
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
IsOnlySource (source)
|
||||
{
|
||||
if (this.files.length === 0) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < this.files.length; i++) {
|
||||
let file = this.files[i];
|
||||
if (file.source !== source) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
IsOnlySource (source)
|
||||
{
|
||||
if (this.files.length === 0) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < this.files.length; i++) {
|
||||
let file = this.files[i];
|
||||
if (file.source !== source) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Fill (fileList, fileSource)
|
||||
{
|
||||
this.files = [];
|
||||
for (let fileIndex = 0; fileIndex < fileList.length; fileIndex++) {
|
||||
let fileObject = fileList[fileIndex];
|
||||
let file = new OV.File (fileObject, fileSource);
|
||||
this.AddFile (file);
|
||||
}
|
||||
}
|
||||
Fill (fileList, fileSource)
|
||||
{
|
||||
this.files = [];
|
||||
for (let fileIndex = 0; fileIndex < fileList.length; fileIndex++) {
|
||||
let fileObject = fileList[fileIndex];
|
||||
let file = new OV.File (fileObject, fileSource);
|
||||
this.AddFile (file);
|
||||
}
|
||||
}
|
||||
|
||||
AddFile (file)
|
||||
{
|
||||
this.files.push (file);
|
||||
}
|
||||
|
||||
GetFileContent (file, complete)
|
||||
{
|
||||
let callbacks = {
|
||||
success : function (content) {
|
||||
file.content = content;
|
||||
},
|
||||
error : function () {
|
||||
|
||||
},
|
||||
complete : function () {
|
||||
complete ();
|
||||
}
|
||||
};
|
||||
if (file.content !== null) {
|
||||
complete ();
|
||||
return;
|
||||
}
|
||||
let format = this.GetFileFormat (file);
|
||||
if (file.source === OV.FileSource.Url) {
|
||||
OV.RequestUrl (file.fileUrl, format, callbacks);
|
||||
} else if (file.source === OV.FileSource.File) {
|
||||
OV.ReadFile (file.fileObject, format, callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
GetFileFormat (file)
|
||||
{
|
||||
for (let importerIndex = 0; importerIndex < this.importers.length; importerIndex++) {
|
||||
let importer = this.importers[importerIndex];
|
||||
let extension = file.extension.toLowerCase ();
|
||||
let knownFormats = importer.GetKnownFileFormats ();
|
||||
if (knownFormats[extension] !== undefined) {
|
||||
return knownFormats[extension];
|
||||
}
|
||||
}
|
||||
return OV.FileFormat.Binary;
|
||||
}
|
||||
AddFile (file)
|
||||
{
|
||||
this.files.push (file);
|
||||
}
|
||||
|
||||
GetFileContent (file, complete)
|
||||
{
|
||||
let callbacks = {
|
||||
success : function (content) {
|
||||
file.content = content;
|
||||
},
|
||||
error : function () {
|
||||
|
||||
},
|
||||
complete : function () {
|
||||
complete ();
|
||||
}
|
||||
};
|
||||
if (file.content !== null) {
|
||||
complete ();
|
||||
return;
|
||||
}
|
||||
let format = this.GetFileFormat (file);
|
||||
if (file.source === OV.FileSource.Url) {
|
||||
OV.RequestUrl (file.fileUrl, format, callbacks);
|
||||
} else if (file.source === OV.FileSource.File) {
|
||||
OV.ReadFile (file.fileObject, format, callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
GetFileFormat (file)
|
||||
{
|
||||
for (let importerIndex = 0; importerIndex < this.importers.length; importerIndex++) {
|
||||
let importer = this.importers[importerIndex];
|
||||
let extension = file.extension.toLowerCase ();
|
||||
let knownFormats = importer.GetKnownFileFormats ();
|
||||
if (knownFormats[extension] !== undefined) {
|
||||
return knownFormats[extension];
|
||||
}
|
||||
}
|
||||
return OV.FileFormat.Binary;
|
||||
}
|
||||
|
||||
FindImporter (file)
|
||||
{
|
||||
for (let importerIndex = 0; importerIndex < this.importers.length; importerIndex++) {
|
||||
let importer = this.importers[importerIndex];
|
||||
if (importer.CanImportExtension (file.extension.toLowerCase ())) {
|
||||
return importer;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
FindImporter (file)
|
||||
{
|
||||
for (let importerIndex = 0; importerIndex < this.importers.length; importerIndex++) {
|
||||
let importer = this.importers[importerIndex];
|
||||
if (importer.CanImportExtension (file.extension.toLowerCase ())) {
|
||||
return importer;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
OV.ImportSettings = class
|
||||
{
|
||||
constructor ()
|
||||
{
|
||||
this.defaultColor = new OV.Color (200, 200, 200);
|
||||
}
|
||||
constructor ()
|
||||
{
|
||||
this.defaultColor = new OV.Color (200, 200, 200);
|
||||
}
|
||||
};
|
||||
|
||||
OV.ImportErrorCode =
|
||||
{
|
||||
NoImportableFile : 1,
|
||||
ImportFailed : 2,
|
||||
UnknownError : 3
|
||||
NoImportableFile : 1,
|
||||
ImportFailed : 2,
|
||||
UnknownError : 3
|
||||
};
|
||||
|
||||
OV.ImportError = class
|
||||
{
|
||||
constructor (code, message)
|
||||
{
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
constructor (code, message)
|
||||
{
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
};
|
||||
|
||||
OV.ImportResult = class
|
||||
{
|
||||
constructor ()
|
||||
{
|
||||
this.model = null;
|
||||
this.mainFile = null;
|
||||
this.upVector = null;
|
||||
this.usedFiles = null;
|
||||
this.missingFiles = null;
|
||||
}
|
||||
constructor ()
|
||||
{
|
||||
this.model = null;
|
||||
this.mainFile = null;
|
||||
this.upVector = null;
|
||||
this.usedFiles = null;
|
||||
this.missingFiles = null;
|
||||
}
|
||||
};
|
||||
|
||||
OV.ImportBuffers = class
|
||||
@ -257,151 +257,157 @@ OV.ImportBuffers = class
|
||||
|
||||
OV.Importer = class
|
||||
{
|
||||
constructor ()
|
||||
constructor ()
|
||||
{
|
||||
this.importers = [
|
||||
new OV.ImporterObj (),
|
||||
new OV.ImporterStl (),
|
||||
new OV.ImporterOff (),
|
||||
new OV.ImporterPly (),
|
||||
new OV.Importer3ds (),
|
||||
new OV.ImporterGltf ()
|
||||
];
|
||||
this.fileList = new OV.FileList (this.importers);
|
||||
this.model = null;
|
||||
this.usedFiles = [];
|
||||
this.missingFiles = [];
|
||||
}
|
||||
|
||||
AddImporter (importer)
|
||||
{
|
||||
this.importers = [
|
||||
new OV.ImporterObj (),
|
||||
new OV.ImporterStl (),
|
||||
new OV.ImporterOff (),
|
||||
new OV.ImporterPly (),
|
||||
new OV.Importer3ds (),
|
||||
new OV.ImporterGltf ()
|
||||
];
|
||||
this.fileList = new OV.FileList (this.importers);
|
||||
this.model = null;
|
||||
this.usedFiles = [];
|
||||
this.missingFiles = [];
|
||||
}
|
||||
|
||||
LoadFilesFromUrls (fileList, onReady)
|
||||
{
|
||||
this.LoadFiles (fileList, OV.FileSource.Url, onReady);
|
||||
this.importers.push (importer);
|
||||
}
|
||||
|
||||
LoadFilesFromFileObjects (fileList, onReady)
|
||||
{
|
||||
this.LoadFiles (fileList, OV.FileSource.File, onReady);
|
||||
}
|
||||
LoadFilesFromUrls (fileList, onReady)
|
||||
{
|
||||
this.LoadFiles (fileList, OV.FileSource.Url, onReady);
|
||||
}
|
||||
|
||||
Import (settings, callbacks)
|
||||
{
|
||||
let mainFile = this.fileList.GetMainFile ();
|
||||
if (mainFile === null || mainFile.file === null || mainFile.file.content === null) {
|
||||
callbacks.error (new OV.ImportError (OV.ImportErrorCode.NoImportableFile, null));
|
||||
return;
|
||||
}
|
||||
LoadFilesFromFileObjects (fileList, onReady)
|
||||
{
|
||||
this.LoadFiles (fileList, OV.FileSource.File, onReady);
|
||||
}
|
||||
|
||||
this.RevokeModelUrls ();
|
||||
this.model = null;
|
||||
this.usedFiles = [];
|
||||
this.missingFiles = [];
|
||||
this.usedFiles.push (mainFile.file.name);
|
||||
Import (settings, callbacks)
|
||||
{
|
||||
let mainFile = this.fileList.GetMainFile ();
|
||||
if (mainFile === null || mainFile.file === null || mainFile.file.content === null) {
|
||||
callbacks.onError (new OV.ImportError (OV.ImportErrorCode.NoImportableFile, null));
|
||||
return;
|
||||
}
|
||||
|
||||
let result = new OV.ImportResult ();
|
||||
result.mainFile = mainFile.file.name;
|
||||
this.RevokeModelUrls ();
|
||||
this.model = null;
|
||||
this.usedFiles = [];
|
||||
this.missingFiles = [];
|
||||
this.usedFiles.push (mainFile.file.name);
|
||||
|
||||
let obj = this;
|
||||
let importer = mainFile.importer;
|
||||
let buffers = new OV.ImportBuffers (function (fileName) {
|
||||
let fileBuffer = null;
|
||||
let file = obj.fileList.FindFileByPath (fileName);
|
||||
if (file === null || file.content === null) {
|
||||
obj.missingFiles.push (fileName);
|
||||
fileBuffer = null;
|
||||
} else {
|
||||
fileBuffer = file.content;
|
||||
obj.usedFiles.push (fileName);
|
||||
}
|
||||
return fileBuffer;
|
||||
});
|
||||
let obj = this;
|
||||
let importer = mainFile.importer;
|
||||
let buffers = new OV.ImportBuffers (function (fileName) {
|
||||
let fileBuffer = null;
|
||||
let file = obj.fileList.FindFileByPath (fileName);
|
||||
if (file === null || file.content === null) {
|
||||
obj.missingFiles.push (fileName);
|
||||
fileBuffer = null;
|
||||
} else {
|
||||
fileBuffer = file.content;
|
||||
obj.usedFiles.push (fileName);
|
||||
}
|
||||
return fileBuffer;
|
||||
});
|
||||
|
||||
importer.Import (mainFile.file.content, mainFile.file.extension, {
|
||||
getDefaultMaterial : function () {
|
||||
let material = new OV.Material ();
|
||||
material.diffuse = settings.defaultColor;
|
||||
return material;
|
||||
},
|
||||
getFileBuffer : function (filePath) {
|
||||
return buffers.GetFileBuffer (filePath);
|
||||
},
|
||||
getTextureBuffer : function (filePath) {
|
||||
return buffers.GetTextureBuffer (filePath);
|
||||
}
|
||||
});
|
||||
importer.Import (mainFile.file.content, mainFile.file.extension, {
|
||||
getDefaultMaterial : function () {
|
||||
let material = new OV.Material ();
|
||||
material.diffuse = settings.defaultColor;
|
||||
return material;
|
||||
},
|
||||
getFileBuffer : function (filePath) {
|
||||
return buffers.GetFileBuffer (filePath);
|
||||
},
|
||||
getTextureBuffer : function (filePath) {
|
||||
return buffers.GetTextureBuffer (filePath);
|
||||
},
|
||||
onSuccess : function () {
|
||||
obj.model = importer.GetModel ();
|
||||
obj.model.SetName (mainFile.file.name);
|
||||
|
||||
let result = new OV.ImportResult ();
|
||||
result.mainFile = mainFile.file.name;
|
||||
result.model = obj.model;
|
||||
result.usedFiles = obj.usedFiles;
|
||||
result.missingFiles = obj.missingFiles;
|
||||
result.upVector = importer.GetUpDirection ();
|
||||
callbacks.onSuccess (result);
|
||||
},
|
||||
onError : function () {
|
||||
let message = importer.GetMessage ();
|
||||
callbacks.onError (new OV.ImportError (OV.ImportErrorCode.ImportFailed, message));
|
||||
},
|
||||
onComplete : function () {
|
||||
importer.Clear ();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (importer.IsError ()) {
|
||||
let message = importer.GetMessage ();
|
||||
callbacks.error (new OV.ImportError (OV.ImportErrorCode.ImportFailed, message));
|
||||
return;
|
||||
}
|
||||
LoadFiles (fileList, fileSource, onReady)
|
||||
{
|
||||
let newFileList = new OV.FileList (this.importers);
|
||||
if (fileSource === OV.FileSource.Url) {
|
||||
newFileList.FillFromFileUrls (fileList);
|
||||
} else if (fileSource === OV.FileSource.File) {
|
||||
newFileList.FillFromFileObjects (fileList);
|
||||
}
|
||||
let reset = false;
|
||||
if (newFileList.HasMainFile ()) {
|
||||
reset = true;
|
||||
} else {
|
||||
let foundMissingFile = false;
|
||||
for (let i = 0; i < this.missingFiles.length; i++) {
|
||||
let missingFile = this.missingFiles[i];
|
||||
if (newFileList.ContainsFileByPath (missingFile)) {
|
||||
foundMissingFile = true;
|
||||
}
|
||||
}
|
||||
if (!foundMissingFile) {
|
||||
reset = true;
|
||||
} else {
|
||||
let newFiles = newFileList.GetFiles ();
|
||||
this.fileList.ExtendFromFileList (newFiles);
|
||||
reset = false;
|
||||
}
|
||||
}
|
||||
if (reset) {
|
||||
this.fileList = newFileList;
|
||||
}
|
||||
this.fileList.GetContent (function () {
|
||||
onReady ();
|
||||
});
|
||||
}
|
||||
|
||||
this.model = importer.GetModel ();
|
||||
this.model.SetName (mainFile.file.name);
|
||||
GetFileList ()
|
||||
{
|
||||
return this.fileList;
|
||||
}
|
||||
|
||||
result.model = this.model;
|
||||
result.usedFiles = this.usedFiles;
|
||||
result.missingFiles = this.missingFiles;
|
||||
result.upVector = importer.GetUpDirection ();
|
||||
callbacks.success (result);
|
||||
}
|
||||
IsOnlyFileSource (source)
|
||||
{
|
||||
return this.fileList.IsOnlySource (source);
|
||||
}
|
||||
|
||||
LoadFiles (fileList, fileSource, onReady)
|
||||
{
|
||||
let newFileList = new OV.FileList (this.importers);
|
||||
if (fileSource === OV.FileSource.Url) {
|
||||
newFileList.FillFromFileUrls (fileList);
|
||||
} else if (fileSource === OV.FileSource.File) {
|
||||
newFileList.FillFromFileObjects (fileList);
|
||||
}
|
||||
let reset = false;
|
||||
if (newFileList.HasMainFile ()) {
|
||||
reset = true;
|
||||
} else {
|
||||
let foundMissingFile = false;
|
||||
for (let i = 0; i < this.missingFiles.length; i++) {
|
||||
let missingFile = this.missingFiles[i];
|
||||
if (newFileList.ContainsFileByPath (missingFile)) {
|
||||
foundMissingFile = true;
|
||||
}
|
||||
}
|
||||
if (!foundMissingFile) {
|
||||
reset = true;
|
||||
} else {
|
||||
let newFiles = newFileList.GetFiles ();
|
||||
this.fileList.ExtendFromFileList (newFiles);
|
||||
reset = false;
|
||||
}
|
||||
}
|
||||
if (reset) {
|
||||
this.fileList = newFileList;
|
||||
}
|
||||
this.fileList.GetContent (function () {
|
||||
onReady ();
|
||||
});
|
||||
}
|
||||
|
||||
GetFileList ()
|
||||
{
|
||||
return this.fileList;
|
||||
}
|
||||
|
||||
IsOnlyFileSource (source)
|
||||
{
|
||||
return this.fileList.IsOnlySource (source);
|
||||
}
|
||||
|
||||
RevokeModelUrls ()
|
||||
{
|
||||
if (this.model === null) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < this.model.MaterialCount (); i++) {
|
||||
let material = this.model.GetMaterial (i);
|
||||
material.EnumerateTextureMaps (function (texture) {
|
||||
if (texture.url !== null) {
|
||||
OV.RevokeObjectUrl (texture.url);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
RevokeModelUrls ()
|
||||
{
|
||||
if (this.model === null) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < this.model.MaterialCount (); i++) {
|
||||
let material = this.model.GetMaterial (i);
|
||||
material.EnumerateTextureMaps (function (texture) {
|
||||
if (texture.url !== null) {
|
||||
OV.RevokeObjectUrl (texture.url);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,57 +1,83 @@
|
||||
OV.ImporterBase = class
|
||||
{
|
||||
constructor ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Import (content, extension, callbacks)
|
||||
{
|
||||
this.Clear ();
|
||||
|
||||
this.extension = extension;
|
||||
this.callbacks = callbacks;
|
||||
this.model = new OV.Model ();
|
||||
this.error = false;
|
||||
this.message = null;
|
||||
this.ResetContent ();
|
||||
|
||||
let obj = this;
|
||||
this.ImportContent (content, function () {
|
||||
obj.CreateResult (callbacks);
|
||||
});
|
||||
}
|
||||
|
||||
Clear ()
|
||||
{
|
||||
this.extension = null;
|
||||
this.callbacks = null;
|
||||
this.model = null;
|
||||
this.error = null;
|
||||
this.message = null;
|
||||
this.ClearContent ();
|
||||
}
|
||||
|
||||
Import (content, extension, callbacks)
|
||||
{
|
||||
this.extension = extension;
|
||||
this.callbacks = callbacks;
|
||||
this.model = new OV.Model ();
|
||||
this.error = false;
|
||||
this.message = null;
|
||||
|
||||
this.ResetState ();
|
||||
this.ImportContent (content);
|
||||
CreateResult (callbacks)
|
||||
{
|
||||
if (this.error) {
|
||||
callbacks.onError ();
|
||||
callbacks.onComplete ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (OV.IsModelEmpty (this.model)) {
|
||||
this.error = true;
|
||||
callbacks.onError ();
|
||||
callbacks.onComplete ();
|
||||
return;
|
||||
}
|
||||
|
||||
OV.FinalizeModel (this.model, this.callbacks.getDefaultMaterial);
|
||||
}
|
||||
|
||||
ResetState ()
|
||||
{
|
||||
|
||||
callbacks.onSuccess ();
|
||||
callbacks.onComplete ();
|
||||
}
|
||||
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
GetUpDirection ()
|
||||
{
|
||||
return OV.Direction.Z;
|
||||
}
|
||||
|
||||
ImportContent (content)
|
||||
ClearContent ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ResetContent ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ImportContent (fileContent, onFinish)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@ -1,40 +1,40 @@
|
||||
OV.GltfComponentType =
|
||||
{
|
||||
BYTE : 5120,
|
||||
UNSIGNED_BYTE : 5121,
|
||||
SHORT : 5122,
|
||||
UNSIGNED_SHORT : 5123,
|
||||
UNSIGNED_INT : 5125,
|
||||
FLOAT : 5126
|
||||
BYTE : 5120,
|
||||
UNSIGNED_BYTE : 5121,
|
||||
SHORT : 5122,
|
||||
UNSIGNED_SHORT : 5123,
|
||||
UNSIGNED_INT : 5125,
|
||||
FLOAT : 5126
|
||||
};
|
||||
|
||||
OV.GltfDataType =
|
||||
{
|
||||
SCALAR : 0,
|
||||
VEC2 : 1,
|
||||
VEC3 : 2,
|
||||
VEC4 : 3,
|
||||
MAT2 : 4,
|
||||
MAT3 : 5,
|
||||
SCALAR : 0,
|
||||
VEC2 : 1,
|
||||
VEC3 : 2,
|
||||
VEC4 : 3,
|
||||
MAT2 : 4,
|
||||
MAT3 : 5,
|
||||
MAT4 : 6
|
||||
};
|
||||
|
||||
OV.GltfRenderMode =
|
||||
{
|
||||
POINTS : 0,
|
||||
LINES : 1,
|
||||
LINE_LOOP : 2,
|
||||
LINE_STRIP : 3,
|
||||
TRIANGLES : 4,
|
||||
TRIANGLE_STRIP : 5,
|
||||
POINTS : 0,
|
||||
LINES : 1,
|
||||
LINE_LOOP : 2,
|
||||
LINE_STRIP : 3,
|
||||
TRIANGLES : 4,
|
||||
TRIANGLE_STRIP : 5,
|
||||
TRIANGLE_FAN : 6
|
||||
};
|
||||
|
||||
OV.GltfConstants =
|
||||
{
|
||||
GLTF_STRING : 0x46546C67,
|
||||
JSON_CHUNK_TYPE : 0x4E4F534A,
|
||||
BINARY_CHUNK_TYPE : 0x004E4942
|
||||
GLTF_STRING : 0x46546C67,
|
||||
JSON_CHUNK_TYPE : 0x4E4F534A,
|
||||
BINARY_CHUNK_TYPE : 0x004E4942
|
||||
};
|
||||
|
||||
OV.GltfNodeTree = class
|
||||
@ -345,49 +345,53 @@ OV.GltfExtensions = class
|
||||
|
||||
OV.ImporterGltf = class extends OV.ImporterBase
|
||||
{
|
||||
constructor ()
|
||||
{
|
||||
super ();
|
||||
|
||||
this.bufferContents = null;
|
||||
this.gltfExtensions = null;
|
||||
this.imageIndexToTextureParams = null;
|
||||
}
|
||||
|
||||
ResetState ()
|
||||
{
|
||||
this.bufferContents = [];
|
||||
this.gltfExtensions = new OV.GltfExtensions ();
|
||||
this.imageIndexToTextureParams = {};
|
||||
}
|
||||
constructor ()
|
||||
{
|
||||
super ();
|
||||
}
|
||||
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return extension === 'gltf' || extension === 'glb';
|
||||
}
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return extension === 'gltf' || extension === 'glb';
|
||||
}
|
||||
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {
|
||||
'gltf' : OV.FileFormat.Text,
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {
|
||||
'gltf' : OV.FileFormat.Text,
|
||||
'glb' : OV.FileFormat.Binary,
|
||||
'bin' : OV.FileFormat.Binary
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
GetUpDirection ()
|
||||
{
|
||||
return OV.Direction.Y;
|
||||
}
|
||||
|
||||
ImportContent (fileContent)
|
||||
{
|
||||
ClearContent ()
|
||||
{
|
||||
this.bufferContents = null;
|
||||
this.gltfExtensions = null;
|
||||
this.imageIndexToTextureParams = null;
|
||||
}
|
||||
|
||||
ResetContent ()
|
||||
{
|
||||
this.bufferContents = [];
|
||||
this.gltfExtensions = new OV.GltfExtensions ();
|
||||
this.imageIndexToTextureParams = {};
|
||||
}
|
||||
|
||||
ImportContent (fileContent, onFinish)
|
||||
{
|
||||
if (this.extension === 'gltf') {
|
||||
this.ProcessGltf (fileContent);
|
||||
} else if (this.extension === 'glb') {
|
||||
this.ProcessBinaryGltf (fileContent);
|
||||
}
|
||||
}
|
||||
onFinish ();
|
||||
}
|
||||
|
||||
ProcessGltf (fileContent)
|
||||
{
|
||||
@ -868,7 +872,7 @@ OV.ImporterGltf = class extends OV.ImporterBase
|
||||
let reader = new OV.GltfBufferReader (buffer);
|
||||
reader.SkipBytes (bufferView.byteOffset || 0);
|
||||
let byteStride = bufferView.byteStride;
|
||||
if (byteStride !== undefined) {
|
||||
if (byteStride !== undefined && byteStride !== 0) {
|
||||
reader.SetByteStride (byteStride);
|
||||
}
|
||||
|
||||
|
||||
@ -1,387 +1,391 @@
|
||||
OV.ImporterObj = class extends OV.ImporterBase
|
||||
{
|
||||
constructor ()
|
||||
{
|
||||
super ();
|
||||
constructor ()
|
||||
{
|
||||
super ();
|
||||
}
|
||||
|
||||
this.globalVertices = null;
|
||||
this.globalNormals = null;
|
||||
this.globalUvs = null;
|
||||
|
||||
this.currentMesh = null;
|
||||
this.currentMeshData = null;
|
||||
this.currentMaterial = null;
|
||||
this.currentMaterialIndex = null;
|
||||
|
||||
this.meshNameToMeshData = null;
|
||||
this.materialNameToIndex = null;
|
||||
}
|
||||
|
||||
ResetState ()
|
||||
{
|
||||
this.globalVertices = [];
|
||||
this.globalNormals = [];
|
||||
this.globalUvs = [];
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return extension === 'obj';
|
||||
}
|
||||
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {
|
||||
'obj' : OV.FileFormat.Text,
|
||||
'mtl' : OV.FileFormat.Text
|
||||
};
|
||||
}
|
||||
|
||||
this.currentMesh = null;
|
||||
this.currentMeshData = null;
|
||||
this.currentMaterial = null;
|
||||
this.currentMaterialIndex = null;
|
||||
|
||||
this.meshNameToMeshData = {};
|
||||
this.materialNameToIndex = {};
|
||||
}
|
||||
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return extension === 'obj';
|
||||
}
|
||||
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {
|
||||
'obj' : OV.FileFormat.Text,
|
||||
'mtl' : OV.FileFormat.Text
|
||||
};
|
||||
}
|
||||
|
||||
GetUpDirection ()
|
||||
GetUpDirection ()
|
||||
{
|
||||
return OV.Direction.Y;
|
||||
}
|
||||
|
||||
ImportContent (fileContent)
|
||||
{
|
||||
let obj = this;
|
||||
OV.ReadLines (fileContent, function (line) {
|
||||
if (!obj.IsError ()) {
|
||||
obj.ProcessLine (line);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ProcessLine (line)
|
||||
{
|
||||
if (line[0] === '#') {
|
||||
return;
|
||||
}
|
||||
|
||||
ClearContent ()
|
||||
{
|
||||
this.globalVertices = null;
|
||||
this.globalNormals = null;
|
||||
this.globalUvs = null;
|
||||
|
||||
this.currentMesh = null;
|
||||
this.currentMeshData = null;
|
||||
this.currentMaterial = null;
|
||||
this.currentMaterialIndex = null;
|
||||
|
||||
this.meshNameToMeshData = null;
|
||||
this.materialNameToIndex = null;
|
||||
}
|
||||
|
||||
let parameters = OV.ParametersFromLine (line, '#');
|
||||
if (parameters.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let keyword = parameters[0].toLowerCase ();
|
||||
parameters.shift ();
|
||||
ResetContent ()
|
||||
{
|
||||
this.globalVertices = [];
|
||||
this.globalNormals = [];
|
||||
this.globalUvs = [];
|
||||
|
||||
if (this.ProcessMeshParameter (keyword, parameters, line)) {
|
||||
return;
|
||||
}
|
||||
this.currentMesh = null;
|
||||
this.currentMeshData = null;
|
||||
this.currentMaterial = null;
|
||||
this.currentMaterialIndex = null;
|
||||
|
||||
if (this.ProcessMaterialParameter (keyword, parameters, line)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AddNewMesh (name)
|
||||
{
|
||||
let meshData = this.meshNameToMeshData[name];
|
||||
if (meshData === undefined) {
|
||||
let mesh = new OV.Mesh ();
|
||||
if (name !== null) {
|
||||
mesh.SetName (name);
|
||||
}
|
||||
this.model.AddMesh (mesh);
|
||||
meshData = {
|
||||
mesh : mesh,
|
||||
data : {
|
||||
globalToCurrentVertices : {},
|
||||
globalToCurrentNormals : {},
|
||||
globalToCurrentUvs : {}
|
||||
}
|
||||
};
|
||||
this.meshNameToMeshData[name] = meshData;
|
||||
}
|
||||
this.currentMesh = meshData.mesh;
|
||||
this.currentMeshData = meshData.data;
|
||||
}
|
||||
this.meshNameToMeshData = {};
|
||||
this.materialNameToIndex = {};
|
||||
}
|
||||
|
||||
ImportContent (fileContent, onFinish)
|
||||
{
|
||||
let obj = this;
|
||||
OV.ReadLines (fileContent, function (line) {
|
||||
if (!obj.IsError ()) {
|
||||
obj.ProcessLine (line);
|
||||
}
|
||||
});
|
||||
onFinish ();
|
||||
}
|
||||
|
||||
ProcessLine (line)
|
||||
{
|
||||
if (line[0] === '#') {
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessMeshParameter (keyword, parameters, line)
|
||||
{
|
||||
if (keyword === 'g' || keyword === 'o') {
|
||||
if (parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
let name = OV.NameFromLine (line, keyword.length, '#');
|
||||
this.AddNewMesh (name);
|
||||
return true;
|
||||
} else if (keyword === 'v') {
|
||||
if (parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.globalVertices.push (new OV.Coord3D (
|
||||
parseFloat (parameters[0]),
|
||||
parseFloat (parameters[1]),
|
||||
parseFloat (parameters[2])
|
||||
));
|
||||
return true;
|
||||
} else if (keyword === 'vn') {
|
||||
if (parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.globalNormals.push (new OV.Coord3D (
|
||||
parseFloat (parameters[0]),
|
||||
parseFloat (parameters[1]),
|
||||
parseFloat (parameters[2])
|
||||
));
|
||||
return true;
|
||||
} else if (keyword === 'vt') {
|
||||
if (parameters.length < 2) {
|
||||
return true;
|
||||
}
|
||||
this.globalUvs.push (new OV.Coord2D (
|
||||
parseFloat (parameters[0]),
|
||||
parseFloat (parameters[1])
|
||||
));
|
||||
return true;
|
||||
} else if (keyword === 'f') {
|
||||
if (parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.ProcessFace (parameters);
|
||||
return true;
|
||||
}
|
||||
let parameters = OV.ParametersFromLine (line, '#');
|
||||
if (parameters.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let keyword = parameters[0].toLowerCase ();
|
||||
parameters.shift ();
|
||||
|
||||
return false;
|
||||
}
|
||||
if (this.ProcessMeshParameter (keyword, parameters, line)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessMaterialParameter (keyword, parameters, line)
|
||||
{
|
||||
function CreateColor (parameters)
|
||||
{
|
||||
return new OV.Color (
|
||||
parseInt (parseFloat (parameters[0] * 255.0), 10),
|
||||
parseInt (parseFloat (parameters[1] * 255.0), 10),
|
||||
parseInt (parseFloat (parameters[2] * 255.0), 10)
|
||||
);
|
||||
}
|
||||
if (this.ProcessMaterialParameter (keyword, parameters, line)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AddNewMesh (name)
|
||||
{
|
||||
let meshData = this.meshNameToMeshData[name];
|
||||
if (meshData === undefined) {
|
||||
let mesh = new OV.Mesh ();
|
||||
if (name !== null) {
|
||||
mesh.SetName (name);
|
||||
}
|
||||
this.model.AddMesh (mesh);
|
||||
meshData = {
|
||||
mesh : mesh,
|
||||
data : {
|
||||
globalToCurrentVertices : {},
|
||||
globalToCurrentNormals : {},
|
||||
globalToCurrentUvs : {}
|
||||
}
|
||||
};
|
||||
this.meshNameToMeshData[name] = meshData;
|
||||
}
|
||||
this.currentMesh = meshData.mesh;
|
||||
this.currentMeshData = meshData.data;
|
||||
}
|
||||
|
||||
function CreateTexture (keyword, line, callbacks)
|
||||
{
|
||||
let texture = new OV.TextureMap ();
|
||||
let textureName = OV.NameFromLine (line, keyword.length, '#');
|
||||
let textureBuffer = callbacks.getTextureBuffer (textureName);
|
||||
texture.name = textureName;
|
||||
if (textureBuffer !== null) {
|
||||
texture.url = textureBuffer.url;
|
||||
texture.buffer = textureBuffer.buffer;
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
ProcessMeshParameter (keyword, parameters, line)
|
||||
{
|
||||
if (keyword === 'g' || keyword === 'o') {
|
||||
if (parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
let name = OV.NameFromLine (line, keyword.length, '#');
|
||||
this.AddNewMesh (name);
|
||||
return true;
|
||||
} else if (keyword === 'v') {
|
||||
if (parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.globalVertices.push (new OV.Coord3D (
|
||||
parseFloat (parameters[0]),
|
||||
parseFloat (parameters[1]),
|
||||
parseFloat (parameters[2])
|
||||
));
|
||||
return true;
|
||||
} else if (keyword === 'vn') {
|
||||
if (parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.globalNormals.push (new OV.Coord3D (
|
||||
parseFloat (parameters[0]),
|
||||
parseFloat (parameters[1]),
|
||||
parseFloat (parameters[2])
|
||||
));
|
||||
return true;
|
||||
} else if (keyword === 'vt') {
|
||||
if (parameters.length < 2) {
|
||||
return true;
|
||||
}
|
||||
this.globalUvs.push (new OV.Coord2D (
|
||||
parseFloat (parameters[0]),
|
||||
parseFloat (parameters[1])
|
||||
));
|
||||
return true;
|
||||
} else if (keyword === 'f') {
|
||||
if (parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.ProcessFace (parameters);
|
||||
return true;
|
||||
}
|
||||
|
||||
let obj = this;
|
||||
if (keyword === 'newmtl') {
|
||||
if (parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let material = new OV.Material ();
|
||||
let materialName = OV.NameFromLine (line, keyword.length, '#');
|
||||
let materialIndex = this.model.AddMaterial (material);
|
||||
material.name = materialName;
|
||||
this.currentMaterial = material;
|
||||
this.materialNameToIndex[materialName] = materialIndex;
|
||||
return true;
|
||||
} else if (keyword === 'usemtl') {
|
||||
if (parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let materialName = OV.NameFromLine (line, keyword.length, '#');
|
||||
let materialIndex = this.materialNameToIndex[materialName];
|
||||
if (materialIndex !== undefined) {
|
||||
this.currentMaterialIndex = materialIndex;
|
||||
}
|
||||
return true;
|
||||
} else if (keyword === 'mtllib') {
|
||||
if (parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
let fileName = OV.NameFromLine (line, keyword.length, '#');
|
||||
let fileBuffer = this.callbacks.getFileBuffer (fileName);
|
||||
if (fileBuffer !== null) {
|
||||
OV.ReadLines (fileBuffer, function (line) {
|
||||
if (!obj.IsError ()) {
|
||||
obj.ProcessLine (line);
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
} else if (keyword === 'map_kd') {
|
||||
if (this.currentMaterial === null || parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.diffuseMap = CreateTexture (keyword, line, this.callbacks);
|
||||
return true;
|
||||
} else if (keyword === 'map_ks') {
|
||||
if (this.currentMaterial === null || parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.specularMap = CreateTexture (keyword, line, this.callbacks);
|
||||
return true;
|
||||
} else if (keyword === 'map_bump' || keyword === 'bump') {
|
||||
if (this.currentMaterial === null || parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.bumpMap = CreateTexture (keyword, line, this.callbacks);
|
||||
return true;
|
||||
} else if (keyword === 'ka') {
|
||||
if (this.currentMaterial === null || parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.ambient = CreateColor (parameters);
|
||||
return true;
|
||||
} else if (keyword === 'kd') {
|
||||
if (this.currentMaterial === null || parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.diffuse = CreateColor (parameters);
|
||||
return true;
|
||||
} else if (keyword === 'ks') {
|
||||
if (this.currentMaterial === null || parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.specular = CreateColor (parameters);
|
||||
return true;
|
||||
} else if (keyword === 'ns') {
|
||||
if (this.currentMaterial === null || parameters.length < 1) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.shininess = parseFloat (parameters[0]) / 100.0;
|
||||
return true;
|
||||
} else if (keyword === 'tr') {
|
||||
if (this.currentMaterial === null || parameters.length < 1) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.opacity = 1.0 - parseFloat (parameters[0]);
|
||||
this.currentMaterial.transparent = OV.IsLower (this.currentMaterial.opacity, 1.0);
|
||||
return true;
|
||||
} else if (keyword === 'd') {
|
||||
if (this.currentMaterial === null || parameters.length < 1) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.opacity = parseFloat (parameters[0]);
|
||||
this.currentMaterial.transparent = OV.IsLower (this.currentMaterial.opacity, 1.0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
ProcessMaterialParameter (keyword, parameters, line)
|
||||
{
|
||||
function CreateColor (parameters)
|
||||
{
|
||||
return new OV.Color (
|
||||
parseInt (parseFloat (parameters[0] * 255.0), 10),
|
||||
parseInt (parseFloat (parameters[1] * 255.0), 10),
|
||||
parseInt (parseFloat (parameters[2] * 255.0), 10)
|
||||
);
|
||||
}
|
||||
|
||||
ProcessFace (parameters)
|
||||
{
|
||||
function GetRelativeIndex (index, count)
|
||||
{
|
||||
if (index > 0) {
|
||||
return index - 1;
|
||||
} else {
|
||||
return count + index;
|
||||
}
|
||||
}
|
||||
|
||||
function GetLocalIndex (globalValueArray, globalToCurrentIndices, globalIndex, valueAdderFunc)
|
||||
{
|
||||
if (isNaN (globalIndex) || globalIndex < 0 || globalIndex >= globalValueArray.length) {
|
||||
return null;
|
||||
}
|
||||
let result = globalToCurrentIndices[globalIndex];
|
||||
if (result === undefined) {
|
||||
let globalValue = globalValueArray[globalIndex];
|
||||
if (globalValue === undefined) {
|
||||
return null;
|
||||
}
|
||||
result = valueAdderFunc (globalValue);
|
||||
globalToCurrentIndices[globalIndex] = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function GetLocalVertexIndex (obj, mesh, globalIndex)
|
||||
{
|
||||
return GetLocalIndex (obj.globalVertices, obj.currentMeshData.globalToCurrentVertices, globalIndex, function (val) {
|
||||
return mesh.AddVertex (new OV.Coord3D (val.x, val.y, val.z));
|
||||
});
|
||||
}
|
||||
|
||||
function GetLocalNormalIndex (obj, mesh, globalIndex)
|
||||
{
|
||||
return GetLocalIndex (obj.globalNormals, obj.currentMeshData.globalToCurrentNormals, globalIndex, function (val) {
|
||||
return mesh.AddNormal (new OV.Coord3D (val.x, val.y, val.z));
|
||||
});
|
||||
}
|
||||
|
||||
function GetLocalUVIndex (obj, mesh, globalIndex)
|
||||
{
|
||||
return GetLocalIndex (obj.globalUvs, obj.currentMeshData.globalToCurrentUvs, globalIndex, function (val) {
|
||||
return mesh.AddTextureUV (new OV.Coord2D (val.x, val.y));
|
||||
});
|
||||
}
|
||||
|
||||
let vertices = [];
|
||||
let normals = [];
|
||||
let uvs = [];
|
||||
|
||||
for (let i = 0; i < parameters.length; i++) {
|
||||
let vertexParams = parameters[i].split ('/');
|
||||
vertices.push (GetRelativeIndex (parseInt (vertexParams[0], 10), this.globalVertices.length));
|
||||
if (vertexParams.length > 1 && vertexParams[1].length > 0) {
|
||||
uvs.push (GetRelativeIndex (parseInt (vertexParams[1], 10), this.globalUvs.length));
|
||||
}
|
||||
if (vertexParams.length > 2 && vertexParams[2].length > 0) {
|
||||
normals.push (GetRelativeIndex (parseInt (vertexParams[2], 10), this.globalNormals.length));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.currentMesh === null) {
|
||||
this.AddNewMesh ('');
|
||||
}
|
||||
|
||||
for (let i = 0; i < vertices.length - 2; i++) {
|
||||
let v0 = GetLocalVertexIndex (this, this.currentMesh, vertices[0]);
|
||||
let v1 = GetLocalVertexIndex (this, this.currentMesh, vertices[i + 1]);
|
||||
let v2 = GetLocalVertexIndex (this, this.currentMesh, vertices[i + 2]);
|
||||
if (v0 === null || v1 === null || v2 === null) {
|
||||
this.SetError ();
|
||||
this.SetMessage ('Invalid vertex index.');
|
||||
break;
|
||||
}
|
||||
let triangle = new OV.Triangle (v0, v1, v2);
|
||||
if (normals.length === vertices.length) {
|
||||
let n0 = GetLocalNormalIndex (this, this.currentMesh, normals[0]);
|
||||
let n1 = GetLocalNormalIndex (this, this.currentMesh, normals[i + 1]);
|
||||
let n2 = GetLocalNormalIndex (this, this.currentMesh, normals[i + 2]);
|
||||
if (n0 === null || n1 === null || n2 === null) {
|
||||
this.SetError ();
|
||||
this.SetMessage ('Invalid normal index.');
|
||||
break;
|
||||
}
|
||||
triangle.SetNormals (n0, n1, n2);
|
||||
}
|
||||
if (uvs.length === vertices.length) {
|
||||
let u0 = GetLocalUVIndex (this, this.currentMesh, uvs[0]);
|
||||
let u1 = GetLocalUVIndex (this, this.currentMesh, uvs[i + 1]);
|
||||
let u2 = GetLocalUVIndex (this, this.currentMesh, uvs[i + 2]);
|
||||
if (u0 === null || u1 === null || u2 === null) {
|
||||
this.SetError ();
|
||||
this.SetMessage ('Invalid uv index.');
|
||||
break;
|
||||
}
|
||||
triangle.SetTextureUVs (u0, u1, u2);
|
||||
}
|
||||
if (this.currentMaterialIndex !== null) {
|
||||
triangle.mat = this.currentMaterialIndex;
|
||||
}
|
||||
this.currentMesh.AddTriangle (triangle);
|
||||
}
|
||||
}
|
||||
function CreateTexture (keyword, line, callbacks)
|
||||
{
|
||||
let texture = new OV.TextureMap ();
|
||||
let textureName = OV.NameFromLine (line, keyword.length, '#');
|
||||
let textureBuffer = callbacks.getTextureBuffer (textureName);
|
||||
texture.name = textureName;
|
||||
if (textureBuffer !== null) {
|
||||
texture.url = textureBuffer.url;
|
||||
texture.buffer = textureBuffer.buffer;
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
let obj = this;
|
||||
if (keyword === 'newmtl') {
|
||||
if (parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let material = new OV.Material ();
|
||||
let materialName = OV.NameFromLine (line, keyword.length, '#');
|
||||
let materialIndex = this.model.AddMaterial (material);
|
||||
material.name = materialName;
|
||||
this.currentMaterial = material;
|
||||
this.materialNameToIndex[materialName] = materialIndex;
|
||||
return true;
|
||||
} else if (keyword === 'usemtl') {
|
||||
if (parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let materialName = OV.NameFromLine (line, keyword.length, '#');
|
||||
let materialIndex = this.materialNameToIndex[materialName];
|
||||
if (materialIndex !== undefined) {
|
||||
this.currentMaterialIndex = materialIndex;
|
||||
}
|
||||
return true;
|
||||
} else if (keyword === 'mtllib') {
|
||||
if (parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
let fileName = OV.NameFromLine (line, keyword.length, '#');
|
||||
let fileBuffer = this.callbacks.getFileBuffer (fileName);
|
||||
if (fileBuffer !== null) {
|
||||
OV.ReadLines (fileBuffer, function (line) {
|
||||
if (!obj.IsError ()) {
|
||||
obj.ProcessLine (line);
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
} else if (keyword === 'map_kd') {
|
||||
if (this.currentMaterial === null || parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.diffuseMap = CreateTexture (keyword, line, this.callbacks);
|
||||
return true;
|
||||
} else if (keyword === 'map_ks') {
|
||||
if (this.currentMaterial === null || parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.specularMap = CreateTexture (keyword, line, this.callbacks);
|
||||
return true;
|
||||
} else if (keyword === 'map_bump' || keyword === 'bump') {
|
||||
if (this.currentMaterial === null || parameters.length === 0) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.bumpMap = CreateTexture (keyword, line, this.callbacks);
|
||||
return true;
|
||||
} else if (keyword === 'ka') {
|
||||
if (this.currentMaterial === null || parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.ambient = CreateColor (parameters);
|
||||
return true;
|
||||
} else if (keyword === 'kd') {
|
||||
if (this.currentMaterial === null || parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.diffuse = CreateColor (parameters);
|
||||
return true;
|
||||
} else if (keyword === 'ks') {
|
||||
if (this.currentMaterial === null || parameters.length < 3) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.specular = CreateColor (parameters);
|
||||
return true;
|
||||
} else if (keyword === 'ns') {
|
||||
if (this.currentMaterial === null || parameters.length < 1) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.shininess = parseFloat (parameters[0]) / 1000.0;
|
||||
return true;
|
||||
} else if (keyword === 'tr') {
|
||||
if (this.currentMaterial === null || parameters.length < 1) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.opacity = 1.0 - parseFloat (parameters[0]);
|
||||
this.currentMaterial.transparent = OV.IsLower (this.currentMaterial.opacity, 1.0);
|
||||
return true;
|
||||
} else if (keyword === 'd') {
|
||||
if (this.currentMaterial === null || parameters.length < 1) {
|
||||
return true;
|
||||
}
|
||||
this.currentMaterial.opacity = parseFloat (parameters[0]);
|
||||
this.currentMaterial.transparent = OV.IsLower (this.currentMaterial.opacity, 1.0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ProcessFace (parameters)
|
||||
{
|
||||
function GetRelativeIndex (index, count)
|
||||
{
|
||||
if (index > 0) {
|
||||
return index - 1;
|
||||
} else {
|
||||
return count + index;
|
||||
}
|
||||
}
|
||||
|
||||
function GetLocalIndex (globalValueArray, globalToCurrentIndices, globalIndex, valueAdderFunc)
|
||||
{
|
||||
if (isNaN (globalIndex) || globalIndex < 0 || globalIndex >= globalValueArray.length) {
|
||||
return null;
|
||||
}
|
||||
let result = globalToCurrentIndices[globalIndex];
|
||||
if (result === undefined) {
|
||||
let globalValue = globalValueArray[globalIndex];
|
||||
if (globalValue === undefined) {
|
||||
return null;
|
||||
}
|
||||
result = valueAdderFunc (globalValue);
|
||||
globalToCurrentIndices[globalIndex] = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function GetLocalVertexIndex (obj, mesh, globalIndex)
|
||||
{
|
||||
return GetLocalIndex (obj.globalVertices, obj.currentMeshData.globalToCurrentVertices, globalIndex, function (val) {
|
||||
return mesh.AddVertex (new OV.Coord3D (val.x, val.y, val.z));
|
||||
});
|
||||
}
|
||||
|
||||
function GetLocalNormalIndex (obj, mesh, globalIndex)
|
||||
{
|
||||
return GetLocalIndex (obj.globalNormals, obj.currentMeshData.globalToCurrentNormals, globalIndex, function (val) {
|
||||
return mesh.AddNormal (new OV.Coord3D (val.x, val.y, val.z));
|
||||
});
|
||||
}
|
||||
|
||||
function GetLocalUVIndex (obj, mesh, globalIndex)
|
||||
{
|
||||
return GetLocalIndex (obj.globalUvs, obj.currentMeshData.globalToCurrentUvs, globalIndex, function (val) {
|
||||
return mesh.AddTextureUV (new OV.Coord2D (val.x, val.y));
|
||||
});
|
||||
}
|
||||
|
||||
let vertices = [];
|
||||
let normals = [];
|
||||
let uvs = [];
|
||||
|
||||
for (let i = 0; i < parameters.length; i++) {
|
||||
let vertexParams = parameters[i].split ('/');
|
||||
vertices.push (GetRelativeIndex (parseInt (vertexParams[0], 10), this.globalVertices.length));
|
||||
if (vertexParams.length > 1 && vertexParams[1].length > 0) {
|
||||
uvs.push (GetRelativeIndex (parseInt (vertexParams[1], 10), this.globalUvs.length));
|
||||
}
|
||||
if (vertexParams.length > 2 && vertexParams[2].length > 0) {
|
||||
normals.push (GetRelativeIndex (parseInt (vertexParams[2], 10), this.globalNormals.length));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.currentMesh === null) {
|
||||
this.AddNewMesh ('');
|
||||
}
|
||||
|
||||
for (let i = 0; i < vertices.length - 2; i++) {
|
||||
let v0 = GetLocalVertexIndex (this, this.currentMesh, vertices[0]);
|
||||
let v1 = GetLocalVertexIndex (this, this.currentMesh, vertices[i + 1]);
|
||||
let v2 = GetLocalVertexIndex (this, this.currentMesh, vertices[i + 2]);
|
||||
if (v0 === null || v1 === null || v2 === null) {
|
||||
this.SetError ();
|
||||
this.SetMessage ('Invalid vertex index.');
|
||||
break;
|
||||
}
|
||||
let triangle = new OV.Triangle (v0, v1, v2);
|
||||
if (normals.length === vertices.length) {
|
||||
let n0 = GetLocalNormalIndex (this, this.currentMesh, normals[0]);
|
||||
let n1 = GetLocalNormalIndex (this, this.currentMesh, normals[i + 1]);
|
||||
let n2 = GetLocalNormalIndex (this, this.currentMesh, normals[i + 2]);
|
||||
if (n0 === null || n1 === null || n2 === null) {
|
||||
this.SetError ();
|
||||
this.SetMessage ('Invalid normal index.');
|
||||
break;
|
||||
}
|
||||
triangle.SetNormals (n0, n1, n2);
|
||||
}
|
||||
if (uvs.length === vertices.length) {
|
||||
let u0 = GetLocalUVIndex (this, this.currentMesh, uvs[0]);
|
||||
let u1 = GetLocalUVIndex (this, this.currentMesh, uvs[i + 1]);
|
||||
let u2 = GetLocalUVIndex (this, this.currentMesh, uvs[i + 2]);
|
||||
if (u0 === null || u1 === null || u2 === null) {
|
||||
this.SetError ();
|
||||
this.SetMessage ('Invalid uv index.');
|
||||
break;
|
||||
}
|
||||
triangle.SetTextureUVs (u0, u1, u2);
|
||||
}
|
||||
if (this.currentMaterialIndex !== null) {
|
||||
triangle.mat = this.currentMaterialIndex;
|
||||
}
|
||||
this.currentMesh.AddTriangle (triangle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -3,13 +3,34 @@ OV.ImporterOff = class extends OV.ImporterBase
|
||||
constructor ()
|
||||
{
|
||||
super ();
|
||||
}
|
||||
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return extension === 'off';
|
||||
}
|
||||
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {
|
||||
'off' : OV.FileFormat.Text
|
||||
};
|
||||
}
|
||||
|
||||
GetUpDirection ()
|
||||
{
|
||||
return OV.Direction.Y;
|
||||
}
|
||||
|
||||
ClearContent ()
|
||||
{
|
||||
this.model = null;
|
||||
this.mesh = null;
|
||||
this.status = null;
|
||||
}
|
||||
|
||||
ResetState ()
|
||||
{
|
||||
|
||||
ResetContent ()
|
||||
{
|
||||
this.mesh = new OV.Mesh ();
|
||||
this.model.AddMesh (this.mesh);
|
||||
this.status = {
|
||||
@ -18,46 +39,30 @@ OV.ImporterOff = class extends OV.ImporterBase
|
||||
foundVertex : 0,
|
||||
foundFace : 0
|
||||
};
|
||||
}
|
||||
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return extension === 'off';
|
||||
}
|
||||
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {
|
||||
'off' : OV.FileFormat.Text
|
||||
};
|
||||
}
|
||||
|
||||
GetUpDirection ()
|
||||
{
|
||||
return OV.Direction.Y;
|
||||
}
|
||||
|
||||
ImportContent (fileContent)
|
||||
{
|
||||
ImportContent (fileContent, onFinish)
|
||||
{
|
||||
let obj = this;
|
||||
OV.ReadLines (fileContent, function (line) {
|
||||
if (!obj.IsError ()) {
|
||||
obj.ProcessLine (line);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ProcessLine (line)
|
||||
{
|
||||
if (line[0] === '#') {
|
||||
return;
|
||||
}
|
||||
OV.ReadLines (fileContent, function (line) {
|
||||
if (!obj.IsError ()) {
|
||||
obj.ProcessLine (line);
|
||||
}
|
||||
});
|
||||
onFinish ();
|
||||
}
|
||||
|
||||
ProcessLine (line)
|
||||
{
|
||||
if (line[0] === '#') {
|
||||
return;
|
||||
}
|
||||
|
||||
let parameters = OV.ParametersFromLine (line, '#');
|
||||
if (parameters.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let parameters = OV.ParametersFromLine (line, '#');
|
||||
if (parameters.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parameters[0] === 'OFF') {
|
||||
return;
|
||||
}
|
||||
@ -99,5 +104,5 @@ OV.ImporterOff = class extends OV.ImporterBase
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -89,51 +89,55 @@ OV.ImporterPly = class extends OV.ImporterBase
|
||||
constructor ()
|
||||
{
|
||||
super ();
|
||||
this.model = null;
|
||||
this.mesh = null;
|
||||
}
|
||||
|
||||
ResetState ()
|
||||
{
|
||||
this.mesh = new OV.Mesh ();
|
||||
this.model.AddMesh (this.mesh);
|
||||
}
|
||||
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return extension === 'ply';
|
||||
}
|
||||
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return extension === 'ply';
|
||||
}
|
||||
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {
|
||||
'ply' : OV.FileFormat.Binary
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
return {
|
||||
'ply' : OV.FileFormat.Binary
|
||||
};
|
||||
}
|
||||
|
||||
GetUpDirection ()
|
||||
{
|
||||
return OV.Direction.Y;
|
||||
}
|
||||
|
||||
ClearContent ()
|
||||
{
|
||||
this.model = null;
|
||||
this.mesh = null;
|
||||
}
|
||||
|
||||
ImportContent (fileContent)
|
||||
{
|
||||
ResetContent ()
|
||||
{
|
||||
this.mesh = new OV.Mesh ();
|
||||
this.model.AddMesh (this.mesh);
|
||||
}
|
||||
|
||||
ImportContent (fileContent, onFinish)
|
||||
{
|
||||
let headerString = this.GetHeaderContent (fileContent);
|
||||
let header = this.ReadHeader (headerString);
|
||||
if (!header.Check ()) {
|
||||
if (header.Check ()) {
|
||||
if (header.format === 'ascii') {
|
||||
let contentString = OV.ArrayBufferToUtf8String (fileContent);
|
||||
contentString = contentString.substr (headerString.length);
|
||||
this.ReadAsciiContent (header, contentString);
|
||||
} else if (header.format === 'binary_little_endian' || header.format === 'binary_big_endian') {
|
||||
this.ReadBinaryContent (header, fileContent, headerString.length);
|
||||
}
|
||||
} else {
|
||||
this.SetError ();
|
||||
this.SetMessage ('Invalid header information.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (header.format === 'ascii') {
|
||||
let contentString = OV.ArrayBufferToUtf8String (fileContent);
|
||||
contentString = contentString.substr (headerString.length);
|
||||
this.ReadAsciiContent (header, contentString);
|
||||
} else if (header.format === 'binary_little_endian' || header.format === 'binary_big_endian') {
|
||||
this.ReadBinaryContent (header, fileContent, headerString.length);
|
||||
}
|
||||
}
|
||||
onFinish ();
|
||||
}
|
||||
|
||||
GetHeaderContent (fileContent)
|
||||
{
|
||||
@ -180,7 +184,7 @@ OV.ImporterPly = class extends OV.ImporterBase
|
||||
header.AddSingleFormat (parameters[1], parameters[2]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return header;
|
||||
}
|
||||
@ -231,7 +235,7 @@ OV.ImporterPly = class extends OV.ImporterBase
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ReadBinaryContent (header, fileContent, headerLength)
|
||||
@ -279,7 +283,7 @@ OV.ImporterPly = class extends OV.ImporterBase
|
||||
return null;
|
||||
}
|
||||
|
||||
let materialName = '#' + IntegerToHex (color[0]) + IntegerToHex (color[1]) + IntegerToHex (color[2]) + IntegerToHex (color[3]);
|
||||
let materialName = 'Color ' + IntegerToHex (color[0]) + IntegerToHex (color[1]) + IntegerToHex (color[2]) + IntegerToHex (color[3]);
|
||||
let materialIndex = colorToMaterial[materialName];
|
||||
if (materialIndex === undefined) {
|
||||
let material = new OV.Material ();
|
||||
|
||||
@ -3,36 +3,40 @@ OV.ImporterStl = class extends OV.ImporterBase
|
||||
constructor ()
|
||||
{
|
||||
super ();
|
||||
this.mesh = null;
|
||||
this.triangle = null;
|
||||
}
|
||||
|
||||
ResetState ()
|
||||
{
|
||||
this.mesh = new OV.Mesh ();
|
||||
this.model.AddMesh (this.mesh);
|
||||
this.triangle = null;
|
||||
}
|
||||
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return extension === 'stl';
|
||||
}
|
||||
CanImportExtension (extension)
|
||||
{
|
||||
return extension === 'stl';
|
||||
}
|
||||
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {
|
||||
'stl' : OV.FileFormat.Binary
|
||||
};
|
||||
}
|
||||
|
||||
GetKnownFileFormats ()
|
||||
{
|
||||
return {
|
||||
'stl' : OV.FileFormat.Binary
|
||||
};
|
||||
}
|
||||
|
||||
GetUpDirection ()
|
||||
{
|
||||
return OV.Direction.Z;
|
||||
}
|
||||
|
||||
ClearContent ()
|
||||
{
|
||||
this.mesh = null;
|
||||
this.triangle = null;
|
||||
}
|
||||
|
||||
ImportContent (fileContent)
|
||||
{
|
||||
ResetContent ()
|
||||
{
|
||||
this.mesh = new OV.Mesh ();
|
||||
this.model.AddMesh (this.mesh);
|
||||
this.triangle = null;
|
||||
}
|
||||
|
||||
ImportContent (fileContent, onFinish)
|
||||
{
|
||||
if (this.IsBinaryStlFile (fileContent)) {
|
||||
this.ProcessBinary (fileContent);
|
||||
} else {
|
||||
@ -44,10 +48,11 @@ OV.ImporterStl = class extends OV.ImporterBase
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
onFinish ();
|
||||
}
|
||||
|
||||
IsBinaryStlFile (fileContent)
|
||||
{
|
||||
IsBinaryStlFile (fileContent)
|
||||
{
|
||||
let byteLength = fileContent.byteLength;
|
||||
if (byteLength < 84) {
|
||||
return false;
|
||||
@ -64,17 +69,17 @@ OV.ImporterStl = class extends OV.ImporterBase
|
||||
return true;
|
||||
}
|
||||
|
||||
ProcessLine (line)
|
||||
{
|
||||
if (line[0] === '#') {
|
||||
return;
|
||||
}
|
||||
ProcessLine (line)
|
||||
{
|
||||
if (line[0] === '#') {
|
||||
return;
|
||||
}
|
||||
|
||||
let parameters = OV.ParametersFromLine (line, '#');
|
||||
if (parameters.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let parameters = OV.ParametersFromLine (line, '#');
|
||||
if (parameters.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let keyword = parameters[0];
|
||||
if (keyword === 'solid') {
|
||||
if (parameters.length > 1) {
|
||||
@ -132,7 +137,7 @@ OV.ImporterStl = class extends OV.ImporterBase
|
||||
}
|
||||
|
||||
ProcessBinary (fileContent)
|
||||
{
|
||||
{
|
||||
function ReadVector (reader)
|
||||
{
|
||||
let coord = new OV.Coord3D ();
|
||||
|
||||
@ -40,6 +40,16 @@ OV.MeshBuffer = class
|
||||
this.primitives = [];
|
||||
}
|
||||
|
||||
PrimitiveCount ()
|
||||
{
|
||||
return this.primitives.length;
|
||||
}
|
||||
|
||||
GetPrimitive (index)
|
||||
{
|
||||
return this.primitives[index];
|
||||
}
|
||||
|
||||
GetByteLength (indexTypeSize, numberTypeSize)
|
||||
{
|
||||
let byteLength = 0;
|
||||
@ -53,7 +63,7 @@ OV.MeshBuffer = class
|
||||
|
||||
OV.ConvertMeshToMeshBuffer = function (mesh)
|
||||
{
|
||||
function AddVertexToPrimitiveBuffer (mesh, vertexIndex, normalIndex, uvIndex, primitiveBuffer, primitiveMaps)
|
||||
function AddVertexToPrimitiveBuffer (mesh, vertexIndex, normalIndex, uvIndex, primitiveBuffer, meshToPrimitiveVertices)
|
||||
{
|
||||
function GetUVOrDefault (mesh, uvIndex, forceUVs)
|
||||
{
|
||||
@ -106,10 +116,10 @@ OV.ConvertMeshToMeshBuffer = function (mesh)
|
||||
return null;
|
||||
}
|
||||
|
||||
let primitiveVertices = primitiveMaps.meshToPrimitiveVertices[vertexIndex];
|
||||
let primitiveVertices = meshToPrimitiveVertices[vertexIndex];
|
||||
if (primitiveVertices === undefined) {
|
||||
let primitiveVertex = AddVertex (mesh, vertexIndex, normalIndex, uvIndex, primitiveBuffer);
|
||||
primitiveMaps.meshToPrimitiveVertices[vertexIndex] = [primitiveVertex];
|
||||
meshToPrimitiveVertices[vertexIndex] = [primitiveVertex];
|
||||
} else {
|
||||
let existingPrimitiveVertex = FindMatchingPrimitiveVertex (mesh, primitiveVertices, normalIndex, uvIndex);
|
||||
if (existingPrimitiveVertex !== null) {
|
||||
@ -139,21 +149,19 @@ OV.ConvertMeshToMeshBuffer = function (mesh)
|
||||
});
|
||||
|
||||
let primitiveBuffer = null;
|
||||
let primitiveMaps = null;
|
||||
let meshToPrimitiveVertices = null;
|
||||
for (let i = 0; i < triangleIndices.length; i++) {
|
||||
let triangleIndex = triangleIndices[i];
|
||||
let triangle = mesh.GetTriangle (triangleIndex);
|
||||
if (primitiveBuffer === null || primitiveBuffer.material !== triangle.mat) {
|
||||
primitiveBuffer = new OV.MeshPrimitiveBuffer ();
|
||||
primitiveBuffer.material = triangle.mat;
|
||||
primitiveMaps = {
|
||||
meshToPrimitiveVertices : {}
|
||||
};
|
||||
meshToPrimitiveVertices = {};
|
||||
meshBuffer.primitives.push (primitiveBuffer);
|
||||
}
|
||||
AddVertexToPrimitiveBuffer (mesh, triangle.v0, triangle.n0, triangle.u0, primitiveBuffer, primitiveMaps);
|
||||
AddVertexToPrimitiveBuffer (mesh, triangle.v1, triangle.n1, triangle.u1, primitiveBuffer, primitiveMaps);
|
||||
AddVertexToPrimitiveBuffer (mesh, triangle.v2, triangle.n2, triangle.u2, primitiveBuffer, primitiveMaps);
|
||||
AddVertexToPrimitiveBuffer (mesh, triangle.v0, triangle.n0, triangle.u0, primitiveBuffer, meshToPrimitiveVertices);
|
||||
AddVertexToPrimitiveBuffer (mesh, triangle.v1, triangle.n1, triangle.u1, primitiveBuffer, meshToPrimitiveVertices);
|
||||
AddVertexToPrimitiveBuffer (mesh, triangle.v2, triangle.n2, triangle.u2, primitiveBuffer, meshToPrimitiveVertices);
|
||||
}
|
||||
|
||||
return meshBuffer;
|
||||
|
||||
@ -25,6 +25,13 @@ OV.Color = class
|
||||
this.b = b; // 0 .. 255
|
||||
}
|
||||
|
||||
Set (r, g, b)
|
||||
{
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
Clone ()
|
||||
{
|
||||
return new OV.Color (this.r, this.g, this.b);
|
||||
|
||||
@ -41,6 +41,16 @@ OV.TransformMesh = function (mesh, transformation)
|
||||
}
|
||||
};
|
||||
|
||||
OV.FlipMeshTrianglesOrientation = function (mesh)
|
||||
{
|
||||
for (let i = 0; i < mesh.TriangleCount (); i++) {
|
||||
let triangle = mesh.GetTriangle (i);
|
||||
let tmp = triangle.v1;
|
||||
triangle.v1 = triangle.v2;
|
||||
triangle.v2 = tmp;
|
||||
}
|
||||
};
|
||||
|
||||
OV.GetMeshBoundingBox = function (mesh)
|
||||
{
|
||||
let min = new OV.Coord3D (Infinity, Infinity, Infinity);
|
||||
|
||||
@ -10,7 +10,6 @@ OV.Init3DViewerElements = function ()
|
||||
|
||||
let width = element.clientWidth;
|
||||
let height = element.clientHeight;
|
||||
console.log (element.clientHeight);
|
||||
viewer.Resize (width, height);
|
||||
|
||||
let loader = new OV.ThreeModelLoader ();
|
||||
|
||||
@ -308,6 +308,10 @@ OV.Navigation = class
|
||||
}
|
||||
}
|
||||
|
||||
if (newCamera === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stepCount === 0) {
|
||||
this.SetCamera (newCamera);
|
||||
return;
|
||||
|
||||
@ -43,7 +43,10 @@ OV.UpVector = class
|
||||
let newEye = oldCamera.center.Clone ().Offset (defaultDir, distance);
|
||||
|
||||
let newCamera = oldCamera.Clone ();
|
||||
if (this.direction === OV.Direction.Y) {
|
||||
if (this.direction === OV.Direction.X) {
|
||||
newCamera.up = new OV.Coord3D (1.0, 0.0, 0.0);
|
||||
newCamera.eye = newEye;
|
||||
} if (this.direction === OV.Direction.Y) {
|
||||
newCamera.up = new OV.Coord3D (0.0, 1.0, 0.0);
|
||||
newCamera.eye = newEye;
|
||||
} else if (this.direction === OV.Direction.Z) {
|
||||
@ -71,6 +74,64 @@ OV.UpVector = class
|
||||
}
|
||||
};
|
||||
|
||||
OV.ViewerGeometry = class
|
||||
{
|
||||
constructor (scene)
|
||||
{
|
||||
this.scene = scene;
|
||||
this.modelMeshes = [];
|
||||
}
|
||||
|
||||
AddModelMeshes (meshes)
|
||||
{
|
||||
for (let i = 0; i < meshes.length; i++) {
|
||||
let mesh = meshes[i];
|
||||
this.modelMeshes.push (mesh);
|
||||
this.scene.add (mesh);
|
||||
}
|
||||
}
|
||||
|
||||
GetModelMeshes ()
|
||||
{
|
||||
return this.modelMeshes;
|
||||
}
|
||||
|
||||
ClearModelMeshes ()
|
||||
{
|
||||
for (let i = 0; i < this.modelMeshes.length; i++) {
|
||||
let mesh = this.modelMeshes[i];
|
||||
mesh.geometry.dispose ();
|
||||
this.scene.remove (mesh);
|
||||
}
|
||||
this.modelMeshes = [];
|
||||
}
|
||||
|
||||
EnumerateModelMeshes (enumerator)
|
||||
{
|
||||
for (let i = 0; i < this.modelMeshes.length; i++) {
|
||||
let mesh = this.modelMeshes[i];
|
||||
enumerator (mesh);
|
||||
}
|
||||
}
|
||||
|
||||
GetModelMeshUnderMouse (mouseCoords, camera, width, height)
|
||||
{
|
||||
let raycaster = new THREE.Raycaster ();
|
||||
let mousePos = new THREE.Vector2 ();
|
||||
mousePos.x = (mouseCoords.x / width) * 2 - 1;
|
||||
mousePos.y = -(mouseCoords.y / height) * 2 + 1;
|
||||
raycaster.setFromCamera (mousePos, camera);
|
||||
let iSectObjects = raycaster.intersectObjects (this.modelMeshes);
|
||||
for (let i = 0; i < iSectObjects.length; i++) {
|
||||
let iSectObject = iSectObjects[i];
|
||||
if (iSectObject.object.type === 'Mesh' && iSectObject.object.visible) {
|
||||
return iSectObject.object;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
OV.Viewer = class
|
||||
{
|
||||
constructor ()
|
||||
@ -78,6 +139,7 @@ OV.Viewer = class
|
||||
this.canvas = null;
|
||||
this.renderer = null;
|
||||
this.scene = null;
|
||||
this.geometry = null;
|
||||
this.camera = null;
|
||||
this.light = null;
|
||||
this.navigation = null;
|
||||
@ -101,10 +163,14 @@ OV.Viewer = class
|
||||
};
|
||||
|
||||
this.renderer = new THREE.WebGLRenderer (parameters);
|
||||
if (window.devicePixelRatio) {
|
||||
this.renderer.setPixelRatio (window.devicePixelRatio);
|
||||
}
|
||||
this.renderer.setClearColor ('#ffffff', 1.0);
|
||||
this.renderer.setSize (this.canvas.width, this.canvas.height);
|
||||
|
||||
this.scene = new THREE.Scene ();
|
||||
this.geometry = new OV.ViewerGeometry (this.scene);
|
||||
|
||||
this.InitCamera ();
|
||||
this.InitLights ();
|
||||
@ -136,6 +202,9 @@ OV.Viewer = class
|
||||
|
||||
ResizeRenderer (width, height)
|
||||
{
|
||||
if (window.devicePixelRatio) {
|
||||
this.renderer.setPixelRatio (window.devicePixelRatio);
|
||||
}
|
||||
this.camera.aspect = width / height;
|
||||
this.camera.updateProjectionMatrix ();
|
||||
this.renderer.setSize (width, height);
|
||||
@ -227,22 +296,19 @@ OV.Viewer = class
|
||||
|
||||
AddMeshes (meshes)
|
||||
{
|
||||
for (let i = 0; i < meshes.length; i++) {
|
||||
let mesh = meshes[i];
|
||||
this.scene.add (mesh);
|
||||
}
|
||||
this.geometry.AddModelMeshes (meshes);
|
||||
this.Render ();
|
||||
}
|
||||
|
||||
Clear ()
|
||||
{
|
||||
this.ClearMeshes ();
|
||||
this.geometry.ClearModelMeshes ();
|
||||
this.Render ();
|
||||
}
|
||||
|
||||
SetMeshesVisibility (isVisible)
|
||||
{
|
||||
this.EnumerateMeshes (function (mesh) {
|
||||
this.geometry.EnumerateModelMeshes (function (mesh) {
|
||||
let visible = isVisible (mesh.userData);
|
||||
if (mesh.visible !== visible) {
|
||||
mesh.visible = visible;
|
||||
@ -262,7 +328,7 @@ OV.Viewer = class
|
||||
return highlightMaterials;
|
||||
}
|
||||
|
||||
this.EnumerateMeshes (function (mesh) {
|
||||
this.geometry.EnumerateModelMeshes (function (mesh) {
|
||||
let highlighted = isHighlighted (mesh.userData);
|
||||
if (highlighted) {
|
||||
if (mesh.userData.threeMaterials === null) {
|
||||
@ -279,28 +345,20 @@ OV.Viewer = class
|
||||
this.Render ();
|
||||
}
|
||||
|
||||
GetMeshUnderMouse (mouseCoords)
|
||||
GetMeshUserDataUnderMouse (mouseCoords)
|
||||
{
|
||||
let raycaster = new THREE.Raycaster ();
|
||||
let mousePos = new THREE.Vector2 ();
|
||||
mousePos.x = (mouseCoords.x / this.canvas.width) * 2 - 1;
|
||||
mousePos.y = -(mouseCoords.y / this.canvas.height) * 2 + 1;
|
||||
raycaster.setFromCamera (mousePos, this.camera);
|
||||
let iSectObjects = raycaster.intersectObjects (this.scene.children);
|
||||
for (let i = 0; i < iSectObjects.length; i++) {
|
||||
let iSectObject = iSectObjects[i];
|
||||
if (iSectObject.object.type === 'Mesh' && iSectObject.object.visible) {
|
||||
return iSectObject.object.userData;
|
||||
}
|
||||
let mesh = this.geometry.GetModelMeshUnderMouse (mouseCoords, this.camera, this.canvas.width, this.canvas.height);
|
||||
if (mesh === null) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
return mesh.userData;
|
||||
}
|
||||
|
||||
GetBoundingBox (needToProcess)
|
||||
{
|
||||
let hasMesh = false;
|
||||
let boundingBox = new THREE.Box3 ();
|
||||
this.EnumerateMeshes (function (mesh) {
|
||||
this.geometry.EnumerateModelMeshes (function (mesh) {
|
||||
if (needToProcess (mesh.userData)) {
|
||||
boundingBox.union (new THREE.Box3 ().setFromObject (mesh));
|
||||
hasMesh = true;
|
||||
@ -327,31 +385,11 @@ OV.Viewer = class
|
||||
|
||||
EnumerateMeshesUserData (enumerator)
|
||||
{
|
||||
this.EnumerateMeshes (function (mesh) {
|
||||
this.geometry.EnumerateModelMeshes (function (mesh) {
|
||||
enumerator (mesh.userData);
|
||||
});
|
||||
}
|
||||
|
||||
EnumerateMeshes (enumerator)
|
||||
{
|
||||
this.scene.traverse (function (object) {
|
||||
if (object.isMesh) {
|
||||
enumerator (object);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ClearMeshes ()
|
||||
{
|
||||
for (let i = this.scene.children.length - 1; i >= 0; i--) {
|
||||
let object = this.scene.children[i];
|
||||
if (object.isMesh) {
|
||||
object.geometry.dispose ();
|
||||
this.scene.remove (object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InitCamera ()
|
||||
{
|
||||
this.camera = new THREE.PerspectiveCamera (45.0, this.canvas.width / this.canvas.height, 0.1, 1000.0);
|
||||
@ -378,22 +416,29 @@ OV.Viewer = class
|
||||
this.scene.add (this.light);
|
||||
}
|
||||
|
||||
GetImageSize ()
|
||||
{
|
||||
let originalSize = new THREE.Vector2 ();
|
||||
this.renderer.getSize (originalSize);
|
||||
return {
|
||||
width : parseInt (originalSize.x, 10),
|
||||
height : parseInt (originalSize.y, 10)
|
||||
};
|
||||
}
|
||||
|
||||
GetImageAsDataUrl (width, height)
|
||||
{
|
||||
let originalSize = null;
|
||||
if (width && height) {
|
||||
originalSize = new THREE.Vector2 ();
|
||||
this.renderer.getSize (originalSize);
|
||||
this.ResizeRenderer (width, height);
|
||||
let originalSize = this.GetImageSize ();
|
||||
let renderWidth = width;
|
||||
let renderHeight = height;
|
||||
if (window.devicePixelRatio) {
|
||||
renderWidth /= window.devicePixelRatio;
|
||||
renderHeight /= window.devicePixelRatio;
|
||||
}
|
||||
this.ResizeRenderer (renderWidth, renderHeight);
|
||||
this.Render ();
|
||||
let url = this.renderer.domElement.toDataURL ();
|
||||
if (originalSize !== null) {
|
||||
this.ResizeRenderer (
|
||||
parseInt (originalSize.x, 10),
|
||||
parseInt (originalSize.y, 10)
|
||||
);
|
||||
}
|
||||
this.ResizeRenderer (originalSize.width, originalSize.height);
|
||||
return url;
|
||||
}
|
||||
};
|
||||
|
||||
@ -62,308 +62,340 @@ function CreateTestModel ()
|
||||
return model;
|
||||
}
|
||||
|
||||
describe ('Exporter', function () {
|
||||
it ('Obj Export', function () {
|
||||
let model = CreateTestModel ();
|
||||
let exporter = new OV.Exporter ();
|
||||
|
||||
let result = exporter.Export (model, OV.FileFormat.Text, 'obj');
|
||||
assert.strictEqual (result.length, 5);
|
||||
|
||||
let mtlFile = result[0];
|
||||
assert.strictEqual (mtlFile.GetName (), 'model.mtl');
|
||||
assert.strictEqual (mtlFile.GetContent (),
|
||||
[
|
||||
'# exported by https://3dviewer.net',
|
||||
'newmtl TestMaterial1',
|
||||
'Ka 0 0 0',
|
||||
'Kd 1 0 0',
|
||||
'Ks 0.2 0.2 0.2',
|
||||
'Ns 0',
|
||||
'd 1',
|
||||
'map_Kd texture1.png',
|
||||
'map_Ks texture2.png',
|
||||
'bump texture3.png',
|
||||
'newmtl TestMaterial2',
|
||||
'Ka 0 0 0',
|
||||
'Kd 0 1 0',
|
||||
'Ks 0.2 0.2 0.2',
|
||||
'Ns 0',
|
||||
'd 1',
|
||||
''
|
||||
].join ('\n'));
|
||||
let objFile = result[1];
|
||||
assert.strictEqual (objFile.GetName (), 'model.obj');
|
||||
assert.strictEqual (objFile.GetContent (),
|
||||
[
|
||||
'# exported by https://3dviewer.net',
|
||||
'mtllib model.mtl',
|
||||
'g TestMesh1',
|
||||
'v 0 0 1',
|
||||
'v 1 0 1',
|
||||
'v 0 1 1',
|
||||
'vn 0 0 1',
|
||||
'usemtl TestMaterial1',
|
||||
'f 1//1 2//1 3//1',
|
||||
'g TestMesh2',
|
||||
'v 0 0 0',
|
||||
'v 1 0 0',
|
||||
'v 0 1 0',
|
||||
'v -1 0 0',
|
||||
'v 0 0 1',
|
||||
'vn 0 0 1',
|
||||
'vn 0 0 1',
|
||||
'vn -1 0 0',
|
||||
'f 4//2 5//2 6//2',
|
||||
'usemtl TestMaterial2',
|
||||
'f 4//3 6//3 7//3',
|
||||
'f 4//4 8//4 6//4',
|
||||
''
|
||||
].join ('\n'));
|
||||
|
||||
let textureFile1 = result[2];
|
||||
assert.strictEqual (textureFile1.GetName (), 'texture1.png');
|
||||
assert.strictEqual (textureFile1.GetContent ().byteLength, 1);
|
||||
|
||||
let textureFile2 = result[3];
|
||||
assert.strictEqual (textureFile2.GetName (), 'texture2.png');
|
||||
assert.strictEqual (textureFile2.GetContent ().byteLength, 2);
|
||||
|
||||
let textureFile3 = result[4];
|
||||
assert.strictEqual (textureFile3.GetName (), 'texture3.png');
|
||||
assert.strictEqual (textureFile3.GetContent ().byteLength, 3);
|
||||
});
|
||||
|
||||
it ('Stl Export', function () {
|
||||
let model = CreateTestModel ();
|
||||
let exporter = new OV.Exporter ();
|
||||
|
||||
let result = exporter.Export (model, OV.FileFormat.Text, 'stl');
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let stlFile = result[0];
|
||||
assert.strictEqual (stlFile.GetName (), 'model.stl');
|
||||
assert.strictEqual (stlFile.GetContent (),
|
||||
[
|
||||
'solid Model',
|
||||
'facet normal 0 0 1',
|
||||
' outer loop',
|
||||
' vertex 0 0 1',
|
||||
' vertex 1 0 1',
|
||||
' vertex 0 1 1',
|
||||
' endloop',
|
||||
'endfacet',
|
||||
'facet normal 0 0 1',
|
||||
' outer loop',
|
||||
' vertex 0 0 0',
|
||||
' vertex 1 0 0',
|
||||
' vertex 0 1 0',
|
||||
' endloop',
|
||||
'endfacet',
|
||||
'facet normal 0 0 1',
|
||||
' outer loop',
|
||||
' vertex 0 0 0',
|
||||
' vertex 0 1 0',
|
||||
' vertex -1 0 0',
|
||||
' endloop',
|
||||
'endfacet',
|
||||
'facet normal -1 0 0',
|
||||
' outer loop',
|
||||
' vertex 0 0 0',
|
||||
' vertex 0 0 1',
|
||||
' vertex 0 1 0',
|
||||
' endloop',
|
||||
'endfacet',
|
||||
'endsolid Model',
|
||||
''
|
||||
].join ('\n'));
|
||||
});
|
||||
|
||||
it ('Stl Binary Export', function () {
|
||||
let model = CreateTestModel ();
|
||||
let exporter = new OV.Exporter ();
|
||||
|
||||
let result = exporter.Export (model, OV.FileFormat.Binary, 'stl');
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let stlFile = result[0];
|
||||
assert.strictEqual (stlFile.GetName (), 'model.stl');
|
||||
assert.strictEqual (stlFile.GetContent ().byteLength, 284);
|
||||
|
||||
let contentBuffer = stlFile.GetContent ();
|
||||
let importer = new OV.ImporterStl ();
|
||||
importer.Import (contentBuffer, 'stl', {
|
||||
getDefaultMaterial () {
|
||||
return new OV.Material ();
|
||||
}
|
||||
});
|
||||
let importedModel = importer.GetModel ();
|
||||
assert.strictEqual (importedModel.VertexCount (), 12);
|
||||
assert.strictEqual (importedModel.TriangleCount (), 4);
|
||||
});
|
||||
|
||||
it ('Off Export', function () {
|
||||
let model = CreateTestModel ();
|
||||
let exporter = new OV.Exporter ();
|
||||
|
||||
let result = exporter.Export (model, OV.FileFormat.Text, 'off');
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let offFile = result[0];
|
||||
assert.strictEqual (offFile.GetName (), 'model.off');
|
||||
assert.strictEqual (offFile.GetContent (),
|
||||
[
|
||||
'OFF',
|
||||
'8 4 0',
|
||||
'0 0 1',
|
||||
'1 0 1',
|
||||
'0 1 1',
|
||||
'0 0 0',
|
||||
'1 0 0',
|
||||
'0 1 0',
|
||||
'-1 0 0',
|
||||
'0 0 1',
|
||||
'3 0 1 2',
|
||||
'3 3 4 5',
|
||||
'3 3 5 6',
|
||||
'3 3 7 5',
|
||||
''
|
||||
].join ('\n'));
|
||||
});
|
||||
|
||||
it ('Ply Export', function () {
|
||||
let model = CreateTestModel ();
|
||||
let exporter = new OV.Exporter ();
|
||||
|
||||
let result = exporter.Export (model, OV.FileFormat.Text, 'ply');
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let plyFile = result[0];
|
||||
assert.strictEqual (plyFile.GetName (), 'model.ply');
|
||||
assert.strictEqual (plyFile.GetContent (),
|
||||
[
|
||||
'ply',
|
||||
'format ascii 1.0',
|
||||
'element vertex 8',
|
||||
'property float x',
|
||||
'property float y',
|
||||
'property float z',
|
||||
'element face 4',
|
||||
'property list uchar int vertex_index',
|
||||
'end_header',
|
||||
'0 0 1',
|
||||
'1 0 1',
|
||||
'0 1 1',
|
||||
'0 0 0',
|
||||
'1 0 0',
|
||||
'0 1 0',
|
||||
'-1 0 0',
|
||||
'0 0 1',
|
||||
'3 0 1 2',
|
||||
'3 3 4 5',
|
||||
'3 3 5 6',
|
||||
'3 3 7 5',
|
||||
''
|
||||
].join ('\n'));
|
||||
});
|
||||
|
||||
it ('Ply Binary Export', function () {
|
||||
let model = CreateTestModel ();
|
||||
let exporter = new OV.Exporter ();
|
||||
|
||||
let result = exporter.Export (model, OV.FileFormat.Binary, 'ply');
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let plyFile = result[0];
|
||||
assert.strictEqual (plyFile.GetName (), 'model.ply');
|
||||
assert.strictEqual (plyFile.GetContent ().byteLength, 315);
|
||||
|
||||
let contentBuffer = plyFile.GetContent ();
|
||||
let importer = new OV.ImporterPly ();
|
||||
importer.Import (contentBuffer, 'ply', {
|
||||
getDefaultMaterial () {
|
||||
return new OV.Material ();
|
||||
}
|
||||
});
|
||||
let importedModel = importer.GetModel ();
|
||||
assert.strictEqual (importedModel.VertexCount (), 8);
|
||||
assert.strictEqual (importedModel.TriangleCount (), 4);
|
||||
});
|
||||
|
||||
it ('Gltf Ascii Export', function () {
|
||||
let model = CreateTestModel ();
|
||||
let exporter = new OV.Exporter ();
|
||||
|
||||
let result = exporter.Export (model, OV.FileFormat.Text, 'gltf');
|
||||
assert.strictEqual (result.length, 3);
|
||||
|
||||
let gltfFile = result[0];
|
||||
let binFile = result[1];
|
||||
let textureFile = result[2];
|
||||
assert.strictEqual (gltfFile.GetName (), 'model.gltf');
|
||||
assert.strictEqual (binFile.GetName (), 'model.bin');
|
||||
|
||||
assert.strictEqual (textureFile.GetName (), 'texture1.png');
|
||||
assert.strictEqual (textureFile.GetContent ().byteLength, 1);
|
||||
|
||||
let contentBuffer = gltfFile.GetContent ();
|
||||
let importer = new OV.ImporterGltf ();
|
||||
importer.Import (contentBuffer, 'gltf', {
|
||||
getDefaultMaterial () {
|
||||
return new OV.Material ();
|
||||
},
|
||||
getFileBuffer (filePath) {
|
||||
if (filePath == 'model.bin') {
|
||||
return binFile.GetContent ();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getTextureBuffer (filePath) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
let importedModel = importer.GetModel ();
|
||||
assert (OV.CheckModel (importedModel));
|
||||
assert.strictEqual (importedModel.MaterialCount (), 2);
|
||||
assert.strictEqual (importedModel.MeshCount (), 2);
|
||||
assert.strictEqual (importedModel.GetMesh (0).GetName (), 'TestMesh1');
|
||||
assert.strictEqual (importedModel.GetMesh (1).GetName (), 'TestMesh2');
|
||||
assert.strictEqual (importedModel.VertexCount (), 12);
|
||||
assert.strictEqual (importedModel.TriangleCount (), 4);
|
||||
});
|
||||
|
||||
it ('Gltf Binary Export', function () {
|
||||
let model = CreateTestModel ();
|
||||
function Export (model, format, extension, onReady)
|
||||
{
|
||||
let exporter = new OV.Exporter ();
|
||||
|
||||
let result = exporter.Export (model, OV.FileFormat.Binary, 'glb');
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let glbFile = result[0];
|
||||
assert.strictEqual (glbFile.GetName (), 'model.glb');
|
||||
|
||||
let contentBuffer = glbFile.GetContent ();
|
||||
let importer = new OV.ImporterGltf ();
|
||||
importer.Import (contentBuffer, 'glb', {
|
||||
getDefaultMaterial () {
|
||||
return new OV.Material ();
|
||||
},
|
||||
getFileBuffer (filePath) {
|
||||
return null;
|
||||
},
|
||||
getTextureBuffer (filePath) {
|
||||
return null;
|
||||
exporter.Export (model, format, extension, {
|
||||
onSuccess : function (files) {
|
||||
onReady (files);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let importedModel = importer.GetModel ();
|
||||
assert (OV.CheckModel (importedModel));
|
||||
assert.strictEqual (importedModel.MaterialCount (), 2);
|
||||
assert.strictEqual (importedModel.MeshCount (), 2);
|
||||
assert.strictEqual (importedModel.GetMesh (0).GetName (), 'TestMesh1');
|
||||
assert.strictEqual (importedModel.GetMesh (1).GetName (), 'TestMesh2');
|
||||
assert.strictEqual (importedModel.VertexCount (), 12);
|
||||
assert.strictEqual (importedModel.TriangleCount (), 4);
|
||||
});
|
||||
describe ('Exporter', function () {
|
||||
it ('Exporter Error', function (done) {
|
||||
let model = CreateTestModel ();
|
||||
let exporter = new OV.Exporter ();
|
||||
exporter.Export (model, OV.FileFormat.Text, 'ext', {
|
||||
onError : function () {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it ('Obj Export', function (done) {
|
||||
let model = CreateTestModel ();
|
||||
Export (model, OV.FileFormat.Text, 'obj', function (result) {
|
||||
assert.strictEqual (result.length, 5);
|
||||
|
||||
let mtlFile = result[0];
|
||||
assert.strictEqual (mtlFile.GetName (), 'model.mtl');
|
||||
assert.strictEqual (mtlFile.GetContent (),
|
||||
[
|
||||
'# exported by https://3dviewer.net',
|
||||
'newmtl TestMaterial1',
|
||||
'Ka 0 0 0',
|
||||
'Kd 1 0 0',
|
||||
'Ks 0.2 0.2 0.2',
|
||||
'Ns 0',
|
||||
'd 1',
|
||||
'map_Kd texture1.png',
|
||||
'map_Ks texture2.png',
|
||||
'bump texture3.png',
|
||||
'newmtl TestMaterial2',
|
||||
'Ka 0 0 0',
|
||||
'Kd 0 1 0',
|
||||
'Ks 0.2 0.2 0.2',
|
||||
'Ns 0',
|
||||
'd 1',
|
||||
''
|
||||
].join ('\n'));
|
||||
let objFile = result[1];
|
||||
assert.strictEqual (objFile.GetName (), 'model.obj');
|
||||
assert.strictEqual (objFile.GetContent (),
|
||||
[
|
||||
'# exported by https://3dviewer.net',
|
||||
'mtllib model.mtl',
|
||||
'g TestMesh1',
|
||||
'v 0 0 1',
|
||||
'v 1 0 1',
|
||||
'v 0 1 1',
|
||||
'vn 0 0 1',
|
||||
'usemtl TestMaterial1',
|
||||
'f 1//1 2//1 3//1',
|
||||
'g TestMesh2',
|
||||
'v 0 0 0',
|
||||
'v 1 0 0',
|
||||
'v 0 1 0',
|
||||
'v -1 0 0',
|
||||
'v 0 0 1',
|
||||
'vn 0 0 1',
|
||||
'vn 0 0 1',
|
||||
'vn -1 0 0',
|
||||
'f 4//2 5//2 6//2',
|
||||
'usemtl TestMaterial2',
|
||||
'f 4//3 6//3 7//3',
|
||||
'f 4//4 8//4 6//4',
|
||||
''
|
||||
].join ('\n'));
|
||||
|
||||
let textureFile1 = result[2];
|
||||
assert.strictEqual (textureFile1.GetName (), 'texture1.png');
|
||||
assert.strictEqual (textureFile1.GetContent ().byteLength, 1);
|
||||
|
||||
let textureFile2 = result[3];
|
||||
assert.strictEqual (textureFile2.GetName (), 'texture2.png');
|
||||
assert.strictEqual (textureFile2.GetContent ().byteLength, 2);
|
||||
|
||||
let textureFile3 = result[4];
|
||||
assert.strictEqual (textureFile3.GetName (), 'texture3.png');
|
||||
assert.strictEqual (textureFile3.GetContent ().byteLength, 3);
|
||||
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('Stl Export', function (done) {
|
||||
let model = CreateTestModel ();
|
||||
Export (model, OV.FileFormat.Text, 'stl', function (result) {
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let stlFile = result[0];
|
||||
assert.strictEqual (stlFile.GetName (), 'model.stl');
|
||||
assert.strictEqual (stlFile.GetContent (),
|
||||
[
|
||||
'solid Model',
|
||||
'facet normal 0 0 1',
|
||||
' outer loop',
|
||||
' vertex 0 0 1',
|
||||
' vertex 1 0 1',
|
||||
' vertex 0 1 1',
|
||||
' endloop',
|
||||
'endfacet',
|
||||
'facet normal 0 0 1',
|
||||
' outer loop',
|
||||
' vertex 0 0 0',
|
||||
' vertex 1 0 0',
|
||||
' vertex 0 1 0',
|
||||
' endloop',
|
||||
'endfacet',
|
||||
'facet normal 0 0 1',
|
||||
' outer loop',
|
||||
' vertex 0 0 0',
|
||||
' vertex 0 1 0',
|
||||
' vertex -1 0 0',
|
||||
' endloop',
|
||||
'endfacet',
|
||||
'facet normal -1 0 0',
|
||||
' outer loop',
|
||||
' vertex 0 0 0',
|
||||
' vertex 0 0 1',
|
||||
' vertex 0 1 0',
|
||||
' endloop',
|
||||
'endfacet',
|
||||
'endsolid Model',
|
||||
''
|
||||
].join ('\n'));
|
||||
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('Stl Binary Export', function (done) {
|
||||
let model = CreateTestModel ();
|
||||
Export (model, OV.FileFormat.Binary, 'stl', function (result) {
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let stlFile = result[0];
|
||||
assert.strictEqual (stlFile.GetName (), 'model.stl');
|
||||
assert.strictEqual (stlFile.GetContent ().byteLength, 284);
|
||||
|
||||
let contentBuffer = stlFile.GetContent ();
|
||||
let importer = new OV.ImporterStl ();
|
||||
importer.Import (contentBuffer, 'stl', {
|
||||
getDefaultMaterial () {
|
||||
return new OV.Material ();
|
||||
},
|
||||
onSuccess () {
|
||||
let importedModel = importer.GetModel ();
|
||||
assert.strictEqual (importedModel.VertexCount (), 12);
|
||||
assert.strictEqual (importedModel.TriangleCount (), 4);
|
||||
done ();
|
||||
}
|
||||
});
|
||||
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('Off Export', function (done) {
|
||||
let model = CreateTestModel ();
|
||||
Export (model, OV.FileFormat.Text, 'off', function (result) {
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let offFile = result[0];
|
||||
assert.strictEqual (offFile.GetName (), 'model.off');
|
||||
assert.strictEqual (offFile.GetContent (),
|
||||
[
|
||||
'OFF',
|
||||
'8 4 0',
|
||||
'0 0 1',
|
||||
'1 0 1',
|
||||
'0 1 1',
|
||||
'0 0 0',
|
||||
'1 0 0',
|
||||
'0 1 0',
|
||||
'-1 0 0',
|
||||
'0 0 1',
|
||||
'3 0 1 2',
|
||||
'3 3 4 5',
|
||||
'3 3 5 6',
|
||||
'3 3 7 5',
|
||||
''
|
||||
].join ('\n'));
|
||||
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('Ply Export', function (done) {
|
||||
let model = CreateTestModel ();
|
||||
Export (model, OV.FileFormat.Text, 'ply', function (result) {
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let plyFile = result[0];
|
||||
assert.strictEqual (plyFile.GetName (), 'model.ply');
|
||||
assert.strictEqual (plyFile.GetContent (),
|
||||
[
|
||||
'ply',
|
||||
'format ascii 1.0',
|
||||
'element vertex 8',
|
||||
'property float x',
|
||||
'property float y',
|
||||
'property float z',
|
||||
'element face 4',
|
||||
'property list uchar int vertex_index',
|
||||
'end_header',
|
||||
'0 0 1',
|
||||
'1 0 1',
|
||||
'0 1 1',
|
||||
'0 0 0',
|
||||
'1 0 0',
|
||||
'0 1 0',
|
||||
'-1 0 0',
|
||||
'0 0 1',
|
||||
'3 0 1 2',
|
||||
'3 3 4 5',
|
||||
'3 3 5 6',
|
||||
'3 3 7 5',
|
||||
''
|
||||
].join ('\n'));
|
||||
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('Ply Binary Export', function (done) {
|
||||
let model = CreateTestModel ();
|
||||
Export (model, OV.FileFormat.Binary, 'ply', function (result) {
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let plyFile = result[0];
|
||||
assert.strictEqual (plyFile.GetName (), 'model.ply');
|
||||
assert.strictEqual (plyFile.GetContent ().byteLength, 315);
|
||||
|
||||
let contentBuffer = plyFile.GetContent ();
|
||||
let importer = new OV.ImporterPly ();
|
||||
importer.Import (contentBuffer, 'ply', {
|
||||
getDefaultMaterial () {
|
||||
return new OV.Material ();
|
||||
},
|
||||
onSuccess () {
|
||||
let importedModel = importer.GetModel ();
|
||||
assert.strictEqual (importedModel.VertexCount (), 8);
|
||||
assert.strictEqual (importedModel.TriangleCount (), 4);
|
||||
done ();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it ('Gltf Ascii Export', function (done) {
|
||||
let model = CreateTestModel ();
|
||||
Export (model, OV.FileFormat.Text, 'gltf', function (result) {
|
||||
assert.strictEqual (result.length, 3);
|
||||
|
||||
let gltfFile = result[0];
|
||||
let binFile = result[1];
|
||||
let textureFile = result[2];
|
||||
assert.strictEqual (gltfFile.GetName (), 'model.gltf');
|
||||
assert.strictEqual (binFile.GetName (), 'model.bin');
|
||||
|
||||
assert.strictEqual (textureFile.GetName (), 'texture1.png');
|
||||
assert.strictEqual (textureFile.GetContent ().byteLength, 1);
|
||||
|
||||
let contentBuffer = gltfFile.GetContent ();
|
||||
let importer = new OV.ImporterGltf ();
|
||||
importer.Import (contentBuffer, 'gltf', {
|
||||
getDefaultMaterial () {
|
||||
return new OV.Material ();
|
||||
},
|
||||
getFileBuffer (filePath) {
|
||||
if (filePath == 'model.bin') {
|
||||
return binFile.GetContent ();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getTextureBuffer (filePath) {
|
||||
return null;
|
||||
},
|
||||
onSuccess () {
|
||||
let importedModel = importer.GetModel ();
|
||||
assert (OV.CheckModel (importedModel));
|
||||
assert.strictEqual (importedModel.MaterialCount (), 2);
|
||||
assert.strictEqual (importedModel.MeshCount (), 2);
|
||||
assert.strictEqual (importedModel.GetMesh (0).GetName (), 'TestMesh1');
|
||||
assert.strictEqual (importedModel.GetMesh (1).GetName (), 'TestMesh2');
|
||||
assert.strictEqual (importedModel.VertexCount (), 12);
|
||||
assert.strictEqual (importedModel.TriangleCount (), 4);
|
||||
done ();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it ('Gltf Binary Export', function (done) {
|
||||
let model = CreateTestModel ();
|
||||
Export (model, OV.FileFormat.Binary, 'glb', function (result) {
|
||||
assert.strictEqual (result.length, 1);
|
||||
|
||||
let glbFile = result[0];
|
||||
assert.strictEqual (glbFile.GetName (), 'model.glb');
|
||||
|
||||
let contentBuffer = glbFile.GetContent ();
|
||||
let importer = new OV.ImporterGltf ();
|
||||
importer.Import (contentBuffer, 'glb', {
|
||||
getDefaultMaterial () {
|
||||
return new OV.Material ();
|
||||
},
|
||||
getFileBuffer (filePath) {
|
||||
return null;
|
||||
},
|
||||
getTextureBuffer (filePath) {
|
||||
return null;
|
||||
},
|
||||
onSuccess () {
|
||||
let importedModel = importer.GetModel ();
|
||||
assert (OV.CheckModel (importedModel));
|
||||
assert.strictEqual (importedModel.MaterialCount (), 2);
|
||||
assert.strictEqual (importedModel.MeshCount (), 2);
|
||||
assert.strictEqual (importedModel.GetMesh (0).GetName (), 'TestMesh1');
|
||||
assert.strictEqual (importedModel.GetMesh (1).GetName (), 'TestMesh2');
|
||||
assert.strictEqual (importedModel.VertexCount (), 12);
|
||||
assert.strictEqual (importedModel.TriangleCount (), 4);
|
||||
done ();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -3,159 +3,167 @@ var testFiles = require ('../utils/testfiles.js');
|
||||
var testUtils = require ('../utils/testutils.js');
|
||||
|
||||
describe ('3ds Importer', function() {
|
||||
it ('cube_with_materials.obj', function () {
|
||||
var model = testFiles.Import3dsFile ('cube_with_materials.3ds');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'tex' },
|
||||
{ name : 'red' },
|
||||
{ name : 'green' },
|
||||
{ name : 'blue' },
|
||||
{ name : 'white' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
it ('cube_with_materials.3ds', function (done) {
|
||||
testFiles.Import3dsFile ('cube_with_materials.3ds', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'tex' },
|
||||
{ name : 'red' },
|
||||
{ name : 'green' },
|
||||
{ name : 'blue' },
|
||||
{ name : 'white' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('cube_with_texture_transformations.3ds', function () {
|
||||
var model = testFiles.Import3dsFile ('cube_with_texture_transformations.3ds');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'tex' },
|
||||
{ name : 'red' },
|
||||
{ name : 'green' },
|
||||
{ name : 'blue' },
|
||||
{ name : 'white' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
it ('cube_with_texture_transformations.3ds', function (done) {
|
||||
testFiles.Import3dsFile ('cube_with_texture_transformations.3ds', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'tex' },
|
||||
{ name : 'red' },
|
||||
{ name : 'green' },
|
||||
{ name : 'blue' },
|
||||
{ name : 'white' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('cube_two_instances.3ds', function () {
|
||||
var model = testFiles.Import3dsFile ('cube_two_instances.3ds');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'tex' },
|
||||
{ name : 'red' },
|
||||
{ name : 'green' },
|
||||
{ name : 'blue' },
|
||||
{ name : 'white' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [2, 0, 0],
|
||||
max : [3, 1, 1]
|
||||
}
|
||||
}
|
||||
]
|
||||
it ('cube_two_instances.3ds', function (done) {
|
||||
testFiles.Import3dsFile ('cube_two_instances.3ds', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'tex' },
|
||||
{ name : 'red' },
|
||||
{ name : 'green' },
|
||||
{ name : 'blue' },
|
||||
{ name : 'white' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [2, 0, 0],
|
||||
max : [3, 1, 1]
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('cube_four_instances.3ds', function () {
|
||||
var model = testFiles.Import3dsFile ('cube_four_instances.3ds');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'tex' },
|
||||
{ name : 'red' },
|
||||
{ name : 'green' },
|
||||
{ name : 'blue' },
|
||||
{ name : 'white' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [2, 0, 0],
|
||||
max : [3, 1, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [2, 2, 0],
|
||||
max : [3, 3, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 2, 0],
|
||||
max : [1, 3, 1]
|
||||
}
|
||||
}
|
||||
]
|
||||
it ('cube_four_instances.3ds', function (done) {
|
||||
testFiles.Import3dsFile ('cube_four_instances.3ds', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'tex' },
|
||||
{ name : 'red' },
|
||||
{ name : 'green' },
|
||||
{ name : 'blue' },
|
||||
{ name : 'white' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [2, 0, 0],
|
||||
max : [3, 1, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [2, 2, 0],
|
||||
max : [3, 3, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
name : 'cube',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 8,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 2, 0],
|
||||
max : [1, 3, 1]
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -6,10 +6,10 @@ function ImportFilesWithImporter (importer, files, callbacks)
|
||||
importer.LoadFilesFromFileObjects (files, function () {
|
||||
let settings = new OV.ImportSettings ();
|
||||
importer.Import (settings, {
|
||||
success : function (importResult) {
|
||||
onSuccess : function (importResult) {
|
||||
callbacks.success (importer, importResult);
|
||||
},
|
||||
error : function (importError) {
|
||||
onError : function (importError) {
|
||||
callbacks.error (importer, importError);
|
||||
}
|
||||
});
|
||||
@ -23,7 +23,7 @@ function ImportFiles (files, callbacks)
|
||||
}
|
||||
|
||||
describe ('Importer Test', function () {
|
||||
it ('Empty File List', function () {
|
||||
it ('Empty File List', function (done) {
|
||||
let files = [];
|
||||
ImportFiles (files, {
|
||||
success : function (importer, importResult) {
|
||||
@ -31,11 +31,12 @@ describe ('Importer Test', function () {
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.strictEqual (importError.code, OV.ImportErrorCode.NoImportableFile);
|
||||
done ();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it ('Not existing file', function () {
|
||||
it ('Not existing file', function (done) {
|
||||
let files = [
|
||||
new FileObject ('obj', 'missing.obj')
|
||||
];
|
||||
@ -45,11 +46,12 @@ describe ('Importer Test', function () {
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.strictEqual (importError.code, OV.ImportErrorCode.NoImportableFile);
|
||||
done ();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it ('Not imprtable file', function () {
|
||||
it ('Not imprtable file', function (done) {
|
||||
let files = [
|
||||
new FileObject ('', 'wrong.ext')
|
||||
];
|
||||
@ -59,11 +61,12 @@ describe ('Importer Test', function () {
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.strictEqual (importError.code, OV.ImportErrorCode.NoImportableFile);
|
||||
done ();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it ('Wrong file', function () {
|
||||
it ('Wrong file', function (done) {
|
||||
let files = [
|
||||
new FileObject ('3ds', 'wrong.3ds')
|
||||
];
|
||||
@ -73,11 +76,12 @@ describe ('Importer Test', function () {
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.strictEqual (importError.code, OV.ImportErrorCode.ImportFailed);
|
||||
done ();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it ('Single file', function () {
|
||||
it ('Single file', function (done) {
|
||||
let files = [
|
||||
new FileObject ('obj', 'single_triangle.obj')
|
||||
];
|
||||
@ -86,6 +90,7 @@ describe ('Importer Test', function () {
|
||||
assert (!OV.IsModelEmpty (importResult.model));
|
||||
assert.deepStrictEqual (importResult.usedFiles, ['single_triangle.obj']);
|
||||
assert.deepStrictEqual (importResult.missingFiles, []);
|
||||
done ();
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.fail ();
|
||||
@ -93,7 +98,7 @@ describe ('Importer Test', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it ('Multiple files', function () {
|
||||
it ('Multiple files', function (done) {
|
||||
let files = [
|
||||
new FileObject ('obj', 'cube_with_materials.obj'),
|
||||
new FileObject ('obj', 'cube_with_materials.mtl'),
|
||||
@ -105,7 +110,8 @@ describe ('Importer Test', function () {
|
||||
success : function (importer, importResult) {
|
||||
assert (!OV.IsModelEmpty (importResult.model));
|
||||
assert.deepStrictEqual (importResult.usedFiles, ['cube_with_materials.obj', 'cube_with_materials.mtl', 'cube_texture.png']);
|
||||
assert.deepStrictEqual (importResult.missingFiles, []);
|
||||
assert.deepStrictEqual (importResult.missingFiles, []);
|
||||
done ();
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.fail ();
|
||||
@ -113,7 +119,7 @@ describe ('Importer Test', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it ('Missing files', function () {
|
||||
it ('Missing files', function (done) {
|
||||
let files = [];
|
||||
files.push (new FileObject ('obj', 'cube_with_materials.obj'));
|
||||
ImportFiles (files, {
|
||||
@ -121,36 +127,38 @@ describe ('Importer Test', function () {
|
||||
assert (!OV.IsModelEmpty (importResult.model));
|
||||
assert.deepStrictEqual (importResult.usedFiles, ['cube_with_materials.obj']);
|
||||
assert.deepStrictEqual (importResult.missingFiles, ['cube_with_materials.mtl']);
|
||||
files.push (new FileObject ('obj', 'cube_with_materials.mtl'));
|
||||
ImportFiles (files, {
|
||||
success : function (importer, importResult) {
|
||||
assert (!OV.IsModelEmpty (importResult.model));
|
||||
assert.deepStrictEqual (importResult.usedFiles, ['cube_with_materials.obj', 'cube_with_materials.mtl']);
|
||||
assert.deepStrictEqual (importResult.missingFiles, ['cube_texture.png']);
|
||||
files.push (new FileObject ('obj', 'cube_texture.png'));
|
||||
ImportFiles (files, {
|
||||
success : function (importer, importResult) {
|
||||
assert (!OV.IsModelEmpty (importResult.model));
|
||||
assert.deepStrictEqual (importResult.usedFiles, ['cube_with_materials.obj', 'cube_with_materials.mtl', 'cube_texture.png']);
|
||||
assert.deepStrictEqual (importResult.missingFiles, []);
|
||||
done ();
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.fail ();
|
||||
}
|
||||
});
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.fail ();
|
||||
}
|
||||
});
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.fail ();
|
||||
}
|
||||
});
|
||||
files.push (new FileObject ('obj', 'cube_with_materials.mtl'));
|
||||
ImportFiles (files, {
|
||||
success : function (importer, importResult) {
|
||||
assert (!OV.IsModelEmpty (importResult.model));
|
||||
assert.deepStrictEqual (importResult.usedFiles, ['cube_with_materials.obj', 'cube_with_materials.mtl']);
|
||||
assert.deepStrictEqual (importResult.missingFiles, ['cube_texture.png']);
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.fail ();
|
||||
}
|
||||
});
|
||||
files.push (new FileObject ('obj', 'cube_texture.png'));
|
||||
ImportFiles (files, {
|
||||
success : function (importer, importResult) {
|
||||
assert (!OV.IsModelEmpty (importResult.model));
|
||||
assert.deepStrictEqual (importResult.usedFiles, ['cube_with_materials.obj', 'cube_with_materials.mtl', 'cube_texture.png']);
|
||||
assert.deepStrictEqual (importResult.missingFiles, []);
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.fail ();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it ('Missing texture multiple times', function () {
|
||||
it ('Missing texture multiple times', function (done) {
|
||||
let files = [
|
||||
new FileObject ('obj', 'two_materials_same_texture.obj'),
|
||||
new FileObject ('obj', 'two_materials_same_texture.mtl'),
|
||||
@ -160,6 +168,7 @@ describe ('Importer Test', function () {
|
||||
assert (!OV.IsModelEmpty (importResult.model));
|
||||
assert.deepStrictEqual (importResult.usedFiles, ['two_materials_same_texture.obj', 'two_materials_same_texture.mtl']);
|
||||
assert.deepStrictEqual (importResult.missingFiles, ['texture.png']);
|
||||
done ();
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.fail ();
|
||||
@ -167,7 +176,7 @@ describe ('Importer Test', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it ('Append Missing files', function () {
|
||||
it ('Append Missing files', function (done) {
|
||||
let theImporter = new OV.Importer ();
|
||||
ImportFilesWithImporter (theImporter, [new FileObject ('obj', 'cube_with_materials.obj')], {
|
||||
success : function (importer, importResult) {
|
||||
@ -184,6 +193,7 @@ describe ('Importer Test', function () {
|
||||
assert (!OV.IsModelEmpty (importResult.model));
|
||||
assert.deepStrictEqual (importResult.usedFiles, ['cube_with_materials.obj', 'cube_with_materials.mtl', 'cube_texture.png']);
|
||||
assert.deepStrictEqual (importResult.missingFiles, []);
|
||||
done ();
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.fail ();
|
||||
@ -201,7 +211,7 @@ describe ('Importer Test', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it ('Reuse importer', function () {
|
||||
it ('Reuse importer', function (done) {
|
||||
let files1 = [
|
||||
new FileObject ('obj', 'cube_with_materials.obj'),
|
||||
new FileObject ('obj', 'cube_with_materials.mtl'),
|
||||
@ -223,6 +233,7 @@ describe ('Importer Test', function () {
|
||||
assert (!OV.IsModelEmpty (importResult.model));
|
||||
assert.deepStrictEqual (importResult.usedFiles, ['single_triangle.obj']);
|
||||
assert.deepStrictEqual (importResult.missingFiles, []);
|
||||
done ();
|
||||
},
|
||||
error : function (importer, importError) {
|
||||
assert.fail ();
|
||||
@ -235,7 +246,7 @@ describe ('Importer Test', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it ('Default color', function () {
|
||||
it ('Default color', function (done) {
|
||||
let files = [
|
||||
new FileObject ('stl', 'single_triangle.stl')
|
||||
];
|
||||
@ -244,14 +255,15 @@ describe ('Importer Test', function () {
|
||||
let settings = new OV.ImportSettings ();
|
||||
settings.defaultColor = new OV.Color (200, 0, 0);
|
||||
theImporter.Import (settings, {
|
||||
success : function (importResult) {
|
||||
onSuccess : function (importResult) {
|
||||
assert (!OV.IsModelEmpty (importResult.model));
|
||||
assert.deepStrictEqual (importResult.usedFiles, ['single_triangle.stl']);
|
||||
assert.deepStrictEqual (importResult.missingFiles, []);
|
||||
let material = importResult.model.GetMaterial (0);
|
||||
assert.deepStrictEqual (material.diffuse, new OV.Color (200, 0, 0));
|
||||
done ();
|
||||
},
|
||||
error : function (importError) {
|
||||
onError : function (importError) {
|
||||
assert.fail ();
|
||||
}
|
||||
});
|
||||
|
||||
@ -6,348 +6,384 @@ let testUtils = require ('../utils/testutils.js');
|
||||
//console.log (util.inspect(testUtils.ModelToObjectSimple (model), {showHidden: false, depth: null}))
|
||||
|
||||
describe ('Gltf Importer', function () {
|
||||
it ('Triangle', function () {
|
||||
it ('Triangle', function (done) {
|
||||
let testFileList = [
|
||||
['Triangle/glTF', 'Triangle.gltf'],
|
||||
['Triangle/glTF-Embedded', 'Triangle.gltf'],
|
||||
['TriangleWithoutIndices/glTF', 'TriangleWithoutIndices.gltf'],
|
||||
['TriangleWithoutIndices/glTF-Embedded', 'TriangleWithoutIndices.gltf']
|
||||
];
|
||||
let processed = 0;
|
||||
for (let i = 0; i < testFileList.length; i++) {
|
||||
let testFile = testFileList[i];
|
||||
let model = testFiles.ImportGltfFile (testFile[0], testFile[1]);
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 3,
|
||||
normalCount : 1,
|
||||
uvCount : 0,
|
||||
triangleCount : 1,
|
||||
boundingBox : {
|
||||
min : [0.0, 0.0, 0.0],
|
||||
max : [1.0, 1.0, 0.0]
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 3,
|
||||
normalCount : 1,
|
||||
uvCount : 0,
|
||||
triangleCount : 1,
|
||||
boundingBox : {
|
||||
min : [0.0, 0.0, 0.0],
|
||||
max : [1.0, 1.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
]
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it ('Box', function () {
|
||||
it ('Box', function (done) {
|
||||
let testFileList = [
|
||||
['Box/glTF', 'Box.gltf'],
|
||||
['Box/glTF-Embedded', 'Box.gltf'],
|
||||
['Box/glTF-Binary', 'Box.glb']
|
||||
];
|
||||
let processed = 0;
|
||||
for (let i = 0; i < testFileList.length; i++) {
|
||||
let testFile = testFileList[i];
|
||||
let model = testFiles.ImportGltfFile (testFile[0], testFile[1]);
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'Red' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'Mesh',
|
||||
vertexCount : 24,
|
||||
normalCount : 24,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [-0.5, -0.5, -0.5],
|
||||
max : [0.5, 0.5, 0.5]
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'Red' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'Mesh',
|
||||
vertexCount : 24,
|
||||
normalCount : 24,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [-0.5, -0.5, -0.5],
|
||||
max : [0.5, 0.5, 0.5]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
]
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it ('BoxInterleaved', function () {
|
||||
it ('BoxInterleaved', function (done) {
|
||||
let testFileList = [
|
||||
['BoxInterleaved/glTF', 'BoxInterleaved.gltf'],
|
||||
['BoxInterleaved/glTF-Embedded', 'BoxInterleaved.gltf'],
|
||||
['BoxInterleaved/glTF-Binary', 'BoxInterleaved.glb']
|
||||
];
|
||||
let processed = 0;
|
||||
for (let i = 0; i < testFileList.length; i++) {
|
||||
let testFile = testFileList[i];
|
||||
let model = testFiles.ImportGltfFile (testFile[0], testFile[1]);
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'Mesh',
|
||||
vertexCount : 24,
|
||||
normalCount : 24,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [-0.5, -0.5, -0.5],
|
||||
max : [0.5, 0.5, 0.5]
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'Mesh',
|
||||
vertexCount : 24,
|
||||
normalCount : 24,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [-0.5, -0.5, -0.5],
|
||||
max : [0.5, 0.5, 0.5]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
]
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it ('BoxTextured', function () {
|
||||
it ('BoxTextured', function (done) {
|
||||
let testFileList = [
|
||||
['BoxTextured/glTF', 'BoxTextured.gltf'],
|
||||
['BoxTextured/glTF-Embedded', 'BoxTextured.gltf'],
|
||||
['BoxTextured/glTF-Binary', 'BoxTextured.glb']
|
||||
];
|
||||
let processed = 0;
|
||||
for (let i = 0; i < testFileList.length; i++) {
|
||||
let testFile = testFileList[i];
|
||||
let model = testFiles.ImportGltfFile (testFile[0], testFile[1]);
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'Texture' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'Mesh',
|
||||
vertexCount : 24,
|
||||
normalCount : 24,
|
||||
uvCount : 24,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [-0.5, -0.5, -0.5],
|
||||
max : [0.5, 0.5, 0.5]
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'Texture' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'Mesh',
|
||||
vertexCount : 24,
|
||||
normalCount : 24,
|
||||
uvCount : 24,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [-0.5, -0.5, -0.5],
|
||||
max : [0.5, 0.5, 0.5]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
]
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it ('SimpleMeshes', function () {
|
||||
it ('SimpleMeshes', function (done) {
|
||||
let testFileList = [
|
||||
['SimpleMeshes/glTF', 'SimpleMeshes.gltf'],
|
||||
['SimpleMeshes/glTF-Embedded', 'SimpleMeshes.gltf']
|
||||
];
|
||||
let processed = 0;
|
||||
for (let i = 0; i < testFileList.length; i++) {
|
||||
let testFile = testFileList[i];
|
||||
let model = testFiles.ImportGltfFile (testFile[0], testFile[1]);
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 3,
|
||||
normalCount : 3,
|
||||
uvCount : 0,
|
||||
triangleCount : 1,
|
||||
boundingBox : {
|
||||
min : [0.0, 0.0, 0.0],
|
||||
max : [1.0, 1.0, 0.0]
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 3,
|
||||
normalCount : 3,
|
||||
uvCount : 0,
|
||||
triangleCount : 1,
|
||||
boundingBox : {
|
||||
min : [0.0, 0.0, 0.0],
|
||||
max : [1.0, 1.0, 0.0]
|
||||
}
|
||||
},
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 3,
|
||||
normalCount : 3,
|
||||
uvCount : 0,
|
||||
triangleCount : 1,
|
||||
boundingBox : {
|
||||
min : [1.0, 0.0, 0.0],
|
||||
max : [2.0, 1.0, 0.0]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 3,
|
||||
normalCount : 3,
|
||||
uvCount : 0,
|
||||
triangleCount : 1,
|
||||
boundingBox : {
|
||||
min : [1.0, 0.0, 0.0],
|
||||
max : [2.0, 1.0, 0.0]
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
]
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it ('OrientationTest', function () {
|
||||
it ('OrientationTest', function (done) {
|
||||
let testFileList = [
|
||||
['OrientationTest/glTF', 'OrientationTest.gltf'],
|
||||
['OrientationTest/glTF-Embedded', 'OrientationTest.gltf'],
|
||||
['OrientationTest/glTF-Binary', 'OrientationTest.glb'],
|
||||
];
|
||||
let processed = 0;
|
||||
for (let i = 0; i < testFileList.length; i++) {
|
||||
let testFile = testFileList[i];
|
||||
let model = testFiles.ImportGltfFile (testFile[0], testFile[1]);
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'BaseMaterial' },
|
||||
{ name : 'MatX1' },
|
||||
{ name : 'MatX2' },
|
||||
{ name : 'MatY1' },
|
||||
{ name : 'MatY2' },
|
||||
{ name : 'MatZ1' },
|
||||
{ name : 'MatZ2' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name: 'ArrowMeshZ2',
|
||||
vertexCount: 78,
|
||||
normalCount: 78,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ -0.6921195564310951, -1.0785199551363698, -5.330651201963446 ],
|
||||
max: [ 1.0439303242310798, 2.868914373727357, -4.66934876823423 ]
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'BaseMaterial' },
|
||||
{ name : 'MatX1' },
|
||||
{ name : 'MatX2' },
|
||||
{ name : 'MatY1' },
|
||||
{ name : 'MatY2' },
|
||||
{ name : 'MatZ1' },
|
||||
{ name : 'MatZ2' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name: 'ArrowMeshZ2',
|
||||
vertexCount: 78,
|
||||
normalCount: 78,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ -0.6921195564310951, -1.0785199551363698, -5.330651201963446 ],
|
||||
max: [ 1.0439303242310798, 2.868914373727357, -4.66934876823423 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshZ2',
|
||||
vertexCount: 50,
|
||||
normalCount: 50,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ 0.8097413778305054, 2.8717148303985596, -5.33065128326416 ],
|
||||
max: [ 1.4936277866363525, 3.9211390018463135, -4.66934871673584 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshY2',
|
||||
vertexCount: 50,
|
||||
normalCount: 50,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ -1.1686336994171143, -5.330650806427002, 2.93727445602417 ],
|
||||
max: [ -0.46912679076194763, -4.66934871673584, 3.9916374683380127 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ArrowMeshY2',
|
||||
vertexCount: 78,
|
||||
normalCount: 78,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ -0.9557393651589479, -5.330651177643153, -1.06505742884149 ],
|
||||
max: [ 0.6167901044859734, -4.6693486435429055, 2.934442924096579 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ArrowMeshX2',
|
||||
vertexCount: 78,
|
||||
normalCount: 78,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ -5.330651171390089, -1.0326269494863676, -0.6059335185163844 ],
|
||||
max: [ -4.669348828609911, 2.9885841671721116, 0.8202131194767724 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshX2',
|
||||
vertexCount: 54,
|
||||
normalCount: 54,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ -5.33065128326416, 2.991360902786255, -0.012430161237716675 ],
|
||||
max: [ -4.66934871673584, 4.039160251617432, 0.6999828815460205 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshZ1',
|
||||
vertexCount: 52,
|
||||
normalCount: 52,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ -1.3648574352264404, 2.9005930423736572, 4.66934871673584 ],
|
||||
max: [ -0.6740907430648804, 3.9529545307159424, 5.33065128326416 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ArrowMeshZ1',
|
||||
vertexCount: 74,
|
||||
normalCount: 74,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ -1.009571011381568, -1.074115497823536, 4.669348895549774 ],
|
||||
max: [ 0.6625885973069405, 2.8977772707193465, 5.330651104450226 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshX1',
|
||||
vertexCount: 54,
|
||||
normalCount: 54,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ 4.66934871673584, 2.4595587253570557, -2.553251266479492 ],
|
||||
max: [ 5.33065128326416, 3.432579517364502, -1.7226401567459106 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ArrowMeshX1',
|
||||
vertexCount: 78,
|
||||
normalCount: 78,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ 4.669348835945129, -1.0589144181932033, -1.7207290818192755 ],
|
||||
max: [ 5.330651164054871, 2.4574561383341145, 0.9159925616542917 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshY1',
|
||||
vertexCount: 52,
|
||||
normalCount: 52,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ 2.8218495845794678, 4.669349193572998, -1.6833229064941406 ],
|
||||
max: [ 3.864471435546875, 5.33065128326416, -1.0113166570663452 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ArrowMeshY1',
|
||||
vertexCount: 78,
|
||||
normalCount: 78,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ -1.0826615032554154, 4.669348806142807, -1.093071740019906 ],
|
||||
max: [ 2.8190779754834807, 5.3306513130664825, 0.7348238365226794 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'BaseCubeMesh',
|
||||
vertexCount: 272,
|
||||
normalCount: 272,
|
||||
uvCount: 0,
|
||||
triangleCount: 140,
|
||||
boundingBox : {
|
||||
min: [ -5.000001907348633, -5, -5.000001907348633 ],
|
||||
max: [ 5.000002384185791, 5, 5.000002861022949 ]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshZ2',
|
||||
vertexCount: 50,
|
||||
normalCount: 50,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ 0.8097413778305054, 2.8717148303985596, -5.33065128326416 ],
|
||||
max: [ 1.4936277866363525, 3.9211390018463135, -4.66934871673584 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshY2',
|
||||
vertexCount: 50,
|
||||
normalCount: 50,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ -1.1686336994171143, -5.330650806427002, 2.93727445602417 ],
|
||||
max: [ -0.46912679076194763, -4.66934871673584, 3.9916374683380127 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ArrowMeshY2',
|
||||
vertexCount: 78,
|
||||
normalCount: 78,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ -0.9557393651589479, -5.330651177643153, -1.06505742884149 ],
|
||||
max: [ 0.6167901044859734, -4.6693486435429055, 2.934442924096579 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ArrowMeshX2',
|
||||
vertexCount: 78,
|
||||
normalCount: 78,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ -5.330651171390089, -1.0326269494863676, -0.6059335185163844 ],
|
||||
max: [ -4.669348828609911, 2.9885841671721116, 0.8202131194767724 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshX2',
|
||||
vertexCount: 54,
|
||||
normalCount: 54,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ -5.33065128326416, 2.991360902786255, -0.012430161237716675 ],
|
||||
max: [ -4.66934871673584, 4.039160251617432, 0.6999828815460205 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshZ1',
|
||||
vertexCount: 52,
|
||||
normalCount: 52,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ -1.3648574352264404, 2.9005930423736572, 4.66934871673584 ],
|
||||
max: [ -0.6740907430648804, 3.9529545307159424, 5.33065128326416 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ArrowMeshZ1',
|
||||
vertexCount: 74,
|
||||
normalCount: 74,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ -1.009571011381568, -1.074115497823536, 4.669348895549774 ],
|
||||
max: [ 0.6625885973069405, 2.8977772707193465, 5.330651104450226 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshX1',
|
||||
vertexCount: 54,
|
||||
normalCount: 54,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ 4.66934871673584, 2.4595587253570557, -2.553251266479492 ],
|
||||
max: [ 5.33065128326416, 3.432579517364502, -1.7226401567459106 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ArrowMeshX1',
|
||||
vertexCount: 78,
|
||||
normalCount: 78,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ 4.669348835945129, -1.0589144181932033, -1.7207290818192755 ],
|
||||
max: [ 5.330651164054871, 2.4574561383341145, 0.9159925616542917 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'TargetMeshY1',
|
||||
vertexCount: 52,
|
||||
normalCount: 52,
|
||||
uvCount: 0,
|
||||
triangleCount: 26,
|
||||
boundingBox : {
|
||||
min: [ 2.8218495845794678, 4.669349193572998, -1.6833229064941406 ],
|
||||
max: [ 3.864471435546875, 5.33065128326416, -1.0113166570663452 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'ArrowMeshY1',
|
||||
vertexCount: 78,
|
||||
normalCount: 78,
|
||||
uvCount: 0,
|
||||
triangleCount: 38,
|
||||
boundingBox : {
|
||||
min: [ -1.0826615032554154, 4.669348806142807, -1.093071740019906 ],
|
||||
max: [ 2.8190779754834807, 5.3306513130664825, 0.7348238365226794 ]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'BaseCubeMesh',
|
||||
vertexCount: 272,
|
||||
normalCount: 272,
|
||||
uvCount: 0,
|
||||
triangleCount: 140,
|
||||
boundingBox : {
|
||||
min: [ -5.000001907348633, -5, -5.000001907348633 ],
|
||||
max: [ 5.000002384185791, 5, 5.000002861022949 ]
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
]
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it ('MeshPrimitives_4Vertex', function () {
|
||||
it ('MeshPrimitives_4Vertex', function (done) {
|
||||
let testFileList = [
|
||||
['Mesh_PrimitiveMode', 'Mesh_PrimitiveMode_04.gltf'],
|
||||
['Mesh_PrimitiveMode', 'Mesh_PrimitiveMode_05.gltf'],
|
||||
@ -355,90 +391,108 @@ describe ('Gltf Importer', function () {
|
||||
['Mesh_PrimitiveMode', 'Mesh_PrimitiveMode_12.gltf'],
|
||||
['Mesh_PrimitiveMode', 'Mesh_PrimitiveMode_13.gltf']
|
||||
];
|
||||
let processed = 0;
|
||||
for (let i = 0; i < testFileList.length; i++) {
|
||||
let testFile = testFileList[i];
|
||||
let model = testFiles.ImportGltfFile (testFile[0], testFile[1]);
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 4,
|
||||
normalCount : 2,
|
||||
uvCount : 0,
|
||||
triangleCount : 2,
|
||||
boundingBox : {
|
||||
min : [-0.5, -0.5, 0.0],
|
||||
max : [0.5, 0.5, 0.0]
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 4,
|
||||
normalCount : 2,
|
||||
uvCount : 0,
|
||||
triangleCount : 2,
|
||||
boundingBox : {
|
||||
min : [-0.5, -0.5, 0.0],
|
||||
max : [0.5, 0.5, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
]
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it ('MeshPrimitives_6Vertex', function () {
|
||||
it ('MeshPrimitives_6Vertex', function (done) {
|
||||
let testFileList = [
|
||||
['Mesh_PrimitiveMode', 'Mesh_PrimitiveMode_06.gltf']
|
||||
];
|
||||
let processed = 0;
|
||||
for (let i = 0; i < testFileList.length; i++) {
|
||||
let testFile = testFileList[i];
|
||||
let model = testFiles.ImportGltfFile (testFile[0], testFile[1]);
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 6,
|
||||
normalCount : 2,
|
||||
uvCount : 0,
|
||||
triangleCount : 2,
|
||||
boundingBox : {
|
||||
min : [-0.5, -0.5, 0.0],
|
||||
max : [0.5, 0.5, 0.0]
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 6,
|
||||
normalCount : 2,
|
||||
uvCount : 0,
|
||||
triangleCount : 2,
|
||||
boundingBox : {
|
||||
min : [-0.5, -0.5, 0.0],
|
||||
max : [0.5, 0.5, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
]
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it ('SimpleSparseAccessor', function () {
|
||||
it ('SimpleSparseAccessor', function (done) {
|
||||
let testFileList = [
|
||||
['SimpleSparseAccessor/glTF', 'SimpleSparseAccessor.gltf'],
|
||||
['SimpleSparseAccessor/glTF-Embedded', 'SimpleSparseAccessor.gltf']
|
||||
];
|
||||
let processed = 0;
|
||||
for (let i = 0; i < testFileList.length; i++) {
|
||||
let testFile = testFileList[i];
|
||||
let model = testFiles.ImportGltfFile (testFile[0], testFile[1]);
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 14,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0.0, 0.0, 0.0],
|
||||
max : [6.0, 4.0, 0.0]
|
||||
testFiles.ImportGltfFile (testFile[0], testFile[1], function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 14,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0.0, 0.0, 0.0],
|
||||
max : [6.0, 4.0, 0.0]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
]
|
||||
});
|
||||
processed += 1;
|
||||
if (processed == testFileList.length) {
|
||||
done ();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -2,136 +2,147 @@ var assert = require ('assert');
|
||||
var testFiles = require ('../utils/testfiles.js');
|
||||
var testUtils = require ('../utils/testutils.js');
|
||||
|
||||
describe ('Off Importer', function() {
|
||||
it ('single_triangle.off', function () {
|
||||
var model = testFiles.ImportOffFile ('single_triangle.off');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
describe ('Off Importer', function () {
|
||||
it ('single_triangle.off', function (done) {
|
||||
testFiles.ImportOffFile ('single_triangle.off', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('two_triangles.off', function () {
|
||||
var model = testFiles.ImportOffFile ('two_triangles.off');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
},
|
||||
{
|
||||
vertices : [0, 0, 1, 1, 0, 1, 1, 1, 1],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
it ('two_triangles.off', function (done) {
|
||||
testFiles.ImportOffFile ('two_triangles.off', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
},
|
||||
{
|
||||
vertices : [0, 0, 1, 1, 0, 1, 1, 1, 1],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('single_rectangle.off', function () {
|
||||
var model = testFiles.ImportOffFile ('single_rectangle.off');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
},
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 1, 0, 0, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
it ('single_rectangle.off', function (done) {
|
||||
testFiles.ImportOffFile ('single_rectangle.off', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
},
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 1, 0, 0, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('single_triangle_with_comments.off', function () {
|
||||
var model = testFiles.ImportOffFile ('single_triangle_with_comments.off');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
it ('single_triangle_with_comments.off', function (done) {
|
||||
testFiles.ImportOffFile ('single_triangle_with_comments.off', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it ('cube.off', function () {
|
||||
var model = testFiles.ImportOffFile ('cube.off');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
it ('cube.off', function (done) {
|
||||
testFiles.ImportOffFile ('cube.off', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -3,210 +3,226 @@ var testFiles = require ('../utils/testfiles.js');
|
||||
var testUtils = require ('../utils/testutils.js');
|
||||
|
||||
describe ('Ply Importer', function() {
|
||||
it ('single_triangle.ply', function () {
|
||||
var model = testFiles.ImportPlyFile ('single_triangle.ply');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
it ('single_triangle.ply', function (done) {
|
||||
var model = testFiles.ImportPlyFile ('single_triangle.ply', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('two_triangles.ply', function () {
|
||||
var model = testFiles.ImportPlyFile ('two_triangles.ply');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
},
|
||||
{
|
||||
vertices : [0, 0, 1, 1, 0, 1, 1, 1, 1],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
it ('two_triangles.ply', function (done) {
|
||||
var model = testFiles.ImportPlyFile ('two_triangles.ply', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
},
|
||||
{
|
||||
vertices : [0, 0, 1, 1, 0, 1, 1, 1, 1],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('single_rectangle.ply', function () {
|
||||
var model = testFiles.ImportPlyFile ('single_rectangle.ply');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
},
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 1, 0, 0, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
it ('single_rectangle.ply', function (done) {
|
||||
var model = testFiles.ImportPlyFile ('single_rectangle.ply', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
},
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 1, 0, 0, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('single_triangle_with_comments.ply', function () {
|
||||
var model = testFiles.ImportPlyFile ('single_triangle_with_comments.ply');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
it ('single_triangle_with_comments.ply', function (done) {
|
||||
var model = testFiles.ImportPlyFile ('single_triangle_with_comments.ply', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('cube.ply', function (done) {
|
||||
var model = testFiles.ImportPlyFile ('cube.ply', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('cube.ply', function () {
|
||||
var model = testFiles.ImportPlyFile ('cube.ply');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
it ('cube_meshlab_ascii.ply', function (done) {
|
||||
var model = testFiles.ImportPlyFile ('cube_meshlab_ascii.ply', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it ('cube_meshlab_ascii.ply', function () {
|
||||
var model = testFiles.ImportPlyFile ('cube_meshlab_ascii.ply');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('cube_meshlab_binary.ply', function () {
|
||||
var model = testFiles.ImportPlyFile ('cube_meshlab_binary.ply');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
it ('cube_meshlab_binary.ply', function (done) {
|
||||
var model = testFiles.ImportPlyFile ('cube_meshlab_binary.ply', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('cube_rgb_binary.ply', function () {
|
||||
var model = testFiles.ImportPlyFile ('cube_rgb_binary.ply');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '#cc0000ff' },
|
||||
{ name : '#00cc00ff' },
|
||||
{ name : '#0000ccff' },
|
||||
{ name : '#cccccc7f' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
it ('cube_rgb_binary.ply', function (done) {
|
||||
var model = testFiles.ImportPlyFile ('cube_rgb_binary.ply', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : 'Color cc0000ff' },
|
||||
{ name : 'Color 00cc00ff' },
|
||||
{ name : 'Color 0000ccff' },
|
||||
{ name : 'Color cccccc7f' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 8,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -3,202 +3,218 @@ var testFiles = require ('../utils/testfiles.js');
|
||||
var testUtils = require ('../utils/testutils.js');
|
||||
|
||||
describe ('Stl Importer', function() {
|
||||
it ('single_triangle.stl', function () {
|
||||
var model = testFiles.ImportStlFile ('single_triangle.stl');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'MeshName',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
it ('single_triangle.stl', function (done) {
|
||||
testFiles.ImportStlFile ('single_triangle.stl', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'MeshName',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('single_triangle_with_comments.stl', function () {
|
||||
var model = testFiles.ImportStlFile ('single_triangle_with_comments.stl');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'MeshName',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
it ('single_triangle_with_comments.stl', function (done) {
|
||||
testFiles.ImportStlFile ('single_triangle_with_comments.stl', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'MeshName',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('single_triangle_no_normal.stl', function () {
|
||||
var model = testFiles.ImportStlFile ('single_triangle_no_normal.stl');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'MeshName',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
it ('single_triangle_no_normal.stl', function (done) {
|
||||
testFiles.ImportStlFile ('single_triangle_no_normal.stl', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'MeshName',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('two_triangles.stl', function () {
|
||||
var model = testFiles.ImportStlFile ('two_triangles.stl');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'MeshName',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
},
|
||||
{
|
||||
vertices : [0, 0, 1, 1, 0, 1, 1, 1, 1],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
it ('two_triangles.stl', function (done) {
|
||||
testFiles.ImportStlFile ('two_triangles.stl', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObject (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'MeshName',
|
||||
triangles : [
|
||||
{
|
||||
vertices : [0, 0, 0, 1, 0, 0, 1, 1, 0],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
},
|
||||
{
|
||||
vertices : [0, 0, 1, 1, 0, 1, 1, 1, 1],
|
||||
normals : [0, 0, 1, 0, 0, 1, 0, 0, 1],
|
||||
uvs : [],
|
||||
mat : 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('stl_ascii.stl', function () {
|
||||
var model = testFiles.ImportStlFile ('stl_ascii.stl');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'Untitled-5427e5af',
|
||||
vertexCount : 1716,
|
||||
normalCount : 572,
|
||||
uvCount : 0,
|
||||
triangleCount : 572,
|
||||
boundingBox : {
|
||||
min : [0, -1.10792799192095, 0],
|
||||
max : [4.94407346265022, 3.31831671830375, 1.2]
|
||||
it ('stl_ascii.stl', function (done) {
|
||||
testFiles.ImportStlFile ('stl_ascii.stl', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'Untitled-5427e5af',
|
||||
vertexCount : 1716,
|
||||
normalCount : 572,
|
||||
uvCount : 0,
|
||||
triangleCount : 572,
|
||||
boundingBox : {
|
||||
min : [0, -1.10792799192095, 0],
|
||||
max : [4.94407346265022, 3.31831671830375, 1.2]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('stl_binary.stl', function () {
|
||||
var model = testFiles.ImportStlFile ('stl_binary.stl');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 2184,
|
||||
normalCount : 728,
|
||||
uvCount : 0,
|
||||
triangleCount : 728,
|
||||
boundingBox : {
|
||||
min : [0, -1.1079280376434326, 0],
|
||||
max : [5.70156717300415, 3.318316698074341, 1.2000000476837158]
|
||||
it ('stl_binary.stl', function (done) {
|
||||
testFiles.ImportStlFile ('stl_binary.stl', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 2184,
|
||||
normalCount : 728,
|
||||
uvCount : 0,
|
||||
triangleCount : 728,
|
||||
boundingBox : {
|
||||
min : [0, -1.1079280376434326, 0],
|
||||
max : [5.70156717300415, 3.318316698074341, 1.2000000476837158]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it ('cube_meshlab_ascii.stl', function () {
|
||||
var model = testFiles.ImportStlFile ('cube_meshlab_ascii.stl');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'STL generated by MeshLab',
|
||||
vertexCount : 36,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
it ('cube_meshlab_ascii.stl', function (done) {
|
||||
testFiles.ImportStlFile ('cube_meshlab_ascii.stl', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : 'STL generated by MeshLab',
|
||||
vertexCount : 36,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
|
||||
it ('cube_meshlab_binary.stl', function () {
|
||||
var model = testFiles.ImportStlFile ('cube_meshlab_binary.stl');
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 36,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
it ('cube_meshlab_binary.stl', function (done) {
|
||||
testFiles.ImportStlFile ('cube_meshlab_binary.stl', function (model) {
|
||||
assert (OV.CheckModel (model));
|
||||
assert.deepStrictEqual (testUtils.ModelToObjectSimple (model), {
|
||||
name : '',
|
||||
materials : [
|
||||
{ name : '' }
|
||||
],
|
||||
meshes : [
|
||||
{
|
||||
name : '',
|
||||
vertexCount : 36,
|
||||
normalCount : 12,
|
||||
uvCount : 0,
|
||||
triangleCount : 12,
|
||||
boundingBox : {
|
||||
min : [0, 0, 0],
|
||||
max : [1, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
done ();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -78,4 +78,62 @@ describe ('Model Utils', function () {
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it ('Mesh Volume Calculation', function () {
|
||||
function GetTriangleArea (v0, v1, v2)
|
||||
{
|
||||
let a = OV.CoordDistance3D (v0, v1);
|
||||
let b = OV.CoordDistance3D (v1, v2);
|
||||
let c = OV.CoordDistance3D (v0, v2);
|
||||
let s = (a + b + c) / 2.0;
|
||||
let areaSquare = s * (s - a) * (s - b) * (s - c);
|
||||
if (areaSquare < 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
return Math.sqrt (areaSquare);
|
||||
}
|
||||
|
||||
var model = new OV.Model ();
|
||||
var cube = new OV.Mesh ();
|
||||
cube.AddVertex (new OV.Coord3D (0.0, 0.0, 0.0));
|
||||
cube.AddVertex (new OV.Coord3D (1.0, 0.0, 0.0));
|
||||
cube.AddVertex (new OV.Coord3D (1.0, 1.0, 0.0));
|
||||
cube.AddVertex (new OV.Coord3D (0.0, 1.0, 0.0));
|
||||
cube.AddVertex (new OV.Coord3D (0.0, 0.0, 1.0));
|
||||
cube.AddVertex (new OV.Coord3D (1.0, 0.0, 1.0));
|
||||
cube.AddVertex (new OV.Coord3D (1.0, 1.0, 1.0));
|
||||
cube.AddVertex (new OV.Coord3D (0.0, 1.0, 1.0));
|
||||
cube.AddTriangle (new OV.Triangle (0, 1, 5));
|
||||
cube.AddTriangle (new OV.Triangle (0, 5, 4));
|
||||
cube.AddTriangle (new OV.Triangle (1, 2, 6));
|
||||
cube.AddTriangle (new OV.Triangle (1, 6, 5));
|
||||
cube.AddTriangle (new OV.Triangle (2, 3, 7));
|
||||
cube.AddTriangle (new OV.Triangle (2, 7, 6));
|
||||
cube.AddTriangle (new OV.Triangle (3, 0, 4));
|
||||
cube.AddTriangle (new OV.Triangle (3, 4, 7));
|
||||
cube.AddTriangle (new OV.Triangle (0, 3, 2));
|
||||
cube.AddTriangle (new OV.Triangle (0, 2, 1));
|
||||
cube.AddTriangle (new OV.Triangle (4, 5, 6));
|
||||
cube.AddTriangle (new OV.Triangle (4, 6, 7));
|
||||
model.AddMesh (cube);
|
||||
OV.FinalizeModel (model, function () {
|
||||
return new OV.Material ();
|
||||
});
|
||||
let surface = 0.0;
|
||||
let volume = 0.0;
|
||||
for (let i = 0; i < model.MeshCount (); i++) {
|
||||
let mesh = model.GetMesh (i);
|
||||
for (j = 0; j < mesh.TriangleCount (); j++) {
|
||||
let triangle = mesh.GetTriangle (j);
|
||||
let v0 = mesh.GetVertex (triangle.v0);
|
||||
let v1 = mesh.GetVertex (triangle.v1);
|
||||
let v2 = mesh.GetVertex (triangle.v2);
|
||||
surface += GetTriangleArea (v0, v1, v2);
|
||||
let signedVolume = OV.DotVector3D (v0, OV.CrossVector3D (v1, v2)) / 6.0;
|
||||
volume += signedVolume;
|
||||
}
|
||||
}
|
||||
assert (OV.IsEqual (volume, 1.0));
|
||||
assert (OV.IsEqual (surface, 6.0));
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,37 +2,37 @@ var testUtils = require ('./testutils.js');
|
||||
|
||||
module.exports =
|
||||
{
|
||||
ImportObjFile : function (fileName)
|
||||
ImportObjFile : function (fileName, onReady)
|
||||
{
|
||||
var importer = new OV.ImporterObj ();
|
||||
return this.ImportFile (importer, OV.FileFormat.Text, 'obj', fileName);
|
||||
this.ImportFile (importer, OV.FileFormat.Text, 'obj', fileName, onReady);
|
||||
},
|
||||
|
||||
ImportStlFile : function (fileName)
|
||||
ImportStlFile : function (fileName, onReady)
|
||||
{
|
||||
var importer = new OV.ImporterStl ();
|
||||
return this.ImportFile (importer, OV.FileFormat.Binary, 'stl', fileName);
|
||||
this.ImportFile (importer, OV.FileFormat.Binary, 'stl', fileName, onReady);
|
||||
},
|
||||
|
||||
ImportOffFile : function (fileName)
|
||||
ImportOffFile : function (fileName, onReady)
|
||||
{
|
||||
var importer = new OV.ImporterOff ();
|
||||
return this.ImportFile (importer, OV.FileFormat.Text, 'off', fileName);
|
||||
this.ImportFile (importer, OV.FileFormat.Text, 'off', fileName, onReady);
|
||||
},
|
||||
|
||||
ImportPlyFile : function (fileName)
|
||||
ImportPlyFile : function (fileName, onReady)
|
||||
{
|
||||
var importer = new OV.ImporterPly ();
|
||||
return this.ImportFile (importer, OV.FileFormat.Binary, 'ply', fileName);
|
||||
this.ImportFile (importer, OV.FileFormat.Binary, 'ply', fileName, onReady);
|
||||
},
|
||||
|
||||
Import3dsFile : function (fileName)
|
||||
Import3dsFile : function (fileName, onReady)
|
||||
{
|
||||
var importer = new OV.Importer3ds ();
|
||||
return this.ImportFile (importer, OV.FileFormat.Binary, '3ds', fileName);
|
||||
this.ImportFile (importer, OV.FileFormat.Binary, '3ds', fileName, onReady);
|
||||
},
|
||||
|
||||
ImportGltfFile : function (folderName, fileName)
|
||||
ImportGltfFile : function (folderName, fileName, onReady)
|
||||
{
|
||||
let extension = OV.GetFileExtension (fileName);
|
||||
let format = OV.FileFormat.Text;
|
||||
@ -40,10 +40,10 @@ module.exports =
|
||||
format = OV.FileFormat.Binary;
|
||||
}
|
||||
var importer = new OV.ImporterGltf ();
|
||||
return this.ImportFile (importer, format, 'gltf/' + folderName, fileName);
|
||||
this.ImportFile (importer, format, 'gltf/' + folderName, fileName, onReady);
|
||||
},
|
||||
|
||||
ImportFile : function (importer, format, folder, fileName)
|
||||
ImportFile : function (importer, format, folder, fileName, onReady)
|
||||
{
|
||||
var content = null;
|
||||
if (format == OV.FileFormat.Text) {
|
||||
@ -77,9 +77,17 @@ module.exports =
|
||||
},
|
||||
getTextureBuffer : function (filePath) {
|
||||
return buffers.GetTextureBuffer (filePath);
|
||||
},
|
||||
onSuccess : function () {
|
||||
let model = importer.GetModel ();
|
||||
onReady (model);
|
||||
},
|
||||
onError : function () {
|
||||
onReady (model);
|
||||
},
|
||||
onComplete : function () {
|
||||
|
||||
}
|
||||
});
|
||||
let model = importer.GetModel ();
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
{
|
||||
"lib_files" : [
|
||||
"libs/jquery-3.5.1.min.js",
|
||||
"libs/three.min-126.js"
|
||||
"libs/three.min-126.js",
|
||||
"libs/rhino3dm.min.js"
|
||||
],
|
||||
"importer_files" : [
|
||||
"source/core/core.js",
|
||||
@ -40,6 +41,8 @@
|
||||
"source/export/exporteroff.js",
|
||||
"source/export/exportergltf.js",
|
||||
"source/export/exporter.js",
|
||||
"source/external/rhino.importer.js",
|
||||
"source/external/rhino.exporter.js",
|
||||
"source/external/three.converter.js",
|
||||
"source/external/three.model.loader.js",
|
||||
"source/parameters/parameterlist.js",
|
||||
|
||||
@ -19,20 +19,19 @@ def GetVersion (rootDir):
|
||||
return packageJson['version']
|
||||
|
||||
def JSHintFolder (folder):
|
||||
result = Tools.RunCommand (['jshint', folder])
|
||||
result = Tools.RunCommand ('jshint', [folder])
|
||||
if result != 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
def CompressFiles (inputFiles, outputFile):
|
||||
parameters = []
|
||||
parameters.append ('google-closure-compiler')
|
||||
for inputFile in inputFiles:
|
||||
extension = os.path.splitext (inputFile)[1]
|
||||
if extension == '.js':
|
||||
parameters.append ('--js=' + os.path.join ('..', inputFile))
|
||||
parameters.append ('--js_output_file=' + outputFile)
|
||||
result = Tools.RunCommand (parameters)
|
||||
result = Tools.RunCommand ('google-closure-compiler', parameters)
|
||||
if result != 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
@ -13,13 +13,9 @@ def WriteContentToFile (filePath, content):
|
||||
fileObject.write (content)
|
||||
fileObject.close ()
|
||||
|
||||
def RunCommand (commands):
|
||||
process = subprocess.Popen (commands, stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True)
|
||||
out, err = process.communicate ()
|
||||
if process.returncode != 0:
|
||||
print (out.decode ())
|
||||
print (err.decode ())
|
||||
return process.returncode
|
||||
def RunCommand (executable, arguments):
|
||||
command = executable + ' "' + '" "'.join (arguments) + '"'
|
||||
return os.system (command)
|
||||
|
||||
class TokenReplacer:
|
||||
def __init__ (self, filePath, keepToken):
|
||||
|
||||
@ -7,8 +7,7 @@ def Main (argv):
|
||||
currentDir = os.path.dirname (os.path.abspath (__file__))
|
||||
os.chdir (currentDir)
|
||||
imagesPath = os.path.abspath (os.path.join ('..', 'website', 'assets', 'images'))
|
||||
for i in range (0, 5):
|
||||
Tools.RunCommand (['svgo', '-r', imagesPath])
|
||||
Tools.RunCommand ('svgo', ['-r', imagesPath])
|
||||
return 0
|
||||
|
||||
sys.exit (Main (sys.argv))
|
||||
|
||||
@ -45,6 +45,8 @@
|
||||
<script type="text/javascript" src="../../source/export/exporteroff.js"></script>
|
||||
<script type="text/javascript" src="../../source/export/exportergltf.js"></script>
|
||||
<script type="text/javascript" src="../../source/export/exporter.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/rhino.importer.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/rhino.exporter.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/three.converter.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/three.model.loader.js"></script>
|
||||
<script type="text/javascript" src="../../source/parameters/parameterlist.js"></script>
|
||||
|
||||
@ -47,6 +47,8 @@
|
||||
<script type="text/javascript" src="../../source/export/exporteroff.js"></script>
|
||||
<script type="text/javascript" src="../../source/export/exportergltf.js"></script>
|
||||
<script type="text/javascript" src="../../source/export/exporter.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/rhino.importer.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/rhino.exporter.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/three.converter.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/three.model.loader.js"></script>
|
||||
<script type="text/javascript" src="../../source/parameters/parameterlist.js"></script>
|
||||
|
||||
@ -45,6 +45,8 @@
|
||||
<script type="text/javascript" src="../../source/export/exporteroff.js"></script>
|
||||
<script type="text/javascript" src="../../source/export/exportergltf.js"></script>
|
||||
<script type="text/javascript" src="../../source/export/exporter.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/rhino.importer.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/rhino.exporter.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/three.converter.js"></script>
|
||||
<script type="text/javascript" src="../../source/external/three.model.loader.js"></script>
|
||||
<script type="text/javascript" src="../../source/parameters/parameterlist.js"></script>
|
||||
|
||||
|
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 304 B |
@ -14,6 +14,7 @@
|
||||
<!-- libs start -->
|
||||
<script type="text/javascript" src="../libs/jquery-3.5.1.min.js"></script>
|
||||
<script type="text/javascript" src="../libs/three.min-126.js"></script>
|
||||
<script type="text/javascript" src="../libs/rhino3dm.min.js"></script>
|
||||
<!-- libs end -->
|
||||
|
||||
<!-- importer start -->
|
||||
@ -53,6 +54,8 @@
|
||||
<script type="text/javascript" src="../source/export/exporteroff.js"></script>
|
||||
<script type="text/javascript" src="../source/export/exportergltf.js"></script>
|
||||
<script type="text/javascript" src="../source/export/exporter.js"></script>
|
||||
<script type="text/javascript" src="../source/external/rhino.importer.js"></script>
|
||||
<script type="text/javascript" src="../source/external/rhino.exporter.js"></script>
|
||||
<script type="text/javascript" src="../source/external/three.converter.js"></script>
|
||||
<script type="text/javascript" src="../source/external/three.model.loader.js"></script>
|
||||
<script type="text/javascript" src="../source/parameters/parameterlist.js"></script>
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
<!-- libs start -->
|
||||
<script type="text/javascript" src="../libs/jquery-3.5.1.min.js"></script>
|
||||
<script type="text/javascript" src="../libs/three.min-126.js"></script>
|
||||
<script type="text/javascript" src="../libs/rhino3dm.min.js"></script>
|
||||
<!-- libs end -->
|
||||
|
||||
<!-- meta start -->
|
||||
@ -53,6 +54,8 @@
|
||||
<script type="text/javascript" src="../source/export/exporteroff.js"></script>
|
||||
<script type="text/javascript" src="../source/export/exportergltf.js"></script>
|
||||
<script type="text/javascript" src="../source/export/exporter.js"></script>
|
||||
<script type="text/javascript" src="../source/external/rhino.importer.js"></script>
|
||||
<script type="text/javascript" src="../source/external/rhino.exporter.js"></script>
|
||||
<script type="text/javascript" src="../source/external/three.converter.js"></script>
|
||||
<script type="text/javascript" src="../source/external/three.model.loader.js"></script>
|
||||
<script type="text/javascript" src="../source/parameters/parameterlist.js"></script>
|
||||
@ -125,12 +128,12 @@
|
||||
<div class="intro_section only_full_width only_full_height"><img src="assets/images/3dviewer_net_logo.svg" class="intro_logo"></img></div>
|
||||
<div class="intro_section intro_big_text">
|
||||
Drag and drop your 3D models here.<br>
|
||||
Supported formats: <b>obj, 3ds, stl, ply, gltf, glb, off</b>.
|
||||
<b>obj, 3ds, stl, ply, gltf, glb, 3dm, off</b>
|
||||
</div>
|
||||
<div class="intro_section">
|
||||
Or you can use the browse button above.
|
||||
</div>
|
||||
<div class="intro_section only_full_height">
|
||||
<div class="intro_section">
|
||||
<div>Example models:</div>
|
||||
<div class="example_models">
|
||||
<a href="index.html#model=assets/models/logo.obj,assets/models/logo.mtl">logo</a>
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
<p>
|
||||
This is the user manual for the <a href="https://3dviewer.net">3dviewer.net</a> website.
|
||||
The website can open several 3D file formats and visualize the model in your browser.
|
||||
Supported file formats: obj, 3ds, stl, ply, gltf, glb, and off.
|
||||
Supported file formats: obj, 3ds, stl, ply, gltf, glb, 3dm, and off.
|
||||
</p>
|
||||
<p>
|
||||
<ol>
|
||||
@ -112,6 +112,13 @@
|
||||
<td class="center green">✓</td>
|
||||
<td>version 2.0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3dm</td>
|
||||
<td>binary</td>
|
||||
<td class="center green">✓</td>
|
||||
<td class="center green">✓</td>
|
||||
<td>experimental</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2">off</td>
|
||||
<td>text</td>
|
||||
@ -173,7 +180,7 @@
|
||||
<h2 id="embedding_viewer">Embedding the viewer</h2>
|
||||
<p>
|
||||
The website allows you to embed a 3D model in your page. It works only if your models are <a href="#loading_models_server">hosted on a web server</a>.
|
||||
To get the embedding code, click on the embedding button (<img class="inline" src="../assets/images/toolbar/embed.svg"/>) in the toolbar.
|
||||
To get the embedding code, click on the share model button (<img class="inline" src="../assets/images/toolbar/share.svg"/>) in the toolbar.
|
||||
</p>
|
||||
|
||||
<h3 id="embed_github">Embedding models hosted on GitHub</h3>
|
||||
@ -191,7 +198,7 @@
|
||||
https://github.com/kovacsv/Online3DViewer/blob/master/test/testfiles/3ds/texture.png
|
||||
</div>
|
||||
</li>
|
||||
<li>Click on OK, and if the model is loaded, click on the embed button in the toolbar (<img class="inline" src="../assets/images/toolbar/embed.svg"/>).</li>
|
||||
<li>Click on OK, and if the model is loaded, click on the share button in the toolbar (<img class="inline" src="../assets/images/toolbar/share.svg"/>).</li>
|
||||
</ol>
|
||||
</p>
|
||||
|
||||
@ -210,7 +217,7 @@
|
||||
https://www.dropbox.com/s/6dfk1jveevbofxm/texture.png?dl=0
|
||||
</div>
|
||||
</li>
|
||||
<li>Click on OK, and if the model is loaded, click on the embed button in the toolbar (<img class="inline" src="../assets/images/toolbar/embed.svg"/>).</li>
|
||||
<li>Click on OK, and if the model is loaded, click on the share button in the toolbar (<img class="inline" src="../assets/images/toolbar/share.svg"/>).</li>
|
||||
</ol>
|
||||
</p>
|
||||
|
||||
|
||||
@ -74,21 +74,31 @@ OV.ShowOpenUrlDialog = function (onOk)
|
||||
$('<div>').html (text).addClass ('ov_dialog_section').appendTo (contentDiv);
|
||||
urlsTextArea.appendTo (contentDiv);
|
||||
dialog.Show ();
|
||||
urlsTextArea.focus ();
|
||||
return dialog;
|
||||
};
|
||||
|
||||
OV.ShowEmbeddingDialog = function (importer, importSettings, camera)
|
||||
OV.ShowSharingDialog = function (importer, importSettings, camera)
|
||||
{
|
||||
function AddCheckboxLine (parentDiv, text, onChange)
|
||||
function AddCheckboxLine (parentDiv, text, id, onChange)
|
||||
{
|
||||
let line = $('<div>').addClass ('ov_dialog_table_row').appendTo (parentDiv);
|
||||
let check = $('<input>').attr ('type', 'checkbox').attr ('checked', 'true').appendTo (line);
|
||||
$('<span>').html (text).appendTo (line);
|
||||
let check = $('<input>').attr ('type', 'checkbox').attr ('checked', 'true').addClass ('ov_dialog_checkradio').attr ('id', id).appendTo (line);
|
||||
$('<label>').attr ('for', id).html (text).appendTo (line);
|
||||
check.change (function () {
|
||||
onChange (check.prop ('checked'));
|
||||
});
|
||||
}
|
||||
|
||||
function GetSharingLink (params)
|
||||
{
|
||||
let builder = OV.CreateUrlBuilder ();
|
||||
builder.AddModelUrls (params.files);
|
||||
builder.AddColor (params.color);
|
||||
let hashParameters = builder.GetParameterList ();
|
||||
return 'https://3dviewer.net#' + hashParameters;
|
||||
}
|
||||
|
||||
function GetEmbeddingCode (params)
|
||||
{
|
||||
let builder = OV.CreateUrlBuilder ();
|
||||
@ -106,6 +116,70 @@ OV.ShowEmbeddingDialog = function (importer, importSettings, camera)
|
||||
return embeddingCode;
|
||||
}
|
||||
|
||||
function AddCopyableTextInput (parentDiv, getText)
|
||||
{
|
||||
let copyText = 'copy';
|
||||
let copiedText = 'copied';
|
||||
let container = $('<div>').addClass ('ov_dialog_copyable_input').appendTo (parentDiv);
|
||||
let input = $('<input>').prop ('readonly', true).appendTo (container);
|
||||
let button = $('<div>').addClass ('button').html (copyText).appendTo (container);
|
||||
button.click (function () {
|
||||
OV.CopyToClipboard (getText ());
|
||||
button.fadeOut (200, function () {
|
||||
button.html (copiedText).fadeIn (200);
|
||||
setTimeout (function () {
|
||||
button.fadeOut (200, function () {
|
||||
button.html (copyText).fadeIn (200);
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
return input;
|
||||
}
|
||||
|
||||
function AddSharingLinkTab (parentDiv, sharingLinkParams)
|
||||
{
|
||||
let section = $('<div>').addClass ('ov_dialog_section').appendTo (parentDiv);
|
||||
$('<div>').html ('Sharing Link').addClass ('ov_dialog_inner_title').appendTo (section);
|
||||
let optionsSection = null;
|
||||
if (OV.FeatureSet.SetDefaultColor) {
|
||||
optionsSection = $('<div>').addClass ('ov_dialog_section').appendTo (section);
|
||||
}
|
||||
let sharingLinkInput = AddCopyableTextInput (section, function () {
|
||||
return GetSharingLink (sharingLinkParams);
|
||||
});
|
||||
if (OV.FeatureSet.SetDefaultColor) {
|
||||
AddCheckboxLine (optionsSection, 'Use overridden default color', 'share_color', function (checked) {
|
||||
sharingLinkParams.color = checked ? importSettings.defaultColor : null;
|
||||
sharingLinkInput.val (GetSharingLink (sharingLinkParams));
|
||||
});
|
||||
sharingLinkParams.color = importSettings.defaultColor;
|
||||
}
|
||||
sharingLinkInput.val (GetSharingLink (sharingLinkParams));
|
||||
}
|
||||
|
||||
function AddEmbeddingCodeTab (parentDiv, embeddingCodeParams)
|
||||
{
|
||||
let section = $('<div>').addClass ('ov_dialog_section').css ('margin-top', '20px').appendTo (parentDiv);
|
||||
$('<div>').html ('Embedding Code').addClass ('ov_dialog_inner_title').appendTo (section);
|
||||
let optionsSection = $('<div>').addClass ('ov_dialog_section').appendTo (section);
|
||||
let embeddingCodeInput = AddCopyableTextInput (section, function () {
|
||||
return GetEmbeddingCode (embeddingCodeParams);
|
||||
});
|
||||
AddCheckboxLine (optionsSection, 'Use current camera position', 'embed_camera', function (checked) {
|
||||
embeddingCodeParams.camera = checked ? camera : null;
|
||||
embeddingCodeInput.val (GetEmbeddingCode (embeddingCodeParams));
|
||||
});
|
||||
if (OV.FeatureSet.SetDefaultColor) {
|
||||
AddCheckboxLine (optionsSection, 'Use overridden default color', 'embed_color', function (checked) {
|
||||
embeddingCodeParams.color = checked ? importSettings.defaultColor : null;
|
||||
embeddingCodeInput.val (GetEmbeddingCode (embeddingCodeParams));
|
||||
});
|
||||
embeddingCodeParams.color = importSettings.defaultColor;
|
||||
}
|
||||
embeddingCodeInput.val (GetEmbeddingCode (embeddingCodeParams));
|
||||
}
|
||||
|
||||
if (!importer.IsOnlyFileSource (OV.FileSource.Url)) {
|
||||
return OV.ShowMessageDialog (
|
||||
'Embedding Failed',
|
||||
@ -121,15 +195,19 @@ OV.ShowEmbeddingDialog = function (importer, importSettings, camera)
|
||||
modelFiles.push (file.fileUrl);
|
||||
}
|
||||
|
||||
let embeddingParams = {
|
||||
let sharingLinkParams = {
|
||||
files : modelFiles,
|
||||
color : null
|
||||
};
|
||||
|
||||
let embeddingCodeParams = {
|
||||
files : modelFiles,
|
||||
camera : camera,
|
||||
color : null
|
||||
};
|
||||
|
||||
let dialog = new OV.ButtonDialog ();
|
||||
let urlsTextArea = $('<textarea>').attr ('readonly', 'true').addClass ('ov_dialog_textarea');
|
||||
let contentDiv = dialog.Init ('Embedding', [
|
||||
let contentDiv = dialog.Init ('Share', [
|
||||
{
|
||||
name : 'Close',
|
||||
onClick () {
|
||||
@ -138,41 +216,8 @@ OV.ShowEmbeddingDialog = function (importer, importSettings, camera)
|
||||
}
|
||||
]);
|
||||
|
||||
let text = 'Embedding options:';
|
||||
$('<div>').html (text).addClass ('ov_dialog_section').appendTo (contentDiv);
|
||||
let optionsSection = $('<div>').addClass ('ov_dialog_section').appendTo (contentDiv);
|
||||
|
||||
AddCheckboxLine (optionsSection, 'Use current camera position', function (checked) {
|
||||
embeddingParams.camera = checked ? camera : null;
|
||||
urlsTextArea.val (GetEmbeddingCode (embeddingParams));
|
||||
});
|
||||
|
||||
if (OV.FeatureSet.SetDefaultColor) {
|
||||
AddCheckboxLine (optionsSection, 'Use overridden default color', function (checked) {
|
||||
embeddingParams.color = checked ? importSettings.defaultColor : null;
|
||||
urlsTextArea.val (GetEmbeddingCode (embeddingParams));
|
||||
});
|
||||
embeddingParams.color = importSettings.defaultColor;
|
||||
}
|
||||
|
||||
urlsTextArea.val (GetEmbeddingCode (embeddingParams));
|
||||
|
||||
urlsTextArea.appendTo (contentDiv);
|
||||
let copyToClipboardText = 'copy to clipboard';
|
||||
let copiedToClipboardText = 'successfully copied';
|
||||
let innerButtonContainer = $('<div>').addClass ('ov_dialog_inner_buttons').appendTo (contentDiv);
|
||||
let copyButton = $('<div>').addClass ('ov_dialog_inner_button').html (copyToClipboardText).appendTo (innerButtonContainer);
|
||||
copyButton.click (function () {
|
||||
OV.CopyToClipboard (urlsTextArea.val ());
|
||||
copyButton.fadeOut (200, function () {
|
||||
copyButton.html (copiedToClipboardText).fadeIn (200);
|
||||
setTimeout (function () {
|
||||
copyButton.fadeOut (200, function () {
|
||||
copyButton.html (copyToClipboardText).fadeIn (200);
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
AddSharingLinkTab (contentDiv, sharingLinkParams);
|
||||
AddEmbeddingCodeTab (contentDiv, embeddingCodeParams);
|
||||
|
||||
dialog.Show ();
|
||||
return dialog;
|
||||
@ -205,6 +250,7 @@ OV.ShowSettingsDialog = function (importSettings, onOk)
|
||||
$('<div>').html ('Default Color').addClass ('ov_dialog_table_row_name').appendTo (colorRow);
|
||||
let valueColumn = $('<div>').addClass ('ov_dialog_table_row_value').appendTo (colorRow);
|
||||
let colorInput = $('<input>').attr ('type', 'color').addClass ('ov_dialog_color').appendTo (valueColumn);
|
||||
$('<span>').addClass ('ov_dialog_table_row_comment').html ('(For surfaces with no material)').appendTo (valueColumn);
|
||||
colorInput.val ('#' + OV.ColorToHexString (dialogSettings.defaultColor));
|
||||
colorInput.change (function () {
|
||||
let colorStr = colorInput.val ().substr (1);
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
OV.ExportType =
|
||||
{
|
||||
Model : 1,
|
||||
Image : 2
|
||||
};
|
||||
|
||||
OV.ExportDialog = class
|
||||
{
|
||||
constructor (callbacks)
|
||||
@ -8,34 +14,47 @@ OV.ExportDialog = class
|
||||
{
|
||||
name : 'obj',
|
||||
formats : [
|
||||
{ name : 'text', format : OV.FileFormat.Text, extension : 'obj' }
|
||||
{ name : 'text', type: OV.ExportType.Model, format : OV.FileFormat.Text, extension : 'obj' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name : 'stl',
|
||||
formats : [
|
||||
{ name : 'text', format : OV.FileFormat.Text, extension : 'stl' },
|
||||
{ name : 'binary', format : OV.FileFormat.Binary, extension : 'stl' }
|
||||
{ name : 'text', type: OV.ExportType.Model, format : OV.FileFormat.Text, extension : 'stl' },
|
||||
{ name : 'binary', type: OV.ExportType.Model, format : OV.FileFormat.Binary, extension : 'stl' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name : 'ply',
|
||||
formats : [
|
||||
{ name : 'text', format : OV.FileFormat.Text, extension : 'ply' },
|
||||
{ name : 'binary', format : OV.FileFormat.Binary, extension : 'ply' }
|
||||
{ name : 'text', type: OV.ExportType.Model, format : OV.FileFormat.Text, extension : 'ply' },
|
||||
{ name : 'binary', type: OV.ExportType.Model, format : OV.FileFormat.Binary, extension : 'ply' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name : 'gltf',
|
||||
formats : [
|
||||
{ name : 'text', format : OV.FileFormat.Text, extension : 'gltf' },
|
||||
{ name : 'binary', format : OV.FileFormat.Binary, extension : 'glb' }
|
||||
{ name : 'text', type: OV.ExportType.Model, format : OV.FileFormat.Text, extension : 'gltf' },
|
||||
{ name : 'binary', type: OV.ExportType.Model, format : OV.FileFormat.Binary, extension : 'glb' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name : 'off',
|
||||
formats : [
|
||||
{ name : 'text', format : OV.FileFormat.Text, extension : 'off' }
|
||||
{ name : 'text', type: OV.ExportType.Model, format : OV.FileFormat.Text, extension : 'off' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name : '3dm',
|
||||
formats : [
|
||||
{ name : 'binary', type: OV.ExportType.Model, format : OV.FileFormat.Binary, extension : '3dm' }
|
||||
]
|
||||
},
|
||||
{
|
||||
name : 'png',
|
||||
formats : [
|
||||
{ name : 'current size', type: OV.ExportType.Image, width : null, height : null, extension : 'png' },
|
||||
{ name : 'fixed size (1920x1080)', type: OV.ExportType.Image, width : 1920, height : 1080, extension : 'png' }
|
||||
]
|
||||
}
|
||||
];
|
||||
@ -46,7 +65,7 @@ OV.ExportDialog = class
|
||||
};
|
||||
}
|
||||
|
||||
Show (model)
|
||||
Show (model, viewer)
|
||||
{
|
||||
if (model === null) {
|
||||
let messageDialog = OV.ShowMessageDialog (
|
||||
@ -76,7 +95,7 @@ OV.ExportDialog = class
|
||||
return;
|
||||
}
|
||||
mainDialog.Hide ();
|
||||
obj.ExportFormat (model);
|
||||
obj.ExportFormat (model, viewer);
|
||||
}
|
||||
}
|
||||
]);
|
||||
@ -119,7 +138,7 @@ OV.ExportDialog = class
|
||||
for (let i = 0; i < exportFormat.formats.length; i++) {
|
||||
let format = exportFormat.formats[i];
|
||||
let formatDiv = $('<div>').addClass ('ov_dialog_table_row').appendTo (this.formatParameters.formatSettingsDiv);
|
||||
let formatInput = $('<input>').addClass ('ov_dialog_table_radio').attr ('type', 'radio').attr ('id', format.name).attr ('name', 'format').appendTo (formatDiv);
|
||||
let formatInput = $('<input>').addClass ('ov_dialog_checkradio').attr ('type', 'radio').attr ('id', format.name).attr ('name', 'format').appendTo (formatDiv);
|
||||
$('<label>').attr ('for', format.name).html (format.name).appendTo (formatDiv);
|
||||
if (i === 0) {
|
||||
formatInput.prop ('checked', true);
|
||||
@ -131,30 +150,48 @@ OV.ExportDialog = class
|
||||
}
|
||||
}
|
||||
|
||||
ExportFormat (model)
|
||||
ExportFormat (model, viewer)
|
||||
{
|
||||
let format = this.formatParameters.selectedFormat;
|
||||
if (format === null) {
|
||||
let selectedFormat = this.formatParameters.selectedFormat;
|
||||
if (selectedFormat === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let obj = this;
|
||||
let progressDialog = new OV.ProgressDialog ();
|
||||
progressDialog.Show ('Exporting Model');
|
||||
OV.RunTaskAsync (function () {
|
||||
let exporter = new OV.Exporter ();
|
||||
let files = exporter.Export (model, format.format, format.extension);
|
||||
if (files.length === 0) {
|
||||
progressDialog.Hide ();
|
||||
} else if (files.length === 1) {
|
||||
progressDialog.Hide ();
|
||||
let file = files[0];
|
||||
OV.DownloadArrayBufferAsFile (file.GetContent (), file.GetName ());
|
||||
} else if (files.length > 1) {
|
||||
progressDialog.Hide ();
|
||||
obj.ShowExportedFiles (files);
|
||||
if (selectedFormat.type === OV.ExportType.Model) {
|
||||
let obj = this;
|
||||
let progressDialog = new OV.ProgressDialog ();
|
||||
progressDialog.Show ('Exporting Model');
|
||||
OV.RunTaskAsync (function () {
|
||||
let exporter = new OV.Exporter ();
|
||||
exporter.AddExporter (new OV.Exporter3dm ());
|
||||
exporter.Export (model, selectedFormat.format, selectedFormat.extension, {
|
||||
onError : function () {
|
||||
progressDialog.Hide ();
|
||||
},
|
||||
onSuccess : function (files) {
|
||||
if (files.length === 0) {
|
||||
progressDialog.Hide ();
|
||||
} else if (files.length === 1) {
|
||||
progressDialog.Hide ();
|
||||
let file = files[0];
|
||||
OV.DownloadArrayBufferAsFile (file.GetContent (), file.GetName ());
|
||||
} else if (files.length > 1) {
|
||||
progressDialog.Hide ();
|
||||
obj.ShowExportedFiles (files);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else if (selectedFormat.type === OV.ExportType.Image) {
|
||||
let url = null;
|
||||
if (selectedFormat.width === null || selectedFormat.height === null) {
|
||||
let size = viewer.GetImageSize ();
|
||||
url = viewer.GetImageAsDataUrl (size.width, size.height);
|
||||
} else {
|
||||
url = viewer.GetImageAsDataUrl (selectedFormat.width, selectedFormat.height);
|
||||
}
|
||||
});
|
||||
OV.DownloadUrlAsFile (url, 'model.' + selectedFormat.extension);
|
||||
}
|
||||
}
|
||||
|
||||
ShowExportedFiles (files)
|
||||
|
||||
@ -5,7 +5,7 @@ OV.InitModelLoader = function (modelLoader, callbacks)
|
||||
if (importError.code === OV.ImportErrorCode.NoImportableFile) {
|
||||
return OV.ShowMessageDialog (
|
||||
'Something went wrong',
|
||||
'No importable file found. You can open obj, 3ds, stl, ply, gltf, glb and off files.',
|
||||
'No importable file found. You can open obj, 3ds, stl, ply, gltf, glb, 3dm, and off files.',
|
||||
importError.message
|
||||
);
|
||||
} else if (importError.code === OV.ImportErrorCode.ImportFailed) {
|
||||
|
||||
@ -100,16 +100,22 @@ OV.CopyToClipboard = function (text)
|
||||
document.body.removeChild (input);
|
||||
};
|
||||
|
||||
OV.DownloadArrayBufferAsFile = function (arrayBuffer, fileName)
|
||||
OV.DownloadUrlAsFile = function (url, fileName)
|
||||
{
|
||||
let link = document.createElement ('a');
|
||||
link.href = OV.CreateObjectUrl (arrayBuffer);
|
||||
link.href = url;
|
||||
link.download = fileName;
|
||||
document.body.appendChild (link);
|
||||
link.click ();
|
||||
document.body.removeChild (link);
|
||||
};
|
||||
|
||||
OV.DownloadArrayBufferAsFile = function (arrayBuffer, fileName)
|
||||
{
|
||||
let url = OV.CreateObjectUrl (arrayBuffer);
|
||||
OV.DownloadUrlAsFile (url, fileName);
|
||||
};
|
||||
|
||||
OV.CreateIconButton = function (iconName, hoverIconName, title, link)
|
||||
{
|
||||
let buttonLink = $('<a>');
|
||||
|
||||
@ -385,6 +385,12 @@ div.ov_dialog div.ov_dialog_title
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.ov_dialog div.ov_dialog_inner_title
|
||||
{
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
div.ov_dialog div.ov_dialog_content
|
||||
{
|
||||
padding: 20px 0px;
|
||||
@ -477,6 +483,7 @@ div.ov_dialog input.ov_dialog_color
|
||||
{
|
||||
width: 36px;
|
||||
height: 18px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
div.ov_dialog div.ov_dialog_file_list
|
||||
@ -506,6 +513,39 @@ div.ov_dialog div.ov_dialog_file_link_text
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.ov_dialog div.ov_dialog_copyable_input
|
||||
{
|
||||
padding: 3px;
|
||||
border: 1px solid #dddddd;
|
||||
border-radius: 5px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
div.ov_dialog div.ov_dialog_copyable_input input
|
||||
{
|
||||
color: #666666;
|
||||
width: 70%;
|
||||
margin-top: 6px;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
float: left;
|
||||
border: 0px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
div.ov_dialog div.ov_dialog_copyable_input div.button
|
||||
{
|
||||
color: #3393bd;
|
||||
width: 28%;
|
||||
text-align: center;
|
||||
padding: 3px;
|
||||
border: 1px solid #3393bd;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
}
|
||||
|
||||
div.ov_dialog div.ov_dialog_inner_buttons
|
||||
{
|
||||
margin-bottom: 10px;
|
||||
@ -536,7 +576,13 @@ div.ov_dialog div.ov_dialog_table_row_value
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.ov_dialog input.ov_dialog_table_radio
|
||||
div.ov_dialog span.ov_dialog_table_row_comment
|
||||
{
|
||||
color: #444444;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
div.ov_dialog input.ov_dialog_checkradio
|
||||
{
|
||||
margin-right: 10px;
|
||||
}
|
||||
@ -672,7 +718,6 @@ div.intro div.intro_section
|
||||
{
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
margin: 20px 0px;
|
||||
}
|
||||
|
||||
div.intro div.intro_big_text
|
||||
@ -709,7 +754,7 @@ div.ov_progress
|
||||
|
||||
div.intro div.intro_section
|
||||
{
|
||||
margin: 20px 0px;
|
||||
margin: 15px 0px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ OV.Website = class
|
||||
OnModelClicked (button, isCtrlPressed, mouseCoordinates)
|
||||
{
|
||||
if (button === 1) {
|
||||
let meshUserData = this.viewer.GetMeshUnderMouse (mouseCoordinates);
|
||||
let meshUserData = this.viewer.GetMeshUserDataUnderMouse (mouseCoordinates);
|
||||
if (meshUserData === null) {
|
||||
this.menu.SetSelection (null);
|
||||
} else {
|
||||
@ -285,10 +285,10 @@ OV.Website = class
|
||||
obj.dialog = dialog;
|
||||
}
|
||||
});
|
||||
exportDialog.Show (obj.model);
|
||||
exportDialog.Show (obj.model, obj.viewer);
|
||||
});
|
||||
AddButton (this.toolbar, 'embed', 'Get embedding code', true, function () {
|
||||
obj.dialog = OV.ShowEmbeddingDialog (importer, obj.importSettings, obj.viewer.GetCamera ());
|
||||
AddButton (this.toolbar, 'share', 'Share model', true, function () {
|
||||
obj.dialog = OV.ShowSharingDialog (importer, obj.importSettings, obj.viewer.GetCamera ());
|
||||
});
|
||||
if (OV.FeatureSet.SetDefaultColor) {
|
||||
AddSeparator (this.toolbar, true);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user