Render Screen is Dificult - javascript

So I'm trying to learn how to use THREE.js to make browser games, however when I try to use the code to import a model the screen renders black. I'm using Brackets to code and run it and I haven't had an issue until now.
Heres the code
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
scene.background = new THREE.Color(0xdddddd);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var loader = new THREE.GLTFLoader();
loader.load('CabbageBase.glb', function(gltf) {
scene.add(gltf.scene);
}, undefined, function(error) {
console.error(error);
});
camera.position.z = 5;
var animate = function() {
requestAnimationFrame(animate);
/*cube.rotation.x += 0.01;
cube.rotation.y += 0.01;*/
renderer.render(scene, camera);
};
animate();
body {
background: linear-gradient(#e4e0ba, #f7d9aa);
margin: 0px;
overflow: hidden;
}
canvas {
display: block;
}
<script src="//cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<script src="GLTFLoader.js"></script>

I don't see anything wrong with the code except for the URLs.
You need to use a specific version of three.js by either downloading it or using a versioned CDN. All of the loaders, controls, and the examples require a specific version. Never link to threejs.org, always either download your own version or use a CDN. For example jsdeliver.
https://www.jsdelivr.com/package/npm/three
So for the three.js library the URL is
https://cdn.jsdelivr.net/npm/three#0.113.2/build/three.min.js
and for the version compatible GLTFLoader the URL is
https://cdn.jsdelivr.net/npm/three#0.113.2/examples/js/loaders/GLTFLoader.js
After that you need a model. I pointed to one on the three.js site (which is also bad since there is no guarantee it will stay their or stay compatible but for models we have less choices, normally you'd use your own model)
And with that the code works as is.
Note: For three.js you also generally need to run a local server which is covered in the docs
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
scene.background = new THREE.Color(0xdddddd);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var loader = new THREE.GLTFLoader();
loader.load('https://threejs.org/examples/models/gltf/Horse.glb', function(gltf) {
scene.add(gltf.scene);
}, undefined, function(error) {
console.error(error);
});
camera.position.z = 5;
var animate = function() {
requestAnimationFrame(animate);
/*cube.rotation.x += 0.01;
cube.rotation.y += 0.01;*/
renderer.render(scene, camera);
};
animate();
body {
background: linear-gradient(#e4e0ba, #f7d9aa);
margin: 0px;
overflow: hidden;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.113.2/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.113.2/examples/js/loaders/GLTFLoader.js"></script>

Related

Three.js "Context Lost" and "Multiple instances being imported"?

I'm trying to create a 3D editor, where the user can edit a 3D scene, and then hit a "play" button and see the result. To render the result, I'm using an iframe. Here is my HTML code:
<iframe id="testing_frame" class="ui"></iframe>
The class ui is just position: absolute; top: 0;. I don't want to have a URL or FILE as the src to this iframe, instead I want to write directly to it. Here is how I do it:
generatedCode += `
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"><\/script>
</head>
<body style="margin: 0;">
<script async>"use strict"
function init(){
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.1, 1000);
var mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({
color: 0xff0000
}));
scene.add(mesh);
camera.position.z = -5;
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
}
window.onload = init;
<\/script>
</body>
</html>`;
That code is stored in the variable generatedCode, which is what I will write to the iframe, here:
var iframe = document.getElementById("testing_frame");
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
iframeDocument.open();
iframeDocument.write(generatedCode);
iframeDocument.close();
This works fine.
My Problem: I have a start/stop button, which runs this code everytime it is clicked. Each time I hit stop, it says WARNING: Multiple instances of Three.js being imported., and if I start and stop the testing iframe around 10 times, it says THREE.WebGLRenderer: Context Lost.
Here I have a video demonstrating my problem. (Don't worry about the things in the console before I start doing anything)
Thanks!
Edit: Here is the start/stop code:
<button id='play_btn' onClick='test_iframe();';>Play</button>
This is the button, below is the test_iframe() function:
function test_iframe() {
let code = generateCodeFromProjectData();
var iframe = document.getElementById("testing_frame");
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
//Write to iframe
iframeDocument.open();
iframeDocument.write(code);
iframeDocument.close();
//If they press play, change it to stop and show the iframe.
if(document.getElementById("play_btn").innerHTML == "Play"){
document.getElementById("testing_frame").style.display = "block";
document.getElementById("play_btn").innerHTML = "Stop";
} else { //If they press stop, hide the iframe and change it to play.
document.getElementById("testing_frame").style.display = "none";
document.getElementById("play_btn").innerHTML = "Play";
}
}
Finally, here is the generateCodeFromProjectData() function, which receives the code:
function generateCodeFromProjectData(){
generatedCode = "";
//Opening
generatedCode += `
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"><\/script>
</head>
<body style="margin: 0;">
<script async>"use strict"
function init(){
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.1, 1000);
var mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({
color: 0xff0000
}));
scene.add(mesh);
camera.position.z = -5;
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
}
window.onload = init;
<\/script>
</body>
</html>`;
return generatedCode;
}
Edit 2: Here's my new code for the `iframe`
generatedCode += `
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"><\/script>
</head>
<body style="margin: 0;">
<script>
function init(){
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.1, 1000);
var mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({
color: 0xff0000
}));
scene.add(mesh);
camera.position.z = -5;
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
function destroy() {
scene = null;
camera = null;
mesh = null;
renderer.dispose()
}
return {destroy};
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
}
window.onload = () => {
var instance = init();
window.onbeforeunload = () => {
instance.destroy();
}
}
<\/script>
</body>
</html>`;
Now I get no error for Context Lost, but the red cube in the center does not show up.
It seems like a memory leak to me. Anything happened inside <iframe /> stays in the memory unless it is deallocated manually or the tab(window) is closed. I've experienced exact same problem when using storybook with different frontend libraries; storybook also uses <iframe /> as an isolated demonstration, but it always needed manual deallocation.
Manual memory deallocation, or dispose() function is necessary in Three.JS as well. Here's an excerpt from the official Three.js document:
Why can't three.js dispose objects automatically?
This question was asked many times by the community so it's important to clarify this matter. Fact is that three.js does not know the lifetime or scope of user-created entities like geometries or materials. This is the responsibility of the application. For example even if a material is currently not used for rendering, it might be necessary for the next frame. So if the application decides that a certain object can be deleted, it has to notify the engine via calling the respective dispose() method.
It says the dispose is necessary for Three.Object3D and says nothing about WebGLRender. Interestingly enough, the dispose() function is listed as WebGLRenderer's spec.
https://threejs.org/docs/?q=renderer#api/en/renderers/WebGLRenderer
to sync the dispose action to iframes, use window.onbeforeunload event handler or add dispose function to your page move action.
// add this code to your iframe code.
function init () {
var scene = // ...
var camera = // ...
var mesh = // ...
var renderer = // ...
/* ... */
function destroy() {
scene = null;
camera = null;
mesh = null;
renderer.dispose()
}
return {destroy};
}
window.onload = () => {
var instance = init();
window.onbeforeunload = () => {
instance.destroy();
}
}
edit: the answer only solves the context lost issue. It has no problem in terms of destroying the instance. Multiple instances being imported should be regarded as another problem. Anything that's added inside <iframe/> is considered in the same scope as its parent. adding <script src="..." /> inside iframe again and again causes multiple instances being imported. So to solve this issue, code must be provided from its parent.
generatedCode should not include the <script />
code should be provided in the same scope as the iframe controller code, so that it can sync the lifecycle of iframe and three.js renderer.
it's little bit more complex than disposing. here's the working code and working demo at codepen
<script src="your three.js url"></script>
<body>
<div id="root">
</div>
<button id='play_btn' onClick='test_iframe()'>Play</button>
</body>
// multiple instances being imported & context lost issue solved
function init(width, height) {
console.log("init", width, height);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(90, width / height, 0.1, 1000);
var mesh = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 1),
new THREE.MeshBasicMaterial({
color: 0xff0000
})
);
scene.add(mesh);
camera.position.z = 5;
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
function destroy() {
console.log("destroy");
scene = null;
camera = null;
mesh = null;
renderer.dispose();
}
function animate() {
if (!renderer) return;
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
return { destroy, domElement: renderer.domElement };
}
let iframe;
const getIframe = () => {
const code = generateCodeFromProjectData();
const root = document.getElementById("root");
const iframe = document.createElement("iframe");
iframe.setAttribute("id", "testing_frame");
iframe.setAttribute("class", "ui");
iframe.style.width = "300px";
iframe.style.height = "300px";
root.appendChild(iframe);
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
iframeDoc.open();
iframeDoc.write(code);
iframeDoc.close();
const body = iframeDoc.querySelector("body");
const instance = init(body.clientWidth, body.clientHeight);
body.appendChild(instance.domElement);
function destroy() {
root.removeChild(iframe);
instance.destroy();
}
return { iframe, iframeDoc, destroy };
};
function test_iframe() {
if (!iframe) {
// init
console.log("init");
iframe = getIframe();
document.getElementById("play_btn").innerHTML = "Stop";
return;
}
console.log("dispose");
// disposing
document.getElementById("play_btn").innerHTML = "Play";
iframe.destroy();
iframe = null;
}
function generateCodeFromProjectData() {
generatedCode = "";
//Opening
generatedCode += `
<!DOCTYPE html>
<html>
<body style="margin: 0;width: 300px;height:300px;">
</body>
</html>`;
return generatedCode;
}

How to capture an image of THREE.Scene uning THREE.PerspectiveCamera?

I was looking online, but I didn’t found much. I’m basically looking for the camera function that renders an image when a button is pressed.
Notice that I have 2 THREE.PerspectiveCamera (main and 2nd). The main camera is the one I use for the OrbitControls. and the 2nd is for capturing the image.
This is how I declare the Three.PerspectiveCamera:
camera_RT = new THREE.PerspectiveCamera(20, window.innerWidth / window.innerHeight, -100, -1000);
camera_RT.position.set( //Set 2nd camera's position according to its parent
camera_RT.position.x,
camera_RT.position.y,
camera_RT_Holder.position.z
);
camera_RT.updateMatrixWorld(); //Update camera's Matrix Wolrd (location in the scene)
//Add the Camera to the camera Holder (parent objects)
camera_RT_Holder.add(camera_RT);
//Create 2nd Camera Helper (View volume)
camera_RT_Helper = new THREE.CameraHelper( camera_RT ); //Create camera helper
scene_Main.add( camera_RT_Helper );//Add the camera helper to the scene
UPDATE:
function saveImage(){
let imgData;
var final_Image;
try {
noLoop(); //STOP p5JS ITERATION - draw() function is not called
camera_RT.imageData = renderer_Main.domElement.toDataURL();
imgData = camera_RT.imageData;
console.log(imgData); //CONSOLE PRINTS : data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABD0AAAJFCAYAAADeVYzuAAAgAElEQVR4Xu3YwQ0AMAwCMbr/0K3UMU7OBjG8ONvuHAECBAgQIECAAAECBAgQIEAgJnCMHrFEvUOAAAECBAgQIECAAAECBAh8AaOHIhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIEAWdyI4AAA/sSURBVCBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAkaPZKyeIkCAAAECBAgQIECAAAECBIweOkCAAAECBAgQIECAAAECBAgkBYweyVg9RYAAAQIECBAgQIAAAQIECBg9dIAAAQIECBAgQIAAAQIECBBIChg9krF6igABAgQIECBAgAABAgQIEDB66AABAgQIECBAgAABAgQIECCQFDB6JGP1FAECBAgQIECAAAECBAgQIGD00AECBAgQIECAAAECBAgQIEAgKWD0SMbqKQIECBAgQIAAAQIECBAgQMDooQMECBAgQIAAAQIECBAgQIBAUsDokYzVUwQIECBAgAABAgQIECBAgIDRQwcIECBAgAABAgQIECBAgACBpIDRIxmrpwgQIECAAAECBAgQIECAAAGjhw4QIECAAAECBAgQIECAAAECSQGjRzJWTxEgQIAAAQIECBAgQIAAAQJGDx0gQIAAAQIECBAgQIAAAQIEkgJGj2SsniJAgAABAgQIECBAgAABAgSMHjpAgAABAgQIECBAgAABAgQIJAWMHslYPUWAAAECBAgQIECAAAECBAgYPXSAAAECBAgQIECAAAECBAgQSAoYPZKxeooAAQIECBAgQIAAAQIECBAweugAAQIECBAgQIAAAQIECBAgkBQweiRj9RQBAgQIECBAgAABAgQIECBg9NABAgQIECBAgAABAgQIECBAIClg9EjG6ikCBAgQIECAAAECBAgQIEDA6KEDBAgQIECAAAECBAgQIECAQFLA6JGM1VMECBAgQIAAAQIECBAgQICA0UMHCBAgQIAAAQIECBAgQIAAgaSA0SMZq6cIECBAgAABAgQIECBAgAABo4cOECBAgAABAgQIECBAgAABAkkBo0cyVk8RIECAAAECBAgQIECAAAECRg8dIECAAAECBAgQIECAAAECBJICRo9krJ4iQIAAAQIECBAgQIAAAQIEjB46QIAAAQIECBAgQIAAAQIECCQFjB7JWD1FgAABAgQIECBAgAABAgQIGD10gAABAgQIECBAgAABAgQIEEgKGD2SsXqKAAECBAgQIECAAAECBAgQMHroAAECBAgQIECAAAECBAgQIJAUMHokY/UUAQIECBAgQIAAAQIECBAgYPTQAQIECBAgQIAAAQIECBAgQCApYPRIxuopAgQIECBAgAABAgQIECBAwOihAwQIECBAgAABAgQIECBAgEBSwOiRjNVTBAgQIECAAAECBAgQIECAgNFDBwgQIECAAAECBAgQIECAAIGkgNEjGaunCBAgQIAAAQIECBAgQIAAAaOHDhAgQIAAAQIECBAgQIAAAQJJAaNHMlZPESBAgAABAgQIECBAgAABAkYPHSBAgAABAgQIECBAgAABAgSSAg8FMUUfXYyMwAAAAABJRU5ErkJggg==
final_Image = createImg(imgData);
final_Image.attribute("id", "finalImage");
final_Image.attribute("style", "display:block; margin:20px auto;");
final_Image.parent(canvas_Parent);
//Hide Scene_Main and disable slider
document.getElementById("canvas_3d_element").style.display = "none";
document.getElementById("slider-element").disabled = true;
stage_9_declared = true;
saveImageRequest = true;
} catch (e) {
console.log(e);
return;
}
}
function animate() {
...
if(!stage_9_declared && !saveImageRequest){
console.log(saveImageRequest);
this.render(); //Render Scene and Camera every frame
}
}
function render() {
//Render only if the camera_Main is declared
if(camera_Main_declared){
renderer_Main.render(scene_Main, camera_Main);
}
}
Here is an example of taking a screenshot.
To change which camera the screenshot is taken from, you would just change which camera you send to the renderer.render() function.
In this example I only have one camera though.
UPDATE: The screenshot button in this example code may not actually work in the demo as it is in an iframe on stackoverflow (in Chrome, and maybe other browsers) because of this.
But here is a jsfiddle demo
var camera, scene, renderer, mesh, material;
init();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer({
antialias: true,
//preserveDrawingBuffer: true
});
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// add Screenshot listener
document.getElementById("shot").addEventListener('click', takeScreenshot);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
// Create scene.
scene = new THREE.Scene();
// Create material
material = new THREE.MeshPhongMaterial();
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(200, 200, 200);
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// Create ambient light and add to scene.
var light = new THREE.AmbientLight(0x404040); // soft white light
scene.add(light);
// Create directional light and add to scene.
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
}
function takeScreenshot() {
// open in new window like this
//
/*
var w = window.open('', '');
w.document.title = "Screenshot";
//w.document.body.style.backgroundColor = "red";
var img = new Image();
// Without 'preserveDrawingBuffer' set to true, we must render now
renderer.render(scene, camera);
img.src = renderer.domElement.toDataURL();
w.document.body.appendChild(img);
*/
/*
// download file like this.
//
var a = document.createElement('a');
// Without 'preserveDrawingBuffer' set to true, we must render now
renderer.render(scene, camera);
a.href = renderer.domElement.toDataURL().replace("image/png", "image/octet-stream");
a.download = 'canvas.png'
a.click();
*/
// New version of file download using toBlob.
// toBlob should be faster than toDataUrl.
// But maybe not because also calling createOjectURL.
// I dunno....
//
renderer.render(scene, camera);
renderer.domElement.toBlob(function(blob){
var a = document.createElement('a');
var url = URL.createObjectURL(blob);
a.href = url;
a.download = 'canvas.png';
a.click();
}, 'image/png', 1.0);
}
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
padding: 0;
margin: 0;
}
canvas {
display: block;
}
#shot {
position: absolute;
top: 0px;
right: 0px;
margin: 5px;
}
<script src="https://rawgit.com/mrdoob/three.js/r102/build/three.min.js"></script>
<button id="shot">Take Screenshot</button>
On button click use the method toDataURL() to capture the image from the camera.
imageData = renderer.domElement.toDataURL();
The DOM element of renderer is a canvas. Refer: https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL for more details

Three.js fast text engraving

I'm trying to engrave some text on a surface using Three.js. I've achieved it using csg.js and ThreeCSG and it works perfect, the result is really good but the problem is it takes a lot of time. On my PC it takes about 30 seconds to engrave the word Hello.
Searching for other solution I found this site. They make custom jewelry and you can engrave text on it and the time it takes to engrave the text is really short! So I assume they are not using csg.js. What other technique can be used to achieve this result?
I though about using bump maps, I should generate a bump map for each letter but I don't know if that's the correct approach.
I can see by looking at the shaders that the site your linked to uses bump maps.
I don't think you would create a bump map for each letter, you would just do all the drawing (text) on a single canvas and apply that as a bump map.
Click on "Run Code Snippet" below for a demo of canvas bump maps (click and drag in the white box).
I hope this helps.
var camera, scene, renderer, mesh, material, stats;
var drawStartPos = {x:0, y:0};
init();
setupCanvasDrawing();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer();
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.getElementById('threejs-container').appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
// Create scene.
scene = new THREE.Scene();
// Create material
material = new THREE.MeshPhongMaterial();
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(200, 200, 200);
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// Create ambient light and add to scene.
var light = new THREE.AmbientLight(0x404040); // soft white light
scene.add(light);
// Create directional light and add to scene.
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
// Add stats to page.
stats = new Stats();
document.body.appendChild( stats.dom );
}
function setupCanvasDrawing() {
// get canvas and context
var drawingCanvas = document.getElementById('drawing-canvas');
var drawingContext = drawingCanvas.getContext('2d');
// draw white background
drawingContext.fillStyle = "#FFFFFF";
drawingContext.fillRect(0,0,128,128);
// set canvas as bumpmap
material.bumpMap = new THREE.Texture(drawingCanvas);
// set the variable to keep track of when to draw
var paint = false;
// add canvas event listeners
drawingCanvas.addEventListener('mousedown', function(e){
paint = true
drawStartPos = {x:e.offsetX, y:e.offsetY};
});
drawingCanvas.addEventListener('mousemove', function(e){
if(paint){
draw(drawingContext, e.offsetX, e.offsetY);
}
});
drawingCanvas.addEventListener('mouseup', function(e){
paint = false;
});
drawingCanvas.addEventListener('mouseleave', function(e){
paint = false;
});
}
// Draw function
function draw(drawContext, x, y) {
drawContext.moveTo(drawStartPos.x, drawStartPos.y);
drawContext.lineTo(x,y);
drawContext.stroke();
drawStartPos = {x:x, y:y};
material.bumpMap.needsUpdate = true;
}
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
stats.update();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
padding: 0;
margin: 0;
}
#drawing-canvas {
position: absolute;
background-color: #000;
top: 0px;
right: 0px;
z-index: 3;
}
#threejs-container {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: 1;
}
<script src="https://rawgit.com/mrdoob/three.js/r83/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/stats.js/r17/build/stats.min.js"></script>
<canvas id="drawing-canvas" height="128" width="128"></canvas>
<div id="threejs-container"></div>

