The page has a divs with classes "skin", "skin2", "skin3"...
And for each class you need to place your 3d model.
I'm trying to do this, but all the 3d models, are tied to the first model.
I want to do this using the example of this site minecraft-skins
Image code results
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(10, window.innerWidth / window.innerHeight, 0.1, 50);
camera.position.z = 20;
camera.position.y = 1.5;
camera.position.x = 0;
renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setClearColor(0x000000, 0);
renderer.setSize(200, 300);
renderer.gammaOutput = true;
var light = new THREE.AmbientLight();
scene.add(light);
let loader = new THREE.GLTFLoader();
loader.load('/Стив.gltf', function (gltf) {
let obj = gltf;
document.getElementsByClassName('skin')[0].insertBefore(renderer.domElement, document.getElementsByClassName('skin')[0].firstChild);
scene.add(obj.scene);
obj.scene.scale.set(4.8, 1.5, 4.9);
obj.scene.rotation.y += 3.6;
obj.scene.rotation.x += 0.06;
});
loader.load('/Стив1.gltf', function (gltf2) {
let obj = gltf2;
document.getElementsByClassName('skin1')[0].insertBefore(renderer.domElement, document.getElementsByClassName('skin1')[0].firstChild);
scene.add(obj.scene);
obj.scene.scale.set(4.8, 1.5, 4.9);
obj.scene.rotation.y += 3.6;
obj.scene.rotation.x += 0.06;
});
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
<!DOCTYPE html>
<htm>
<head>
<title>Skins</title>
<script src="https://cdn.jsdelivr.net/npm/three#0.128.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.128.0/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.128.0/examples/js/loaders/GLTFLoader.js"></script>
</head>
<body>
<div class="block">
<div class="skin">
</div>
</div>
<div class="block">
<div class="skin1">
</div>
</div>
<script src="./script_01.js"></script>
</body>
</html>
Your code creates one renderer. On the first call to .insertBefore(), that renderer puts its context in the skin div. On the second call to .insertBefore(), that context is moved out of the skin div and into the skin1 div; at that point, there's no rendering being done inside of skin.
To achieve what you want, it's best to create a renderer that covers the whole window. Then you can use the renderer's .setScissor() method to render inside the limits of each div. Three.js provides an example of this.
Related
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;
}
In Three.js, the value for setClearColor is white But it render black, when i call external html file:
enter image description here
External file codes:
<div id="3d-modal"></div>
<script src="juicer/js/three.js"></script>
3D-modal scripts:
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75,
window.innerWidth/window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer({antialias : true});
// renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffffff);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Appending Webgl to the "container" Div...
// document.body.appendChild( renderer.domElement );
var container = document.getElementById("3d-modal");
var canvas_width = 290;
var canvas_height = 165;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(canvas_width , canvas_height);
container.appendChild(renderer.domElement);
var animate = function () {
requestAnimationFrame( animate );
renderer.render(scene, camera);
};
animate();
</script>
How can i solve this?
I came across this when I started using three.js as well. It's actually a javascript issue:
Update: Thanks to HdN8 for the updated solution:
renderer.setClearColor( 0xffffff, 0);
(note: syntax => setClearColor ( color, alpha ))
Update #2: As pointed out by WestLangley in another similar question - you must now use the below code when creating a new WebGLRenderer instance in conjunction with the setClearColor() function:
var renderer = new THREE.WebGLRenderer({ alpha: true });
Update #3: Mr.doob points out that since r78 you can alternatively use the code below to set your scene's background colour:
var scene = new THREE.Scene(); // initialising the scene
scene.background = new THREE.Color( 0xff0000 );
Update #4: G Dog
If the background color doesn't change, try changing alpha to 1 from 0.
Created the following mesh in blender:
Whenever I load it into three.js I receive the following result:
I export to .obj format and triangulate all of my faces. Not sure why this is happening. Below is the threejs code I am using to render the mesh. I use the same code with other meshes and they render as expected. I'm guessing I've done something that three.js doesn't like with this mesh?
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="/js/three.js"></script>
<script type="text/javascript" src="/js/DDSLoader.js"></script>
<script type="text/javascript" src="/js/MTLLoader.js"></script>
<script type="text/javascript" src="/js/OBJLoader.js"></script>
<script type="text/javascript" src="/js/OrbitControls.js"></script>
<script type="text/javascript" src="/js/stats.js"></script>
<script type="text/javascript" src="/js/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>
<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 130;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(scene.position);
scene.add(camera);
// create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
//webGLRenderer.setPixelRatio( window.devicePixelRatio );
webGLRenderer.setClearColor(new THREE.Color(0xffffff, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;
var ambient = new THREE.AmbientLight( 0x444444 );
ambient.intensity = 5;
scene.add( ambient );
if('stiletto_switchblade_knife.mtl' !== ''){
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl( '/assets/download/mesh/18/' );
mtlLoader.setPath( '/assets/download/mesh/18/' );
mtlLoader.load( 'stiletto_switchblade_knife.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( '/assets/download/mesh/18/' );
objLoader.load( 'stiletto_switchblade_knife.obj', function ( object ) {
//object.scale.set(100, 100, 100);
//object.rotation.x = -0.3;
scene.add( object );
});
});
} else {
var objLoader = new THREE.OBJLoader();
objLoader.setPath( '/assets/download/mesh/18/' );
objLoader.load( 'stiletto_switchblade_knife.obj', function ( object ) {
object.material = new THREE.MeshLambertMaterial({color: 0xFFFFFF});
//object.scale.set(100, 100, 100);
//object.rotation.x = -0.3;
scene.add( object );
});
}
// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
var controls = new THREE.OrbitControls(camera, webGLRenderer.domElement );
render();
// simple render
function render() {
stats.update();
controls.update();
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>
EDIT
Are meshes required to be watertight in three.js? If so that could be the problem as there are a couple areas that are not in this mesh. That's the only thing I can think of at the moment that differs between this and the meshes that render properly.
Renders like that turned up with OBJ models in three.js R76. It turned out that any object containing a stray "l" (line) element blew up just like what you have shown. I found the bad objects by searching the ASCII OBJ file on "l ", got rid of the strays by selecting and hiding all of the faces, and dealing with whatever was left.
Solved. Turned out I had left a few faces drawn inside of the mesh. This was causing the unexpected behavior. Interesting debugging method. I just started stripping away vertices and rendering with threejs until I found the section that was causing the issue.
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
Hy!
I'm working with three js(webgl). I was trying to embed html webpage, but somehow it don't wants to work.
Tutorials that I was checking:
http://learningthreejs.com/blog/2013/04/30/closing-the-gap-between-html-and-webgl/
http://stemkoski.github.io/Three.js/CSS3D.html
The stemkoski one was working with three js v58, also v60. But it don't realy wants to work using v68(newest version). I don't get any error message, just a black screen where the website should be.
Also I'm able to do something similiar like http://threejs.org/examples/#css3d_youtube .
My question is is there a workaround, or "hot fix" for this problem because I'm out of ideas.
Thanks for your answers.
---UPDATE---
Then let's say I'm using this code:
<!doctype html>
<html lang="en">
<head>
<title>CSS3D (Three.js)</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link rel=stylesheet href="css/base.css"/>
</head>
<body>
<script src="js/Three58.js"></script>
<script src="js/Detector.js"></script>
<script src="js/Stats.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/THREEx.KeyboardState.js"></script>
<script src="js/THREEx.FullScreen.js"></script>
<script src="js/THREEx.WindowResize.js"></script>
<!-- new for this example -->
<script src="js/CSS3DRenderer.js"></script>
<!-- jQuery code to display an information button and box when clicked. -->
<script src="js/jquery-1.9.1.js"></script>
<script src="js/jquery-ui.js"></script>
<link rel=stylesheet href="css/jquery-ui.css" />
<link rel=stylesheet href="css/info.css"/>
<script src="js/info.js"></script>
<div id="infoButton"></div>
<div id="infoBox" title="Demo Information">
This three.js demo is part of a collection at
http://stemkoski.github.io/Three.js/
</div>
<!-- ------------------------------------------------------------ -->
<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
<script>
/*
Three.js "tutorials by example"
Author: Lee Stemkoski
Date: July 2013 (three.js v58)
This demo is based on the work of Jerome Etienne:
http://learningthreejs.com/blog/2013/04/30/closing-the-gap-between-html-and-webgl/
*/
// MAIN
// standard global variables
var container, scene, camera, renderer, controls, stats;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();
// custom global variables
var rendererCSS;
init();
animate();
// FUNCTIONS
function init()
{
// SCENE
scene = new THREE.Scene();
// CAMERA
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(0,150,400);
camera.lookAt(scene.position);
// RENDERER
if ( Detector.webgl )
renderer = new THREE.WebGLRenderer( {antialias:true} );
else
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container = document.getElementById( 'ThreeJS' );
container.appendChild( renderer.domElement );
// EVENTS
THREEx.WindowResize(renderer, camera);
THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });
// CONTROLS
controls = new THREE.OrbitControls( camera, renderer.domElement );
// STATS
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.bottom = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
// LIGHT
var light = new THREE.PointLight(0xffffff);
light.position.set(0,250,0);
scene.add(light);
// FLOOR
var floorTexture = new THREE.ImageUtils.loadTexture( 'images/checkerboard.jpg' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set( 10, 10 );
var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = -0.5;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
////////////
// CUSTOM //
////////////
var planeMaterial = new THREE.MeshBasicMaterial({color: 0x000000, opacity: 0.1, side: THREE.DoubleSide });
var planeWidth = 360;
var planeHeight = 120;
var planeGeometry = new THREE.PlaneGeometry( planeWidth, planeHeight );
var planeMesh= new THREE.Mesh( planeGeometry, planeMaterial );
planeMesh.position.y += planeHeight/2;
// add it to the standard (WebGL) scene
scene.add(planeMesh);
// create a new scene to hold CSS
cssScene = new THREE.Scene();
// create the iframe to contain webpage
var element = document.createElement('iframe')
// webpage to be loaded into iframe
element.src = "index.html";
// width of iframe in pixels
var elementWidth = 1024;
// force iframe to have same relative dimensions as planeGeometry
var aspectRatio = planeHeight / planeWidth;
var elementHeight = elementWidth * aspectRatio;
element.style.width = elementWidth + "px";
element.style.height = elementHeight + "px";
// create a CSS3DObject to display element
var cssObject = new THREE.CSS3DObject( element );
// synchronize cssObject position/rotation with planeMesh position/rotation
cssObject.position = planeMesh.position;
cssObject.rotation = planeMesh.rotation;
// resize cssObject to same size as planeMesh (plus a border)
var percentBorder = 0.05;
cssObject.scale.x /= (1 + percentBorder) * (elementWidth / planeWidth);
cssObject.scale.y /= (1 + percentBorder) * (elementWidth / planeWidth);
cssScene.add(cssObject);
// create a renderer for CSS
rendererCSS = new THREE.CSS3DRenderer();
rendererCSS.setSize( window.innerWidth, window.innerHeight );
rendererCSS.domElement.style.position = 'absolute';
rendererCSS.domElement.style.top = 0;
rendererCSS.domElement.style.margin = 0;
rendererCSS.domElement.style.padding = 0;
document.body.appendChild( rendererCSS.domElement );
// when window resizes, also resize this renderer
THREEx.WindowResize(rendererCSS, camera);
renderer.domElement.style.position = 'absolute';
renderer.domElement.style.top = 0;
// make sure original renderer appears on top of CSS renderer
renderer.domElement.style.zIndex = 1;
rendererCSS.domElement.appendChild( renderer.domElement );
}
function animate()
{
requestAnimationFrame( animate );
render();
update();
}
function update()
{
if ( keyboard.pressed("z") )
{
// do something
}
controls.update();
stats.update();
}
function render()
{
// remember to call both renderers!
rendererCSS.render( cssScene, camera );
renderer.render( scene, camera );
}
</script>
</body>
</html>
As I mentioned above, this is the code from http://stemkoski.github.io/Three.js/CSS3D.html, and he made his code from another tutorial: http://learningthreejs.com/blog/2013/04/30/closing-the-gap-between-html-and-webgl/ this one.
The problem is, theese are working on three js r58-r60(Let's say theese are old codes). I want to do the same thing with three js r68(the newest version). But somehow, when I launch the same code on r68 that screen goes black instead of showing a html page. This is a known bug, you can check it http://learningthreejs.com/blog/2013/04/30/closing-the-gap-between-html-and-webgl/ here:
Hi Jerome, thanks for your interest. Here are a couple of jsfiddles
copied from stemkoski's github showing the results of Three r58 and
r68. Observe that the only difference between the samples is the
library in use: Threejs 58 (working) - http://jsfiddle.net/jL48v/2/
Threejs 68 (broken) - http://jsfiddle.net/jL48v/3/
I've tried several approaches to get this technique working in r68,
but without much luck so far.
Just realized that I messed up the dependency load order. Here's a
"fixed" broken version of r68 - http://jsfiddle.net/jL48v/4/
But he/she forgot to write the solution. and the v4 not working either.