From 88c443b4ed8cc1c2373f7964cf703134728820b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20H=C3=BCbner?=
Date: Sat, 8 Apr 2017 11:24:20 +0200
Subject: [PATCH] Add 3D view toggle
---
app/Resources/assets/js/ModelViewer.js | 114 ++++++++++++++------
app/Resources/assets/style/modelviewer.scss | 25 +++++
app/Resources/assets/style/style.scss | 1 +
app/Resources/views/model/detail.html.twig | 74 ++++++-------
app/config/config.yml | 18 +++-
gulpfile.js | 3 +-
6 files changed, 159 insertions(+), 76 deletions(-)
create mode 100644 app/Resources/assets/style/modelviewer.scss
diff --git a/app/Resources/assets/js/ModelViewer.js b/app/Resources/assets/js/ModelViewer.js
index 5604ee2..adc096d 100644
--- a/app/Resources/assets/js/ModelViewer.js
+++ b/app/Resources/assets/js/ModelViewer.js
@@ -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 = $('', {
+ 'class':'toggle',
+ 'html':'3D View',
+ '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;
diff --git a/app/Resources/assets/style/modelviewer.scss b/app/Resources/assets/style/modelviewer.scss
new file mode 100644
index 0000000..a0e3fbb
--- /dev/null
+++ b/app/Resources/assets/style/modelviewer.scss
@@ -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%;
+ }
+}
\ No newline at end of file
diff --git a/app/Resources/assets/style/style.scss b/app/Resources/assets/style/style.scss
index 2cd9f12..3d8299a 100644
--- a/app/Resources/assets/style/style.scss
+++ b/app/Resources/assets/style/style.scss
@@ -1,3 +1,4 @@
@import "variables";
@import "main";
+@import "modelviewer";
diff --git a/app/Resources/views/model/detail.html.twig b/app/Resources/views/model/detail.html.twig
index 8411068..a057228 100644
--- a/app/Resources/views/model/detail.html.twig
+++ b/app/Resources/views/model/detail.html.twig
@@ -7,44 +7,44 @@
{% block header %}{{ model.name }}{% endblock %}
{% block content %}
-
- - number:
- {{ model.number }}
- - name:
- {{ model.name }}
- - category:
- {{ model.category ? model.category.name }}
- - model:
- {{ model.path }}
- - author:
- {{ model.author }}
- - keywords:
- -
- {% for keyword in model.keywords %}
- {{ keyword.name }}
- {% endfor %}
-
- - aliases:
- -
- {% for alias in model.aliases %}
- {{ alias.number }}
- {% endfor %}
-
- - Download:
- - {{ model.number }}
- - rebrickable parts ({{ rbParts|length }}):
- -
-
-
-
-
-
+
+
 | imagine_filter('model_large')}})
+
+
-
-
-
-
 }})
-
+
+ - number:
- {{ model.number }}
+ - name:
- {{ model.name }}
+ - category:
- {{ model.category ? model.category.name }}
+ - model:
- {{ model.path }}
+ - author:
- {{ model.author }}
+ - keywords:
+ -
+ {% for keyword in model.keywords %}
+ {{ keyword.name }}
+ {% endfor %}
+
+ - aliases:
+ -
+ {% for alias in model.aliases %}
+ {{ alias.number }}
+ {% endfor %}
+
+ - Download:
+ - {{ model.number }}
+ - rebrickable parts ({{ rbParts|length }}):
+ -
+
+
+
+
+
+
@@ -76,7 +76,7 @@
diff --git a/app/config/config.yml b/app/config/config.yml
index 2ce4e0a..0f9fbf2 100644
--- a/app/config/config.yml
+++ b/app/config/config.yml
@@ -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:
diff --git a/gulpfile.js b/gulpfile.js
index 23cdc2d..0822082 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -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 () {