Merge branch 'dev'

This commit is contained in:
Viktor Kovacs 2021-04-04 12:22:11 +02:00
commit c03663ebf5
26 changed files with 559 additions and 172 deletions

View File

@ -1,15 +1,18 @@
# Online 3D Viewer
This repository contains the source code of the https://3dviewer.net website. The website can open several 3D file formats and visualize the model in your browser.
Online 3D Viewer (https://3dviewer.net) is a free and open source web solution to visualize and explore 3D models right in your browser. This repository contains the source code of the website and the library behind it.
[![Build status](https://ci.appveyor.com/api/projects/status/exypq43a8kjby5n0?svg=true)](https://ci.appveyor.com/project/kovacsv/online3dviewer)
[![Build Status](https://travis-ci.com/kovacsv/Online3DViewer.svg?branch=master)](https://travis-ci.com/kovacsv/Online3DViewer)
[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/kovacsv/Online3DViewer.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/kovacsv/Online3DViewer/context:javascript)
[![codecov](https://codecov.io/gh/kovacsv/Online3DViewer/branch/master/graph/badge.svg?token=xD8Kek6gQz)](https://codecov.io/gh/kovacsv/Online3DViewer)
## Documentation
- [User Documentation](https://3dviewer.net/info)
- [Developer Documentation](https://github.com/kovacsv/Online3DViewer/wiki)
The repository is separated into two parts. See more information in the [Developer Documentation](https://github.com/kovacsv/Online3DViewer/wiki).
* **Online 3D Viewer Website**: Source code of the web solution with all of the pages and functions.
* **Online 3D Viewer Engine**: Source code of the library to visualize models easily.
## Supported file formats

4
codecov.yml Normal file
View File

@ -0,0 +1,4 @@
coverage:
range: 50..80
round: down
precision: 0

View File

@ -1,7 +1,7 @@
{
"name": "online-3d-viewer",
"description": "Online 3D Viewer",
"version": "0.7.4",
"version": "0.7.5",
"repository": "github:kovacsv/Online3DViewer",
"license": "MIT",
"devDependencies": {

View File

@ -12,6 +12,11 @@ OV.ThreeModelLoader = class
this.callbacks = callbacks;
}
SetDefaultColor (defaultColor)
{
this.importer.SetDefaultColor (defaultColor);
}
LoadFromUrlList (urls)
{
if (this.inProgress) {
@ -39,11 +44,22 @@ OV.ThreeModelLoader = class
obj.OnFilesLoaded ();
});
}
ReloadFiles ()
{
if (this.inProgress) {
return;
}
this.inProgress = true;
this.callbacks.onLoadStart ();
this.OnFilesLoaded ();
}
OnFilesLoaded ()
{
let obj = this;
this.callbacks.onFilesLoaded ();
this.callbacks.onImportStart ();
OV.RunTaskAsync (function () {
obj.importer.Import ({
success : function (importResult) {
@ -60,7 +76,7 @@ OV.ThreeModelLoader = class
OnModelImported (importResult)
{
let obj = this;
this.callbacks.onModelImported ();
this.callbacks.onVisualizationStart ();
OV.ConvertModelToThreeMeshes (importResult.model, {
onTextureLoaded : function () {
obj.callbacks.onTextureLoaded ();

View File

@ -260,6 +260,7 @@ OV.Importer = class
new OV.ImporterGltf ()
];
this.fileList = new OV.FileList (this.importers);
this.defaultColor = new OV.Color (200, 200, 200);
this.model = null;
this.usedFiles = [];
this.missingFiles = [];
@ -275,6 +276,11 @@ OV.Importer = class
this.LoadFiles (fileList, OV.FileSource.File, onReady);
}
SetDefaultColor (defaultColor)
{
this.defaultColor = defaultColor;
}
Import (callbacks)
{
let mainFile = this.fileList.GetMainFile ();
@ -310,7 +316,7 @@ OV.Importer = class
importer.Import (mainFile.file.content, mainFile.file.extension, {
getDefaultMaterial : function () {
let material = new OV.Material ();
material.diffuse = new OV.Color (200, 200, 200);
material.diffuse = obj.defaultColor;
return material;
},
getFileBuffer : function (filePath) {

View File

@ -1,20 +1,30 @@
OV.UrlParamConverter =
OV.ParameterConverter =
{
CameraToUrlParameter : function (camera)
NumberToString (number)
{
let precision = 5;
return number.toPrecision (precision);
},
StringToNumber (str)
{
return parseFloat (str);
},
CameraToString : function (camera)
{
if (camera === null) {
return null;
}
let precision = 5;
let cameraParameters = [
camera.eye.x.toPrecision (precision), camera.eye.y.toPrecision (precision), camera.eye.z.toPrecision (precision),
camera.center.x.toPrecision (precision), camera.center.y.toPrecision (precision), camera.center.z.toPrecision (precision),
camera.up.x.toPrecision (precision), camera.up.y.toPrecision (precision), camera.up.z.toPrecision (precision)
this.NumberToString (camera.eye.x), this.NumberToString (camera.eye.y), this.NumberToString (camera.eye.z),
this.NumberToString (camera.center.x), this.NumberToString (camera.center.y), this.NumberToString (camera.center.z),
this.NumberToString (camera.up.x), this.NumberToString (camera.up.y), this.NumberToString (camera.up.z)
].join (',');
return cameraParameters;
},
UrlParameterToCamera : function (urlParam)
StringToCamera : function (urlParam)
{
if (urlParam === null || urlParam.length === 0) {
return null;
@ -24,14 +34,14 @@ OV.UrlParamConverter =
return null;
}
let camera = new OV.Camera (
new OV.Coord3D (parseFloat (paramParts[0]), parseFloat (paramParts[1]), parseFloat (paramParts[2])),
new OV.Coord3D (parseFloat (paramParts[3]), parseFloat (paramParts[4]), parseFloat (paramParts[5])),
new OV.Coord3D (parseFloat (paramParts[6]), parseFloat (paramParts[7]), parseFloat (paramParts[8]))
new OV.Coord3D (this.StringToNumber (paramParts[0]), this.StringToNumber (paramParts[1]), this.StringToNumber (paramParts[2])),
new OV.Coord3D (this.StringToNumber (paramParts[3]), this.StringToNumber (paramParts[4]), this.StringToNumber (paramParts[5])),
new OV.Coord3D (this.StringToNumber (paramParts[6]), this.StringToNumber (paramParts[7]), this.StringToNumber (paramParts[8]))
);
return camera;
},
ModelUrlsToUrlParameter : function (urls)
ModelUrlsToString : function (urls)
{
if (urls === null) {
return null;
@ -39,7 +49,7 @@ OV.UrlParamConverter =
return urls.join (',');
},
UrlParameterToModelUrls : function (urlParam)
StringToModelUrls : function (urlParam)
{
if (urlParam === null || urlParam.length === 0) {
return null;
@ -48,22 +58,23 @@ OV.UrlParamConverter =
}
};
OV.UrlParamBuilder = class
OV.ParameterListBuilder = class
{
constructor ()
constructor (separator)
{
this.separator = separator;
this.urlParams = '';
}
AddModelUrls (urls)
{
this.AddUrlPart ('model', OV.UrlParamConverter.ModelUrlsToUrlParameter (urls));
this.AddUrlPart ('model', OV.ParameterConverter.ModelUrlsToString (urls));
return this;
}
AddCamera (camera)
{
this.AddUrlPart ('camera', OV.UrlParamConverter.CameraToUrlParameter (camera));
this.AddUrlPart ('camera', OV.ParameterConverter.CameraToString (camera));
return this;
}
@ -73,7 +84,7 @@ OV.UrlParamBuilder = class
return;
}
if (this.urlParams.length > 0) {
this.urlParams += '$';
this.urlParams += this.separator;
}
this.urlParams += keyword + '=' + urlPart;
}
@ -84,10 +95,11 @@ OV.UrlParamBuilder = class
}
};
OV.UrlParamParser = class
OV.ParameterListParser = class
{
constructor (urlParams)
constructor (urlParams, separator)
{
this.separator = separator;
this.urlParams = urlParams;
}
@ -99,13 +111,13 @@ OV.UrlParamParser = class
}
let keywordParams = this.GetKeywordParams ('model');
return OV.UrlParamConverter.UrlParameterToModelUrls (keywordParams);
return OV.ParameterConverter.StringToModelUrls (keywordParams);
}
GetCamera ()
{
let keywordParams = this.GetKeywordParams ('camera');
return OV.UrlParamConverter.UrlParameterToCamera (keywordParams);
return OV.ParameterConverter.StringToCamera (keywordParams);
}
GetKeywordParams (keyword)
@ -114,7 +126,7 @@ OV.UrlParamParser = class
return null;
}
let keywordToken = keyword + '=';
let urlParts = this.urlParams.split ('$');
let urlParts = this.urlParams.split (this.separator);
for (let i = 0; i < urlParts.length; i++) {
let urlPart = urlParts[i];
if (urlPart.startsWith (keywordToken)) {
@ -125,9 +137,19 @@ OV.UrlParamParser = class
}
};
OV.CreateUrlBuilder = function ()
{
return new OV.ParameterListBuilder ('$');
};
OV.CreateUrlParser = function (urlParams)
{
return new OV.ParameterListParser (urlParams, '$');
};
OV.CreateUrlParameters = function (urls, camera)
{
let builder = new OV.UrlParamBuilder ();
let builder = OV.CreateUrlBuilder ();
builder.AddModelUrls (urls);
builder.AddCamera (camera);
return builder.GetUrlParams ();

View File

@ -1,5 +1,19 @@
OV.Init3DViewerElements = function ()
{
function SetCamera (element, viewer, importResult)
{
let camera = null;
let cameraParams = element.getAttribute ('camera');
if (cameraParams) {
camera = OV.ParameterConverter.StringToCamera (cameraParams);
}
if (camera !== null) {
viewer.SetCamera (camera);
} else {
viewer.SetUpVector (importResult.upVector, false);
}
}
function LoadElement (element)
{
let canvas = document.createElement ('canvas');
@ -8,10 +22,9 @@ OV.Init3DViewerElements = function ()
let viewer = new OV.Viewer ();
viewer.Init (canvas);
let width = parseInt (element.getAttribute ('width'));
let height = parseInt (element.getAttribute ('height'));
element.style.width = width + 'px';
element.style.height = height + 'px';
let width = element.clientWidth;
let height = element.clientHeight;
console.log (element.clientHeight);
viewer.Resize (width, height);
let loader = new OV.ThreeModelLoader ();
@ -23,20 +36,21 @@ OV.Init3DViewerElements = function ()
element.appendChild (progressDiv);
progressDiv.innerHTML = 'Loading model...';
},
onFilesLoaded : function () {
onImportStart : function () {
progressDiv.innerHTML = 'Importing model...';
},
onModelImported : function () {
onVisualizationStart : function () {
progressDiv.innerHTML = 'Visualizing model...';
},
onModelFinished : function (importResult, threeMeshes) {
element.removeChild (progressDiv);
canvas.style.display = 'initial';
canvas.style.display = 'inherit';
viewer.AddMeshes (threeMeshes);
let boundingSphere = viewer.GetBoundingSphere (function (meshUserData) {
return true;
});
viewer.AdjustClippingPlanes (boundingSphere);
SetCamera (element, viewer, importResult);
viewer.FitToWindow (boundingSphere, false);
},
onTextureLoaded : function () {
@ -52,27 +66,34 @@ OV.Init3DViewerElements = function ()
return;
}
let modelUrls = OV.UrlParamConverter.UrlParameterToModelUrls (modelParams);
let modelUrls = OV.ParameterConverter.StringToModelUrls (modelParams);
if (modelUrls === null || modelUrls.length === 0) {
return;
}
let cameraParams = element.getAttribute ('camera');
if (cameraParams) {
let camera = OV.UrlParamConverter.UrlParameterToCamera (cameraParams);
if (camera !== null) {
viewer.SetCamera (camera);
}
}
loader.LoadFromUrlList (modelUrls);
return {
element: element,
viewer: viewer
};
}
let viewerElements = [];
window.addEventListener ('load', function () {
let elements = document.getElementsByClassName ('online_3d_viewer');
for (let i = 0; i < elements.length; i++) {
let element = elements[i];
LoadElement (element);
let viewerElement = LoadElement (element);
viewerElements.push (viewerElement);
}
});
window.addEventListener ('resize', function () {
for (let i = 0; i < viewerElements.length; i++) {
let viewerElement = viewerElements[i];
let width = viewerElement.element.clientWidth;
let height = viewerElement.element.clientHeight;
viewerElement.viewer.Resize (width, height);
}
});
};

View File

@ -233,4 +233,24 @@ describe ('Importer Test', function () {
}
});
});
it ('Default color', function () {
let files = [
new FileObject ('stl', 'single_triangle.stl')
];
let theImporter = new OV.Importer ();
theImporter.SetDefaultColor (new OV.Color (200, 0, 0));
ImportFilesWithImporter (theImporter, files, {
success : function (importer, 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));
},
error : function (importer, importError) {
assert.fail ();
}
});
});
});

View File

@ -1,22 +1,22 @@
var assert = require ('assert');
describe ('Url Utils', function () {
it ('Url builder', function () {
describe ('Parameter List', function () {
it ('Parameter list builder', function () {
let modelUrls = ['a.txt', 'b.txt'];
let camera = new OV.Camera (
new OV.Coord3D (1.0, 1.0, 1.0),
new OV.Coord3D (0.0, 0.0, 0.0),
new OV.Coord3D (0.0, 0.0, 1.0)
);
let urlParams1 = new OV.UrlParamBuilder ().AddModelUrls (modelUrls).GetUrlParams ();
let urlParams2 = new OV.UrlParamBuilder ().AddCamera (camera).GetUrlParams ();
let urlParams3 = new OV.UrlParamBuilder ().AddModelUrls (modelUrls).AddCamera (camera).GetUrlParams ();
let urlParams1 = OV.CreateUrlBuilder ().AddModelUrls (modelUrls).GetUrlParams ();
let urlParams2 = OV.CreateUrlBuilder ().AddCamera (camera).GetUrlParams ();
let urlParams3 = OV.CreateUrlBuilder ().AddModelUrls (modelUrls).AddCamera (camera).GetUrlParams ();
assert.strictEqual (urlParams1, 'model=a.txt,b.txt');
assert.strictEqual (urlParams2, 'camera=1.0000,1.0000,1.0000,0.0000,0.0000,0.0000,0.0000,0.0000,1.0000');
assert.strictEqual (urlParams3, 'model=a.txt,b.txt$camera=1.0000,1.0000,1.0000,0.0000,0.0000,0.0000,0.0000,0.0000,1.0000');
});
it ('Url parser', function () {
it ('Parameter list parser', function () {
let modelUrls = ['a.txt', 'b.txt'];
let camera = new OV.Camera (
new OV.Coord3D (1.0, 1.0, 1.0),
@ -27,16 +27,16 @@ describe ('Url Utils', function () {
let urlParams1 = 'model=a.txt,b.txt';
let urlParams2 = 'camera=1.0000,1.0000,1.0000,0.0000,0.0000,0.0000,0.0000,0.0000,1.0000';
let urlParams3 = 'model=a.txt,b.txt$camera=1.0000,1.0000,1.0000,0.0000,0.0000,0.0000,0.0000,0.0000,1.0000';
let parserLegacy = new OV.UrlParamParser (urlParamsLegacy);
let parserLegacy = OV.CreateUrlParser (urlParamsLegacy);
assert.deepStrictEqual (parserLegacy.GetModelUrls (), modelUrls);
assert.deepStrictEqual (parserLegacy.GetCamera (), null);
let parser1 = new OV.UrlParamParser (urlParams1);
let parser1 = OV.CreateUrlParser (urlParams1);
assert.deepStrictEqual (parser1.GetModelUrls (), modelUrls);
assert.deepStrictEqual (parser1.GetCamera (), null);
let parser2 = new OV.UrlParamParser (urlParams2);
let parser2 = OV.CreateUrlParser (urlParams2);
assert.deepStrictEqual (parser2.GetModelUrls (), null);
assert.deepStrictEqual (parser2.GetCamera (), camera);
let parser3 = new OV.UrlParamParser (urlParams3);
let parser3 = OV.CreateUrlParser (urlParams3);
assert.deepStrictEqual (parser3.GetModelUrls (), modelUrls);
assert.deepStrictEqual (parser3.GetCamera (), camera);
});

View File

@ -42,11 +42,11 @@
"source/export/exporter.js",
"source/external/three.converter.js",
"source/external/three.model.loader.js",
"source/parameters/parameterlist.js",
"source/viewer/domutils.js",
"source/viewer/navigation.js",
"source/viewer/viewer.js",
"source/viewer/domviewer.js",
"source/viewer/urlutils.js"
"source/viewer/domviewer.js"
],
"website_files" : [
"website/o3dv/utils.js",

View File

@ -60,7 +60,13 @@ def CreateDestinationDir (config, rootDir, websiteDir, version, testBuild):
'o3dv/o3dv.website.min.js'
]
for htmlFileName in ['index.html', 'embed.html', os.path.join ('info', 'index.html')]:
htmlFileNames = [
'index.html',
'embed.html',
os.path.join ('info', 'index.html'),
os.path.join ('info', 'cookies.html')
]
for htmlFileName in htmlFileNames:
htmlFilePath = os.path.join (websiteDir, htmlFileName)
replacer = Tools.TokenReplacer (htmlFilePath, False)
replacer.ReplaceTokenFileLinks ('<!-- libs start -->', '<!-- libs end -->', libFiles, None)

View File

@ -2,34 +2,39 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="icon" type="image/png" href="assets/images/3dviewer_net_favicon.png">
<title>Online 3D Viewer</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="icon" type="image/png" href="assets/images/3dviewer_net_favicon.png">
<title>Online 3D Viewer</title>
</head>
<body>
<iframe
src="../../website/embed.html#model=../test/testfiles/3ds/cube_four_instances.3ds,../test/testfiles/3ds/texture.png"
width=400 height=300
style="border:1px solid #eeeeee;">
</iframe>
<iframe
src="../../website/embed.html#model=../test/testfiles/3ds/cube_four_instances.3ds,../test/testfiles/3ds/texture.png$camera=3.929421317669367,6.153966358575169,2.7076091223424714,1.5,1.5,0.5,0,0,1"
width=400 height=300
style="border:1px solid #eeeeee;">
</iframe>
<iframe
src="../../website/embed.html#model=../test/testfiles/obj/hundred_cubes.obj,../test/testfiles/obj/hundred_cubes.mtl"
width=400 height=300
style="border:1px solid #eeeeee;">
</iframe>
<iframe
src="../../website/embed.html#model=wrong.3ds"
width=400 height=300
style="border:1px solid #eeeeee;">
</iframe>
<iframe
src="../../website/embed.html#model=../test/testfiles/3ds/cube_four_instances.3ds,../test/testfiles/3ds/texture.png"
width=360 height=240
style="border:1px solid #eeeeee;">
</iframe>
<iframe
src="../../website/embed.html#model=../test/testfiles/obj/hundred_cubes.obj,../test/testfiles/obj/hundred_cubes.mtl"
width=360 height=240
style="border:1px solid #eeeeee;">
</iframe>
<iframe
src="../../website/embed.html#model=../test/testfiles/3ds/cube_four_instances.3ds,../test/testfiles/3ds/texture.png$camera=3.929421317669367,6.153966358575169,2.7076091223424714,1.5,1.5,0.5,0,0,1"
width=360 height=240
style="border:1px solid #eeeeee;">
</iframe>
<iframe
src="../../website/embed.html#model=../test/testfiles/obj/hundred_cubes.obj,../test/testfiles/obj/hundred_cubes.mtl$camera=1,1,1,0,0,0,0,0,1"
width=360 height=240
style="border:1px solid #eeeeee;">
</iframe>
<iframe
src="../../website/embed.html#model=wrong.3ds"
width=360 height=240
style="border:1px solid #eeeeee;">
</iframe>
</body>
</html>

View File

@ -1,37 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="icon" type="image/png" href="assets/images/3dviewer_net_favicon.png">
<title>Online 3D Viewer</title>
<script type="text/javascript" src="../../libs/three.min-126.js"></script>
<script type="text/javascript" src="../../build/final/website/o3dv/o3dv.min.js"></script>
<script type='text/javascript'>
OV.Init3DViewerElements ();
</script>
<style>
div.online_3d_viewer
{
float: left;
}
</style>
</head>
<body>
<div class="online_3d_viewer" width="400" height="300" model="../../test/testfiles/3ds/cube_four_instances.3ds,../../test/testfiles/3ds/texture.png"></div>
<div class="online_3d_viewer"
width="400" height="300"
model="../../test/testfiles/3ds/cube_four_instances.3ds,../../test/testfiles/3ds/texture.png"
camera="-1.5,-3.0,2.0,0,0,0,0,0,1">
</div>
<div class="online_3d_viewer" width="400" height="300" model="../../test/testfiles/obj/hundred_cubes.obj,../../test/testfiles/obj/hundred_cubes.mtl"></div>
<div class="online_3d_viewer" width="400" height="300" model="wrong.3ds"></div>
</body>
</html>

View File

@ -0,0 +1,80 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<title>Online 3D Viewer</title>
<script type="text/javascript" src="../../libs/three.min-126.js"></script>
<!-- importer start -->
<script type="text/javascript" src="../../source/core/core.js"></script>
<script type="text/javascript" src="../../source/core/taskrunner.js"></script>
<script type="text/javascript" src="../../source/geometry/geometry.js"></script>
<script type="text/javascript" src="../../source/geometry/coord2d.js"></script>
<script type="text/javascript" src="../../source/geometry/coord3d.js"></script>
<script type="text/javascript" src="../../source/geometry/matrix.js"></script>
<script type="text/javascript" src="../../source/geometry/transformation.js"></script>
<script type="text/javascript" src="../../source/geometry/tween.js"></script>
<script type="text/javascript" src="../../source/io/binaryreader.js"></script>
<script type="text/javascript" src="../../source/io/binarywriter.js"></script>
<script type="text/javascript" src="../../source/io/textwriter.js"></script>
<script type="text/javascript" src="../../source/io/bufferutils.js"></script>
<script type="text/javascript" src="../../source/io/fileutils.js"></script>
<script type="text/javascript" src="../../source/model/modelentities.js"></script>
<script type="text/javascript" src="../../source/model/mesh.js"></script>
<script type="text/javascript" src="../../source/model/meshbuffer.js"></script>
<script type="text/javascript" src="../../source/model/model.js"></script>
<script type="text/javascript" src="../../source/model/modelutils.js"></script>
<script type="text/javascript" src="../../source/model/modelfinalization.js"></script>
<script type="text/javascript" src="../../source/import/importerutils.js"></script>
<script type="text/javascript" src="../../source/import/importerbase.js"></script>
<script type="text/javascript" src="../../source/import/importerobj.js"></script>
<script type="text/javascript" src="../../source/import/importerstl.js"></script>
<script type="text/javascript" src="../../source/import/importeroff.js"></script>
<script type="text/javascript" src="../../source/import/importerply.js"></script>
<script type="text/javascript" src="../../source/import/importer3ds.js"></script>
<script type="text/javascript" src="../../source/import/importergltf.js"></script>
<script type="text/javascript" src="../../source/import/importer.js"></script>
<script type="text/javascript" src="../../source/export/exporterutils.js"></script>
<script type="text/javascript" src="../../source/export/exporterbase.js"></script>
<script type="text/javascript" src="../../source/export/exporterobj.js"></script>
<script type="text/javascript" src="../../source/export/exporterstl.js"></script>
<script type="text/javascript" src="../../source/export/exporterply.js"></script>
<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/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>
<script type="text/javascript" src="../../source/viewer/domutils.js"></script>
<script type="text/javascript" src="../../source/viewer/navigation.js"></script>
<script type="text/javascript" src="../../source/viewer/viewer.js"></script>
<script type="text/javascript" src="../../source/viewer/domviewer.js"></script>
<!-- importer end -->
<script type='text/javascript'>
OV.Init3DViewerElements ();
</script>
<style>
html, body
{
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div class="online_3d_viewer"
style="width: 100%; height: 100%;"
model="../../test/testfiles/obj/hundred_cubes.obj,../../test/testfiles/obj/hundred_cubes.mtl"
camera="3,1,2,0,0,0,0,0,1">
</div>
</body>
</html>

View File

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="icon" type="image/png" href="assets/images/3dviewer_net_favicon.png">
<title>Online 3D Viewer</title>
<script type="text/javascript" src="../../libs/three.min-126.js"></script>
<!-- importer start -->
<script type="text/javascript" src="../../source/core/core.js"></script>
<script type="text/javascript" src="../../source/core/taskrunner.js"></script>
<script type="text/javascript" src="../../source/geometry/geometry.js"></script>
<script type="text/javascript" src="../../source/geometry/coord2d.js"></script>
<script type="text/javascript" src="../../source/geometry/coord3d.js"></script>
<script type="text/javascript" src="../../source/geometry/matrix.js"></script>
<script type="text/javascript" src="../../source/geometry/transformation.js"></script>
<script type="text/javascript" src="../../source/geometry/tween.js"></script>
<script type="text/javascript" src="../../source/io/binaryreader.js"></script>
<script type="text/javascript" src="../../source/io/binarywriter.js"></script>
<script type="text/javascript" src="../../source/io/textwriter.js"></script>
<script type="text/javascript" src="../../source/io/bufferutils.js"></script>
<script type="text/javascript" src="../../source/io/fileutils.js"></script>
<script type="text/javascript" src="../../source/model/modelentities.js"></script>
<script type="text/javascript" src="../../source/model/mesh.js"></script>
<script type="text/javascript" src="../../source/model/meshbuffer.js"></script>
<script type="text/javascript" src="../../source/model/model.js"></script>
<script type="text/javascript" src="../../source/model/modelutils.js"></script>
<script type="text/javascript" src="../../source/model/modelfinalization.js"></script>
<script type="text/javascript" src="../../source/import/importerutils.js"></script>
<script type="text/javascript" src="../../source/import/importerbase.js"></script>
<script type="text/javascript" src="../../source/import/importerobj.js"></script>
<script type="text/javascript" src="../../source/import/importerstl.js"></script>
<script type="text/javascript" src="../../source/import/importeroff.js"></script>
<script type="text/javascript" src="../../source/import/importerply.js"></script>
<script type="text/javascript" src="../../source/import/importer3ds.js"></script>
<script type="text/javascript" src="../../source/import/importergltf.js"></script>
<script type="text/javascript" src="../../source/import/importer.js"></script>
<script type="text/javascript" src="../../source/export/exporterutils.js"></script>
<script type="text/javascript" src="../../source/export/exporterbase.js"></script>
<script type="text/javascript" src="../../source/export/exporterobj.js"></script>
<script type="text/javascript" src="../../source/export/exporterstl.js"></script>
<script type="text/javascript" src="../../source/export/exporterply.js"></script>
<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/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>
<script type="text/javascript" src="../../source/viewer/domutils.js"></script>
<script type="text/javascript" src="../../source/viewer/navigation.js"></script>
<script type="text/javascript" src="../../source/viewer/viewer.js"></script>
<script type="text/javascript" src="../../source/viewer/domviewer.js"></script>
<!-- importer end -->
<script type='text/javascript'>
OV.Init3DViewerElements ();
</script>
<style>
div.online_3d_viewer
{
float: left;
border: 1px solid #eeeeee;
margin: 0px 4px 4px 0px;
}
</style>
</head>
<body>
<div class="online_3d_viewer"
style="width: 360px; height: 240px;"
model="../../test/testfiles/3ds/cube_four_instances.3ds,../../test/testfiles/3ds/texture.png">
</div>
<div class="online_3d_viewer"
style="width: 360px; height: 240px;"
model="../../test/testfiles/obj/hundred_cubes.obj,../../test/testfiles/obj/hundred_cubes.mtl">
</div>
<div class="online_3d_viewer"
style="width: 360px; height: 240px;"
model="../../test/testfiles/3ds/cube_four_instances.3ds,../../test/testfiles/3ds/texture.png"
camera="3.929421317669367,6.153966358575169,2.7076091223424714,1.5,1.5,0.5,0,0,1">
</div>
<div class="online_3d_viewer"
style="width: 360px; height: 240px;"
model="../../test/testfiles/obj/hundred_cubes.obj,../../test/testfiles/obj/hundred_cubes.mtl"
camera="1,1,1,0,0,0,0,0,1">
</div>
<div class="online_3d_viewer"
style="width: 360px; height: 240px;"
model="wrong.3ds">
</div>
</body>
</html>

View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<title>Online 3D Viewer</title>
<script type="text/javascript" src="../../libs/three.min-126.js"></script>
<!-- importer start -->
<script type="text/javascript" src="../../source/core/core.js"></script>
<script type="text/javascript" src="../../source/core/taskrunner.js"></script>
<script type="text/javascript" src="../../source/geometry/geometry.js"></script>
<script type="text/javascript" src="../../source/geometry/coord2d.js"></script>
<script type="text/javascript" src="../../source/geometry/coord3d.js"></script>
<script type="text/javascript" src="../../source/geometry/matrix.js"></script>
<script type="text/javascript" src="../../source/geometry/transformation.js"></script>
<script type="text/javascript" src="../../source/geometry/tween.js"></script>
<script type="text/javascript" src="../../source/io/binaryreader.js"></script>
<script type="text/javascript" src="../../source/io/binarywriter.js"></script>
<script type="text/javascript" src="../../source/io/textwriter.js"></script>
<script type="text/javascript" src="../../source/io/bufferutils.js"></script>
<script type="text/javascript" src="../../source/io/fileutils.js"></script>
<script type="text/javascript" src="../../source/model/modelentities.js"></script>
<script type="text/javascript" src="../../source/model/mesh.js"></script>
<script type="text/javascript" src="../../source/model/meshbuffer.js"></script>
<script type="text/javascript" src="../../source/model/model.js"></script>
<script type="text/javascript" src="../../source/model/modelutils.js"></script>
<script type="text/javascript" src="../../source/model/modelfinalization.js"></script>
<script type="text/javascript" src="../../source/import/importerutils.js"></script>
<script type="text/javascript" src="../../source/import/importerbase.js"></script>
<script type="text/javascript" src="../../source/import/importerobj.js"></script>
<script type="text/javascript" src="../../source/import/importerstl.js"></script>
<script type="text/javascript" src="../../source/import/importeroff.js"></script>
<script type="text/javascript" src="../../source/import/importerply.js"></script>
<script type="text/javascript" src="../../source/import/importer3ds.js"></script>
<script type="text/javascript" src="../../source/import/importergltf.js"></script>
<script type="text/javascript" src="../../source/import/importer.js"></script>
<script type="text/javascript" src="../../source/export/exporterutils.js"></script>
<script type="text/javascript" src="../../source/export/exporterbase.js"></script>
<script type="text/javascript" src="../../source/export/exporterobj.js"></script>
<script type="text/javascript" src="../../source/export/exporterstl.js"></script>
<script type="text/javascript" src="../../source/export/exporterply.js"></script>
<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/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>
<script type="text/javascript" src="../../source/viewer/domutils.js"></script>
<script type="text/javascript" src="../../source/viewer/navigation.js"></script>
<script type="text/javascript" src="../../source/viewer/viewer.js"></script>
<script type="text/javascript" src="../../source/viewer/domviewer.js"></script>
<!-- importer end -->
<script type='text/javascript'>
OV.Init3DViewerElements ();
</script>
</head>
<body>
<div class="online_3d_viewer"
style="width: 800px; height: 600px;"
model="../../test/testfiles/obj/hundred_cubes.obj,../../test/testfiles/obj/hundred_cubes.mtl"
camera="3,1,2,0,0,0,0,0,1">
</div>
</body>
</html>

View File

@ -19,8 +19,12 @@ def Main (argv):
config = json.load (configJson)
rootDir = os.path.abspath ('..')
for htmlFileName in ['index.html', 'embed.html']:
htmlFilePath = os.path.join (rootDir, 'website', htmlFileName)
websiteFiles = [
os.path.join ('website', 'index.html'),
os.path.join ('website', 'embed.html')
]
for htmlFileName in websiteFiles:
htmlFilePath = os.path.join (rootDir, htmlFileName)
replacer = Tools.TokenReplacer (htmlFilePath, True)
libFiles = Tools.CreateFileList (config['lib_files'], 'libs/', '../libs/')
importerFiles = Tools.CreateFileList (config['importer_files'], 'source/', '../source/')
@ -29,6 +33,18 @@ def Main (argv):
replacer.ReplaceTokenFileLinks ('<!-- importer start -->', '<!-- importer end -->', importerFiles, None)
replacer.ReplaceTokenFileLinks ('<!-- website start -->', '<!-- website end -->', websiteFiles, None)
replacer.WriteToFile (htmlFilePath)
sandboxFiles = [
os.path.join ('tools', 'sandbox', 'embed_selfhost_single.html'),
os.path.join ('tools', 'sandbox', 'embed_selfhost_multiple.html'),
os.path.join ('tools', 'sandbox', 'embed_selfhost_fullscreen.html')
]
for htmlFileName in sandboxFiles:
htmlFilePath = os.path.join (rootDir, htmlFileName)
replacer = Tools.TokenReplacer (htmlFilePath, True)
importerFiles = Tools.CreateFileList (config['importer_files'], 'source/', '../../source/')
replacer.ReplaceTokenFileLinks ('<!-- importer start -->', '<!-- importer end -->', importerFiles, None)
replacer.WriteToFile (htmlFilePath)
return 0

View File

@ -55,11 +55,11 @@
<script type="text/javascript" src="../source/export/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>
<script type="text/javascript" src="../source/viewer/domutils.js"></script>
<script type="text/javascript" src="../source/viewer/navigation.js"></script>
<script type="text/javascript" src="../source/viewer/viewer.js"></script>
<script type="text/javascript" src="../source/viewer/domviewer.js"></script>
<script type="text/javascript" src="../source/viewer/urlutils.js"></script>
<!-- importer end -->
<!-- website start -->
@ -82,21 +82,13 @@
<!-- analytics end -->
<script type='text/javascript'>
var embed = null;
$(window).on ('load', function () {
embed = new OV.Embed ({
let embed = new OV.Embed ({
viewerDiv : $('#embed_viewer'),
websiteLinkDiv : $('#website_link')
});
embed.Load ();
});
$(window).on ('resize', function () {
if (embed !== null) {
embed.Resize ();
}
});
</script>
</head>

View File

@ -55,11 +55,11 @@
<script type="text/javascript" src="../source/export/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>
<script type="text/javascript" src="../source/viewer/domutils.js"></script>
<script type="text/javascript" src="../source/viewer/navigation.js"></script>
<script type="text/javascript" src="../source/viewer/viewer.js"></script>
<script type="text/javascript" src="../source/viewer/domviewer.js"></script>
<script type="text/javascript" src="../source/viewer/urlutils.js"></script>
<!-- importer end -->
<!-- website start -->
@ -79,10 +79,8 @@
<!-- website end -->
<script type='text/javascript'>
var website = null;
$(window).on ('load', function () {
website = new OV.Website ({
let website = new OV.Website ({
headerDiv : $('#header'),
toolbarDiv : $('#toolbar'),
mainDiv : $('#main'),
@ -93,12 +91,6 @@
});
website.Load ();
});
$(window).on ('resize', function () {
if (website !== null) {
website.Resize ();
}
});
</script>
<!-- analytics start -->

74
website/info/cookies.html Normal file
View File

@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="icon" type="image/png" href="../assets/images/3dviewer_net_favicon.png">
<title>Online 3D Viewer Cookies Policy</title>
<link rel="stylesheet" type="text/css" href="info.css">
<!-- meta start -->
<!-- meta end -->
<!-- analytics start -->
<!-- analytics end -->
</head>
<body>
<div class="main">
<h1><a href=".">Online 3D Viewer Cookies Policy</a></h1>
<p>
Like most similar websites, <a href="https://3dviewer.net">Online 3D Viewer</a> (the "Website") uses cookies.
On this page we explain more about cookies and how we use them.
</p>
<h2>What are cookies?</h2>
<p>
Cookies are small text files that are stored in your web browser that allows Online 3D Viewer or a third party to recognize you.
Cookies can be used to collect, store and share bits of information about your activities across websites, including on
Online 3D Viewer Website.
</p>
<p>
Cookies might be used for the following purposes:
</p>
<ul>
<li>To provide analytics</li>
<li>To store your preferences</li>
</ul>
<p>
Online 3D Viewer uses both session cookies and persistent cookies.
</p>
<p>
A session cookie is used to identify a particular visit to our Website. These cookies expire after a short time,
or when you close your web browser after using our Website. We use these cookies to identify you during a single browsing session,
such as when you visit our Website.
</p>
<p>
A persistent cookie will remain on your devices for a set period of time specified in the cookie.
We use these cookies where we need to identify you over a longer period of time. For example,
we would use a persistent cookie to store your preferences on the Website.
</p>
<h2>How do third parties use cookies on the Website?</h2>
<p>
Third party companies like analytics companies use cookies to collect user information on an anonymous basis.
They may use that information to build a profile of your activities on the Online 3D Viewer Website and
other websites that you've visited.
</p>
<h2>What are your cookies options?</h2>
<p>
If you don't like the idea of cookies or certain types of cookies, you can change your browser's settings to
delete cookies that have already been set and to not accept new cookies. To learn more about how to do this,
visit the help pages of your browser.
</p>
<p>
Please note, however, that if you delete cookies or do not accept them, you might not be able to use all of
the features we offer, you may not be able to store your preferences, and some of our pages might not display properly.
</p>
</div>
</body>
</html>

View File

@ -42,6 +42,7 @@
<li><a href="#embed_selfhost">Self-hosted viewer</a></li>
</ol>
<li><a href="#exporting_models">Exporting models</a></li>
<li><a href="#cookies_policy">Cookies policy</a></li>
</ol>
</p>
@ -225,6 +226,10 @@
After that select the format you would like to export to, and download the resulting files one by one.
</p>
<h2 id="cookies_policy">Cookies policy</h2>
<p>
You can check the policy at the <a href="cookies.html">Cookies Policy</a> page.
</p>
</div>
</body>

View File

@ -74,6 +74,7 @@ h3
p
{
text-align: justify;
margin: 10px 0px;
line-height: 25px;
}

View File

@ -20,15 +20,16 @@ OV.Embed = class
if (urls === null) {
return;
}
let camera = this.hashHandler.GetCameraFromHash ();
if (camera !== null) {
this.viewer.SetCamera (camera);
}
this.modelLoader.LoadFromUrlList (urls);
let hashParameters = OV.CreateUrlParameters (urls, null);
let websiteUrl = this.parameters.websiteLinkDiv.attr ('href') + '#' + hashParameters;
this.parameters.websiteLinkDiv.attr ('href', websiteUrl);
}
let obj = this;
$(window).on ('resize', function () {
obj.Resize ();
});
}
Resize ()
@ -45,6 +46,12 @@ OV.Embed = class
return true;
});
this.viewer.AdjustClippingPlanes (boundingSphere);
let camera = this.hashHandler.GetCameraFromHash ();
if (camera !== null) {
this.viewer.SetCamera (camera);
} else {
this.viewer.SetUpVector (importResult.upVector, false);
}
this.viewer.FitToWindow (boundingSphere, false);
}

View File

@ -30,38 +30,20 @@ OV.HashHandler = class
GetCameraFromHash ()
{
let parser = new OV.UrlParamParser (this.GetHash ());
let parser = OV.CreateUrlParser (this.GetHash ());
return parser.GetCamera ();
}
GetModelFilesFromHash ()
{
let parser = new OV.UrlParamParser (this.GetHash ());
let parser = OV.CreateUrlParser (this.GetHash ());
return parser.GetModelUrls ();
}
SetModelFilesToHash (files)
{
let builder = new OV.UrlParamBuilder ();
builder.AddModelUrls (files);
this.SetHash (builder.GetUrlParams ());
}
GetFromHash (keyword)
{
let hash = this.GetHash ();
if (hash.length === 0) {
return null;
}
let keywordToken = keyword + '=';
let hashParts = hash.split ('$');
for (let i = 0; i < hashParts.length; i++) {
let hashPart = hashParts[i];
if (hashPart.startsWith (keywordToken)) {
return hashPart.substr (keywordToken.length);
}
}
return null;
let params = OV.CreateUrlParameters (files, null);
this.SetHash (params);
}
GetHash ()

View File

@ -40,10 +40,10 @@ OV.InitModelLoader = function (modelLoader, callbacks)
progressDialog = new OV.ProgressDialog ();
progressDialog.Show ('Loading Model');
},
onFilesLoaded : function () {
onImportStart : function () {
progressDialog.SetText ('Importing Model');
},
onModelImported : function () {
onVisualizationStart : function () {
progressDialog.SetText ('Visualizing Model');
},
onModelFinished : function (importResult, threeMeshes) {

View File

@ -32,6 +32,11 @@ OV.Website = class
this.Resize ();
this.OnHashChange ();
let obj = this;
$(window).on ('resize', function () {
obj.Resize ();
});
}
Resize ()