Issue with getting colors in a Blender imported mesh to be shown using Three.js

I am trying to display glued cubes, imported from blender, using Three.js.
I am using latest Version of Three.js and Blender 2.78a.
I started by making my cube object;just like this:
https://www.jonathan-petitcolas.com/2015/07/27/importing-blender-modelized-mesh-in-threejs.html
But I have different/more glued cubes.
I created above 3d object in Blender, Then exported the mesh using the Three.js .js exporter.
Here is the marmelab.json file.
{
"metadata":{
"generator":"io_three",
"faces":6,
"type":"Geometry",
"version":3,
"materials":1,
"normals":6,
"vertices":24,
"uvs":1
},
"faces":[43,8,10,12,14,0,0,1,2,3,0,0,0,0,43,16,18,20,22,0,3,0,1,2,1,1,1,1,43,9,15,19,17,0,3,0,1,2,2,2,2,2,43,1,13,21,5,0,3,0,1,2,3,3,3,3,43,3,11,23,7,0,3,0,1,2,4,4,4,4,43,2,0,4,6,0,3,0,1,2,5,5,5,5],
"materials":[{
"DbgIndex":0,
"blending":"NormalBlending",
"opacity":1,
"depthWrite":true,
"visible":true,
"transparent":false,
"colorEmissive":[0,0,0],
"colorDiffuse":[0.8,0.432941,0],
"wireframe":false,
"DbgName":"01 - Default",
"specularCoef":11,
"colorSpecular":[0.18,0.18,0.18],
"DbgColor":15658734,
"depthTest":true,
"shading":"phong"
}],
"normals":[0,0,1,0,0,-1,0,1,-0,1,0,-0,0,-1,-0,-1,0,-0],
"name":"Untitled.001Geometry.1",
"vertices":[-0.307576,-0,-0.433258,-0.002776,-0,-0.433258,-0.307576,-0,-0.738058,-0.002776,-0,-0.738058,-0.307576,0.3048,-0.433258,-0.002776,0.3048,-0.433258,-0.307576,0.3048,-0.738058,-0.002776,0.3048,-0.738058,-0.307576,-0,-0.433258,-0.307576,-0,-0.433258,-0.307576,-0,-0.738058,-0.307576,-0,-0.738058,-0.002776,-0,-0.738058,-0.002776,-0,-0.738058,-0.002776,-0,-0.433258,-0.002776,-0,-0.433258,-0.307576,0.3048,-0.433258,-0.307576,0.3048,-0.433258,-0.002776,0.3048,-0.433258,-0.002776,0.3048,-0.433258,-0.002776,0.3048,-0.738058,-0.002776,0.3048,-0.738058,-0.307576,0.3048,-0.738058,-0.307576,0.3048,-0.738058],
"uvs":[[1,0,1,1,0,1,0,0]]
}
javascript to load the mesh and display
var scene, camera, renderer;
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
var SPEED = 0.01;
function init() {
scene = new THREE.Scene();
initMesh();
initCamera();
initLights();
initRenderer();
document.body.appendChild(renderer.domElement);
}
function initCamera() {
camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 1, 10);
camera.position.set(0, 3.5, 5);
camera.lookAt(scene.position);
}
function initRenderer() {
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
}
function initLights() {
var light = new THREE.AmbientLight(0xffffff);
scene.add(light);
}
var mesh = null;
function initMesh() {
var loader = new THREE.JSONLoader();
loader.load('./marmelab.json', function(geometry, materials) {
mesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));
mesh.scale.x = mesh.scale.y = mesh.scale.z = 0.75;
mesh.translation = THREE.GeometryUtils.center(geometry);
scene.add(mesh);
});
}
function rotateMesh() {
if (!mesh) {
return;
}
mesh.rotation.x -= SPEED * 2;
mesh.rotation.y -= SPEED;
mesh.rotation.z -= SPEED * 3;
}
function render() {
requestAnimationFrame(render);
rotateMesh();
renderer.render(scene, camera);
}
init();
render();
However in Browser the shape is rtained ; but the color is white.
What am I missing here?
Thank you so much in advance.
EDIT
I updated the Plunker with the latest version of three.js and it now works with your unedited json above - http://plnkr.co/edit/RwkgzrvfqzYlWtShhpjt?p=preview
Also successfully tested with my own, more complicated, model - http://plnkr.co/edit/SWXv1GyKIGryORiNYlgx?p=preview
The problem is caused by using an older version of three.js. I originally tested using the version provided by the website you linked to. I suspect you might have done the same given the result.
Somewhere around revision 70 they changed the exporter to no longer export the colorAmbient property, and that older version of Three.js required it.

