1
0
mirror of https://github.com/ToxicCrack/PrintABrick.git synced 2025-05-16 04:10:09 -07:00

Add 3D view toggle

This commit is contained in:
David Hübner 2017-04-08 11:24:20 +02:00
parent db7195e4d3
commit 88c443b4ed
6 changed files with 159 additions and 76 deletions

View File

@ -1,45 +1,75 @@
var ModelViewer = function($container) {
var ModelViewer = function($dom_element) {
var $this = this;
this.container = $container;
this.container = document.createElement('div');
this.dom_element = $dom_element;
$dom_element.append(this.container);
this.container.style.display = "none";
this.camera = null;
this.scene = null;
this.renderer = null;
this.controls = null;
this.object = null;
this.width = parseFloat(this.container.width());
this.height = parseFloat(this.container.height());
this.width = parseFloat($dom_element.width());
this.height = parseFloat($dom_element.height());
this.visible = true;
this.stats = null;
this.scale = 1;
this.wireframe = false;
this.rendering = false;
this.initHtml();
this.initScene();
function renderLoop() {
requestAnimationFrame( renderLoop );
$this.render();
requestAnimationFrame(renderLoop);
if($this.rendering) {
$this.render();
}
$this.stats.update();
}
renderLoop();
};
ModelViewer.prototype.initHtml = function () {
$this = this;
var buttons = document.createElement("div");
buttons.setAttribute("class", "modelviewer-buttons");
var toggleButton = $('<button/>', {
'class':'toggle',
'html':'<span>3D View</span>',
'click': $this.toggleRendering.bind($this)
}).appendTo(buttons);
this.dom_element.append(buttons);
};
ModelViewer.prototype.initScene = function() {
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color( 0xffffff );
this.camera = new THREE.PerspectiveCamera(45, this.width / this.height, 1, 1000);
this.camera.position.z = 8;
this.camera = new THREE.PerspectiveCamera(45, this.width / this.height, 1, 300);
this.camera.position.z = 7;
this.camera.position.y = -5;
this.camera.position.x = 3;
this.camera.up = new THREE.Vector3(0, 0, 1);
this.reflectCamera = new THREE.CubeCamera(1, 50, 200);
this.scene.add(this.reflectCamera);
// this.reflectCamera = new THREE.CubeCamera(1, 50, 100);
// this.scene.add(this.reflectCamera);
this.scene.fog = new THREE.FogExp2(0xbbbbbb, 0.2);
var material = new THREE.MeshPhongMaterial({
color: 0xffffff,
emissive: 0xffffff,
shading: THREE.SmoothShading,
fog: false,
fog: true,
side: THREE.BackSide
});
@ -48,13 +78,13 @@ ModelViewer.prototype.initScene = function() {
this.scene.add(skybox);
var groundPlaneMaterial = new THREE.MeshPhongMaterial({
color: 0x888888,
color: 0x999999,
wireframe: false,
transparent: true,
opacity: 0.25,
// fog: true,
// specular: 0x999999,
envMap: this.reflectCamera.renderTarget
fog: false,
specular: 0x999999,
// envMap: this.reflectCamera.renderTarget
});
var x = 80;
var y = 80;
@ -86,47 +116,54 @@ ModelViewer.prototype.initScene = function() {
this.renderer = new THREE.WebGLRenderer();
this.renderer.setSize(this.width, this.height);
this.renderer.setPixelRatio(window.devicePixelRatio ? window.devicePixelRatio : 1);
this.container.append(this.renderer.domElement);
// this.renderer.shadowMap.enabled = true;
// this.renderer.shadowMap.renderReverseSided = false;
this.scene.fog = new THREE.FogExp2(0xcacaca, 0.9);
// // Light
this.spotLight = new THREE.SpotLight(0xffffff, 0.9, 0);
this.spotLight.position.set(-70, 100, 100);
this.controls = new THREE.OrbitControls( this.camera, this.renderer.domElement );
this.controls.enableZoom = true;
this.initLights();
this.stats = new Stats();
this.container.append( this.stats.dom );
};
ModelViewer.prototype.initLights = function () {
this.spotLight = new THREE.SpotLight(0xffffff, 0.8, 0);
this.spotLight.position.set(-100, 100, 100);
this.spotLight.castShadow = false;
this.scene.add(this.spotLight);
this.bottomSpotLight = new THREE.SpotLight(0xffffff, 0.3, 0);
this.bottomSpotLight = new THREE.SpotLight(0xffffff, 0.5, 0);
this.bottomSpotLight.position.set(70, -100, -100);
this.bottomSpotLight.castShadow = false;
this.scene.add(this.bottomSpotLight);
this.ambientLight = new THREE.AmbientLight(0xffffff, 0.1);
this.scene.add(this.ambientLight);
this.pointLight = new THREE.PointLight(0xffaaff, 0.9, 0);
this.pointLight = new THREE.PointLight(0xfdfdfd, 1, 0);
this.pointLight.position.set(32, -39, 35);
this.pointLight.castShadow = true;
this.scene.add(this.pointLight);
this.renderer.shadowMap.enabled = true;
this.renderer.shadowMap.renderReverseSided = false;
// $container.append(this.renderer.domElement);
this.controls = new THREE.OrbitControls( this.camera, this.renderer.domElement );
this.controls.enableZoom = true;
};
ModelViewer.prototype.addModel = function(geometry) {
var material = new THREE.MeshPhongMaterial({
color: 0x136FC3,
color: 0x1379d7,
specular: 0x0D0D0D,
shading: THREE.SmoothShading,
shininess: 150,
shininess: 30,
fog: false,
side: THREE.DoubleSide,
// wireframe: true,
wireframe: this.wireframe,
});
geometry.center();
@ -179,7 +216,8 @@ ModelViewer.prototype.centerCamera = function(mesh) {
var geometry = mesh.geometry;
var distanceX = (geometry.boundingBox.max.x - geometry.boundingBox.min.x) / 2 / Math.tan(this.camera.fov * this.camera.aspect * Math.PI / 360);
var distanceX = ((geometry.boundingBox.max.x - geometry.boundingBox.min.x) / 2) / Math.tan(this.camera.fov * this.camera.aspect * Math.PI / 360);
var distanceY = (geometry.boundingBox.max.y - geometry.boundingBox.min.y) / 2 / Math.tan(this.camera.fov * this.camera.aspect * Math.PI / 360);
var distanceZ = (geometry.boundingBox.max.z - geometry.boundingBox.min.z) / 2 / Math.tan(this.camera.fov * Math.PI / 360);
@ -195,6 +233,16 @@ ModelViewer.prototype.centerCamera = function(mesh) {
this.controls.reset();
};
ModelViewer.prototype.toggleRendering = function () {
if($this.rendering) {
$this.container.style.display = "none";
$this.rendering = false;
} else {
$this.container.style.display = "block";
$this.rendering = true;
}
};
ModelViewer.prototype.objectCenter = function (mesh) {
var middle = new THREE.Vector3();
var geometry = mesh.geometry;

View File

@ -0,0 +1,25 @@
.model-container {
width:600px;
height: 400px;
position: relative;
img {
width: 100%;
height: 100%;
}
.modelviewer-buttons {
position: absolute;
top: 0;
height: 30px;
width: 100%;
}
#model-viewer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}

View File

@ -1,3 +1,4 @@
@import "variables";
@import "main";
@import "modelviewer";

View File

@ -7,44 +7,44 @@
{% block header %}{{ model.name }}{% endblock %}
{% block content %}
<dl>
<dt>number:</dt><dd>{{ model.number }}</dd>
<dt>name:</dt><dd>{{ model.name }}</dd>
<dt>category:</dt><dd>{{ model.category ? model.category.name }}</dd>
<dt>model:</dt><dd>{{ model.path }}</dd>
<dt>author:</dt><dd>{{ model.author }}</dd>
<dt>keywords:</dt>
<dd>
{% for keyword in model.keywords %}
<span class="ui label">{{ keyword.name }}</span>
{% endfor %}
</dd>
<dt>aliases:</dt>
<dd>
{% for alias in model.aliases %}
<span class="ui label">{{ alias.number }}</span>
{% endfor %}
</dd>
<dd>Download:</dd>
<dt><a href="{{ url('media_file', {'path': model.path}) }}">{{ model.number }}</a></dt>
<dt>rebrickable parts ({{ rbParts|length }}):</dt>
<dd>
<p>
<div class="ui eight doubling cards">
{% for alias in rbParts %}
<a href="{{ url('rebrickable_part_show', {number:alias.number}) }}" class="ui label">{{ alias.number }}</a>
{% endfor %}
</div>
</p>
</dd>
</dl>
<div class="model-container">
<img src="{{ asset('ldraw/images/'~model.number~'.png') | imagine_filter('model_large')}}">
<div id="model-viewer"></div>
</div>
<div style="display: flex; flex-wrap: wrap">
<div id="model" style="height: 200px; width: 300px; padding: 5px; display: inline-block"></div>
<div style="height: 300px; width: 300px; padding: 5px; display: inline-block">
<img src="{{ url('media_file', {'path': 'ldraw/images/'~model.number~'.png'}) }}" style="max-height: 90%; max-width: 100%">
</div>
<dl>
<dt>number:</dt><dd>{{ model.number }}</dd>
<dt>name:</dt><dd>{{ model.name }}</dd>
<dt>category:</dt><dd>{{ model.category ? model.category.name }}</dd>
<dt>model:</dt><dd>{{ model.path }}</dd>
<dt>author:</dt><dd>{{ model.author }}</dd>
<dt>keywords:</dt>
<dd>
{% for keyword in model.keywords %}
<span class="ui label">{{ keyword.name }}</span>
{% endfor %}
</dd>
<dt>aliases:</dt>
<dd>
{% for alias in model.aliases %}
<span class="ui label">{{ alias.number }}</span>
{% endfor %}
</dd>
<dd>Download:</dd>
<dt><a href="{{ url('media_file', {'path': model.path}) }}">{{ model.number }}</a></dt>
<dt>rebrickable parts ({{ rbParts|length }}):</dt>
<dd>
<p>
<div class="ui eight doubling cards">
{% for alias in rbParts %}
<a href="{{ url('rebrickable_part_show', {number:alias.number}) }}" class="ui label">{{ alias.number }}</a>
{% endfor %}
</div>
</p>
</dd>
</dl>
<div>
<h4 class="ui horizontal divider header">
<i class="puzzle icon"></i> Subparts of this model
</h4>
@ -76,7 +76,7 @@
<script type="text/javascript">
window.onload = function() {
modelView = new ModelViewer($('#model'));
modelView = new ModelViewer($('#model-viewer'));
modelView.loadStl('{{ url('media_file', {'path': model.path }) }}');
};
</script>

View File

@ -112,6 +112,14 @@ liip_imagine:
quality: 80
filters:
thumbnail: { size: [200, 200], mode: inset }
background: { size: [250, 250], position: center, color: '#FFFFFF' }
model_large:
data_loader: media
cache: ~
quality: 92
filters:
thumbnail: { size: [400, 300], mode: inset }
background: { size: [600, 400], position: center, color: '#FFFFFF' }
rebrickable_part_min:
quality: 80
data_loader: rebrickable
@ -125,11 +133,11 @@ liip_imagine:
filters:
thumbnail: { size: [600, 600], mode: inset }
rebrickable_set_min:
quality: 80
data_loader: rebrickable
cache: ~
filters:
thumbnail: { size: [300, 300], mode: inset }
quality: 80
data_loader: rebrickable
cache: ~
filters:
thumbnail: { size: [300, 300], mode: inset }
oneup_flysystem:
adapters:

View File

@ -32,6 +32,7 @@ gulp.task('js', function() {
'node_modules/jquery/dist/jquery.js',
'node_modules/semantic-ui/dist/semantic.js',
'app/Resources/assets/js/**.js',
'node_modules/three/examples/js/libs/stats.min.js'
])
.pipe(plugins.concat('main.js'))
.pipe(gulp.dest('web/resources/js'));
@ -45,7 +46,7 @@ gulp.task('files', function () {
gulp.task('watch', ['js', 'css', 'three'], function () {
gulp.watch('app/Resources/assets/js/**.js' , ['js']);
gulp.watch('app/Resources/assets/style/**/*.sass' , ['css']);
gulp.watch('app/Resources/assets/style/**/*.scss' , ['css']);
});
gulp.task('default', function () {