JavaScript runtime error: Unable to get property 'geometries' of undefined or null reference when importing 3D models into a three.js viewport

I am trying to import my own 3D models into a three.js viewport but I keep getting this error:
0x800a138f - JavaScript runtime error: Unable to get property
'geometries' of undefined or null reference
My code:
<html>
<head>
<title>My first Three.js app</title>
<style>
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script src="js/three.min.js"></script>
<script>
// Our Javascript will go here.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var json = THREE.JSONLoader("teapot.js"); // I Think this loads the model
var loader = new THREE.JSONLoader();
var result = loader.parse(json, texturePath);
var mesh = new THREE.Mesh(result.geometry, result.materials);
scene.add(mesh);
camera.position.z = 5;
function render() {
requestAnimationFrame(render);
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
}
render();
</script>
</body>
</html>
You're loading it wrong, when using the loader, first you declare the loader as such:
var loader = new THREE.JSONLoader();
Then you tell the loader to load your model, since this takes a while, you attach a function to handle adding it to the scene AFTER the loading is done
loader.load('path_to_model', function (geometry) {
var material = new THREE.MeshLambertMaterial({
//whatever material properties you want to use
});
// create a mesh with models geometry and material
var mesh = new THREE.Mesh(
geometry,
material
);
scene.add(mesh);
});
That should do the trick

Categories