Getting current geometry of animated mesh - three.js

How does one get the current geometry of an animated mesh? Say I have a mesh that's going through some animation and I want to grab a copy of the current pose and create a new mesh using it (not necessarily skinned the same way), how would I do this?
Edit: Here is a simple example. It loads one of the three.js example animations and runs it. The loaded mesh is skinnedMesh. Every time animate() is called, a copy of the mesh is made using skinnedMesh.geometry. The copy is called newMesh, and it's created with a simple red MeshBasicMaterial and offset to one side of the original.
If you run the code, you'll see that although skinnedMesh is animated, newMesh is always a copy of the untransformed geometry. If it was doing what I wanted it to do, newMesh would be in the same pose as skinnedMesh.
Clearly this particular example is very inefficient, as I could just make another copy of skinnedMesh and animate it separately. But that's not what I want to do. I want to be able to grab the state of the animated mesh at any point in time and make a copy of the pose it happens to be in at that moment.
I hope this makes everything clearer.
<!DOCTYPE html>
<html lang="en">
<head>
<title>test</title>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js"> </script>
<script>
var container;
var camera, scene, renderer, loader, clock, light;
var skinnedMesh, animation, groundMaterial, planeGeometry, mixer;
var newMesh = null;
var loaded = false;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(10, 0, 10);
scene = new THREE.Scene();
loader = new THREE.JSONLoader();
clock = new THREE.Clock;
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
groundMaterial = new THREE.MeshPhongMaterial({
emissive: 0x010101
});
planeGeometry = new THREE.PlaneBufferGeometry(16000, 16000);
ground = new THREE.Mesh(planeGeometry, groundMaterial);
ground.position.set(0, -5, 0);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
light = new THREE.HemisphereLight(0x777777, 0x003300, 1);
light.position.set(-80, 500, 50);
scene.add(light);
loader.load('http://threejs.org/examples/models/skinned/simple/simple.js', function(geometry, materials) {
for (var k in materials) {
materials[k].skinning = true;
}
skinnedMesh = new THREE.SkinnedMesh(geometry, new THREE.MeshFaceMaterial(materials));
skinnedMesh.scale.set(1, 1, 1);
skinnedMesh.position.y = 0;
scene.add(skinnedMesh);
mixer = new THREE.AnimationMixer(skinnedMesh);
mixer.addAction(new THREE.AnimationAction(skinnedMesh.geometry.animations[0]));
camera.lookAt(skinnedMesh.position);
loaded = true;
});
}
function animate() {
requestAnimationFrame(animate);
if (!loaded) {
return;
}
if (mixer) mixer.update(clock.getDelta());
if (newMesh) {
scene.remove(newMesh);
}
newMesh = new THREE.Mesh(skinnedMesh.geometry,
new THREE.MeshBasicMaterial({
color: 0xff0000
})
);
newMesh.position.x = skinnedMesh.position.x - 6;
scene.add(newMesh);
render();
}
function render() {
renderer.render(scene, camera);
}
</script>
</body>
</html>

You can directly reference the geometry property of a Mesh Object which contains an array of faces.
Manipulating the geometry ad-hoc is an adventure onto itself, but the structure should be clear enough.
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({
color: 0xffff00
});
var mesh = new THREE.Mesh(geometry, material);
console.log(mesh.geometry)
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.min.js"></script>

Bones don't affect the geometry in memory, their matrices are being applied to geometry in a shader during the rendering and that geometry can't be accessed from JS level.
You have to bake the current pose into positions and also to normals, implementation: https://stackoverflow.com/a/66404012/696535

Related

Basic Three.js template scene, canĀ“t animate

I'm really new in Three.js and javascript in general.
My question, I'm been trying to create some king of basic frankenstein template ( mainly based on Lee Stemkoski's examples) to use Three.js but as right know i can't make the cube spin infinitely, I have been watching tutorials and other examples but i can't make it work, any ideas why or how to solve it?
And
Any suggestions on how to improve this template scene?
Thanks in advance
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js Template</title>
<meta charset=utf-8>
<link rel="stylesheet" type="text/css" href="css/styles.css">
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,700' rel='stylesheet' type='text/css'>
<script src="js/three.js"></script>
<script src="js/Detector.js"></script>
<script src="js/Stats.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/OBJLoader.js"></script>
<script src="js/MTLLoader.js"></script>
<script src="js/DDSLoader.js"></script>
<script src="js/THREEx.KeyboardState.js"></script>
<script src="js/THREEx.FullScreen.js"></script>
<script src="js/THREEx.WindowResize.js"></script>
</head>
<body>
<div id="info">
three.js Template Scene<br />
from Base scene
</div>
<div id="threeJSScene"></div>
<script>
// MAIN //
// standard global variables
var container, scene, camera, renderer, controls, stats, animate;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();
// initialization
init();
// animation loop / game loop
animate();
// FUNCTIONS //
function init()
{
// SCENE //
scene = new THREE.Scene();
//Add fog to the scene
// scene.fog = new THREE.FogExp2( 0xcccccc, 0.001 );
// CAMERA //
// set the view size in pixels (custom or according to window size)
// var SCREEN_WIDTH = 400, SCREEN_HEIGHT = 300;
var SCREEN_WIDTH = window.innerWidth,
SCREEN_HEIGHT = window.innerHeight;
// camera attributes
var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
// set up camera
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR);
// add the camera to the scene
scene.add(camera);
// the camera defaults to position (0,0,0)
// so pull it back (z = 400) and up (y = 100) and set the angle towards the scene origin
camera.position.set(0,150,400);
camera.lookAt(scene.position);
// RENDERER //
// create and start the renderer; choose antialias setting.
if ( Detector.webgl )
renderer = new THREE.WebGLRenderer( {alpha:true, antialias:true} );
else
renderer = new THREE.CanvasRenderer();
// Configure renderer size
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
//Change BG Color
//renderer.setClearColor( 0xAA20AA );
//Configure pixel aspect ratio
renderer.setPixelRatio( window.devicePixelRatio );
//Enable shadows
renderer.shadowMapEnabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Modify gamma
// renderer.gammaInput = true;
// renderer.gammaOutput = true;
//Attach div element to variable to contain the renderer
container = document.getElementById( 'threeJSScene' );
// alternatively: to create the div at runtime, use:
// container = document.createElement( 'div' );
// document.body.appendChild( container );
// attach renderer to the *container* div
container.appendChild( renderer.domElement );
// EVENTS //
// automatically resize renderer
THREEx.WindowResize(renderer, camera);
// toggle full-screen on given key press
THREEx.FullScreen.bindKey({ charCode : 'm'.charCodeAt(0) });
// CONTROLS //
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // remove when using animation loop
// enable animation loop when using damping or autorotation
//controls.enableDamping = true;
//controls.dampingFactor = 0.25;
controls.enableZoom = true;
//controls.update(); ----------> // required if controls.enableDamping = true, or if controls.autoRotate = true
// STATS //
// displays current and past frames per second attained by scene
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.bottom = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
// LIGHT //
// Add ambient light to Scene - Color(Blue) - Intensity
var Ambientlight = new THREE.AmbientLight (0x506699, 1);
scene.add(Ambientlight);
// Add light to Scene - Color(Red) - Intensity - Distance - decay
var light1 = new THREE.PointLight (0xff0000, 2, 400, 2);
light1.position.set(-60,150,-30);
light1.castShadow = true;
light1.shadowCameraVisible = true;
light1.shadow.mapSize.width = 1024 * 2;
light1.shadow.mapSize.height = 1024 * 2;
light1.shadowDarkness = 0.95;
light1.shadow.camera.near = 20;
light1.shadow.camera.far = 10000;
scene.add(light1);
// spotlight #1 -- yellow, dark shadow
var spotlight = new THREE.SpotLight(0xffff00);
spotlight.position.set(-60,150,-30);
spotlight.shadowCameraVisible = true;
spotlight.shadowDarkness = 0.95;
spotlight.intensity = 2;
// must enable shadow casting ability for the light
spotlight.castShadow = true;
scene.add(spotlight);
// GEOMETRY //
// Create a Cube Mesh //
var geometry = new THREE.BoxGeometry( 50, 50, 50 );
// Create a basic material
var material = new THREE.MeshStandardMaterial( {
color: "#ffffff",
side: THREE.DoubleSide,
//transparent: true,
//opacity: 0.5,
//wireframe: true,
//wireframeLinewidth: 5,
map: new THREE.TextureLoader().load('img/pattern.jpg'),
normalMap: new THREE.TextureLoader().load('img/pattern_NRM.png')
});
//Join the two attribute ( Geometry and material )
var mesh = new THREE.Mesh( geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.position.set(0, 50, 0); // Chance object position
//Add geometry to the scene
scene.add (mesh);
// Create a TorusKnot //
var TorusknotGeometry = new THREE.TorusKnotGeometry( 15, 5, 60, 25 );
var Torusknot = new THREE.Mesh( TorusknotGeometry, material); // We are using the same material created for the cube
Torusknot.castShadow = true;
Torusknot.receiveShadow = true;
Torusknot.position.set (0,100,0);
scene.add (Torusknot);
// Create a cube for the ground //
var groundGeometry = new THREE.BoxGeometry(200,200,10);
var ground = new THREE.Mesh( groundGeometry, material);
ground.castShadow = true;
ground.receiveShadow = true;
ground.position.set (0,0,0);
ground.rotation.x = 1.57;
scene.add (ground);
// Load in the mesh and add it to the scene.
var loader = new THREE.JSONLoader();
loader.load( "models/treehouse_logo.js", function(log){
var materiallogo = new THREE.MeshLambertMaterial({color: 0x55B663});
logo = new THREE.Mesh(log, materiallogo);
logo.scale.set (50,50,50);
logo.position.y = -1;
logo.castShadow = true;
logo.receiveShadow = true;
scene.add(logo);
});
// FLOOR //
// note: 4x4 checkboard pattern scaled so that each square is 25 by 25 pixels.
var floorTexture = new THREE.ImageUtils.loadTexture( 'img/checkerboard.jpg' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set( 10, 10 );
// DoubleSide: render texture on both sides of mesh
var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 1, 1);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.castShadow = true;
floor.receiveShadow = true;
floor.position.y = -0.5;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
// create a set of coordinate axes to help orient user
// specify length in pixels in each direction
var axes = new THREE.AxisHelper(100);
scene.add( axes );
// SKY //
// recommend either a skybox or fog effect (can't use both at the same time)
// without one of these, the scene's background color is determined by webpage background
// make sure the camera's "far" value is large enough so that it will render the skyBox!
var skyBoxGeometry = new THREE.CubeGeometry( 10000, 10000, 10000 );
// BackSide: render faces from inside of the cube, instead of from outside (default).
var skyBoxMaterial = new THREE.MeshBasicMaterial( { color: 0x9999ff, side: THREE.BackSide } );
var skyBox = new THREE.Mesh( skyBoxGeometry, skyBoxMaterial );
// scene.add(skyBox);
}
function update()
{
controls.update();
stats.update();
}
//Animate function
function animate()
{
requestAnimationFrame( animate );
render();
update();
}
// Render the scene - Always goes at the end
function render()
{
renderer.render( scene, camera );
}
</script>
</body>
</html>
To rotate your cube you'll need to add some value to the cube's rotation every frame. The reason this didn't work when you did it before is that the cube is defined in your init function and the render function doesn't have a reference to it.
So your fix requires two things:
Define your cube in a scope that both methods can "see"
Add some value to the rotation of your cube every frame
Inside of the init function you're defining your cube as mesh, so rename this to cube and remove var:
//Join the two attribute ( Geometry and material )
//var mesh = new THREE.Mesh( geometry, material); // Old
cube = new THREE.Mesh( geometry, material); // new
Removing var causes cube to become a global variable defined on the dom window rather than the init function. So your render function can "see" cube. So now all you have to do is rotate it!
function render()
{
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
}
I hope that helps!
and if you'd like to learn more about scope give this link a good read, it's helped me quite a bit.
https://toddmotto.com/everything-you-wanted-to-know-about-javascript-scope/
I ctrl + f'd the code, and you don't reference the rotation of the cube once. That would explain why it's not rotating. You can't will it to rotate, you need to actually write something that will change the values of the elements in your scene.
In order to continuously change the rotation of something, you need to reference or increment its rotation in the part of the code that loops.

three.js Particles closer to camera appears larger in Orthographic Camera

It seems that with OrthographicCamera, if a particle (Points) is closer to the camera it will just appear to be larger. While, for example, BoxGeometrys with same size will always be in the same size, regardless of their distances to the camera.
See the sample below, where the green & red cubes have the same size but different distances to camera, so do the two white particles:
var container, camera, controls, scene, renderer;
init();
animate();
function init() {
var container = document.getElementById('container');
camera =
new THREE.OrthographicCamera(-window.innerWidth / 2,
window.innerWidth / 2, -window.innerHeight / 2,
window.innerHeight / 2, 1, 400);
camera.position.z = 200;
controls = new THREE.OrthographicTrackballControls(camera);
controls.addEventListener('change', render);
scene = new THREE.Scene();
var light = new THREE.DirectionalLight()
light.position.set(1, 5, 10)
scene.add(light);
var light = new THREE.DirectionalLight(0xaaaaaa)
light.position.set(-10, -1, -5)
scene.add(light);
var light = new THREE.AmbientLight(0x555555)
scene.add(light);
var pGeo = new THREE.Geometry()
var pVec1 = new THREE.Vector3
var pVec2 = new THREE.Vector3
var a = 80
pGeo.vertices.push(pVec1.fromArray([-a, -a, -a]));
pGeo.vertices.push(pVec2.fromArray([a, a, a]));
scene.add(new THREE.Points(pGeo, new THREE.PointsMaterial({
size: 80
})))
var cGeo = new THREE.BoxGeometry(80, 80, 80);
var MPG1 = new THREE.MeshPhongMaterial({
color: 0xff0000
});
var cMesh1 = new THREE.Mesh(cGeo, MPG1);
cMesh1.position.set(a, -a, -a);
cMesh1.updateMatrix();
scene.add(cMesh1);
var MPG2 = new THREE.MeshPhongMaterial({
color: 0x00ff00
});
var cMesh2 = new THREE.Mesh(cGeo, MPG2);
cMesh2.position.set(-a, a, a);
cMesh2.updateMatrix();
scene.add(cMesh2);
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
renderer.render(scene, camera)
render()
}
function animate() {
requestAnimationFrame(animate);
controls.update();
}
function render() {
renderer.render(scene, camera);
}
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrthographicTrackballControls.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Particle_Orthographic</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>
<body>
<div id="container"></div>
</body>
</html>
I want to know, whether there is something I missed that can make particles behave in the same way as other Geometry with OrthographicCamera.
Because I am trying to visualise some aluminum matrix, OrthographicCamera is quite necessary to demonstrate the uniform crystal structure. Also the matrix would vary from 4^3 to 100^3 in volume (and number of aluminum atoms), so the scene will sort of keep changing size, and other Geometry will make it very slow.
Thanks in advance
When using THREE.PointsMaterial, to prevent the particle size from attenuating (changing size) with distance from the camera, set
material.sizeAttenuation = false;
three.js r.72

threejs : error when deleting a Geometry or BufferGeometry in combination with a Sprite/Ortho camera

I load some objects using the ctm binary loader in Threejs r69. This returns Mesh objects using a BufferGeometry internally.
I need to remove from the scene then delete one of these Meshes, including their material/texture/geometry. According to examples and google, I should use:
scene.remove(m_mesh);
m_mesh.geometry.dispose();
m_mesh.geometry = null;
m_mesh.material.dispose();
m_mesh.material = null;
m_mesh = null;
This removes the object from the scene, but the screen goes black for a second, and I've got a GL error :
Error: WebGL: drawElements: no VBO bound to enabled vertex attrib index 2!
Looks like the above sequence (ran in my render() operation, just before drawing the scene) did not clean everything, or at least I still have references to non existing VBOs somewhere.
I've spent quite some time debugging the problem and came to the conclusion that this happens only when using an orthographic camera with a Sprite and a Perspective camera, in 2 differents scenes.
Basically, I draw a flat background using a Sprite and a dedicated scene, then my 3D scene with Meshes. If I delete a mesh from the 3D scene, then the drawing of the flat background fails.
I can't figure out why. Looks like there's a side effect of deleting a Mesh on Sprites, even if attached to different scenes.
If I comment the background drawing, then the deletion of my mesh works perfectly.
I insert below a reproduction of the problem using the standard threejs distribution. Wait about 5 seconds and you should see some GL errors on the jaavscript console.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - geometries</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="build/three.min.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
if (!Detector.webgl) Detector.addGetWebGLMessage();
var container, stats;
var camera, scene, renderer;
frame_count = 0;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.y = 400;
// I need a second camera for my 2D sprite (used as a background)
// must use another texture so that it's not destroyed when removing the first object
cameraOrtho = new THREE.OrthographicCamera(window.innerWidth / -2,
window.innerWidth / 2,
window.innerHeight / 2,
window.innerHeight / -2,
1, 10);
cameraOrtho.position.z = 10;
cameraOrtho.position.y = 400;
sceneBackground = new THREE.Scene();
var map1 = THREE.ImageUtils.loadTexture('textures/disturb.jpg');
var material1 = new THREE.SpriteMaterial({
map: map1
});
var spriteBackground = new THREE.Sprite(material1);
spriteBackground.scale.set(window.innerWidth, window.innerHeight, 1);
spriteBackground.position.set(window.innerWidth / 2,
window.innerHeight / 2);
sceneBackground.add(spriteBackground);
scene = new THREE.Scene();
var light;
my_object = null;
scene.add(new THREE.AmbientLight(0x404040));
light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 1, 0);
scene.add(light);
var map = THREE.ImageUtils.loadTexture('textures/UV_Grid_Sm.jpg');
map.wrapS = map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
var material = new THREE.MeshLambertMaterial({
map: map,
side: THREE.DoubleSide
});
// one object is enough to demonstrate
// can't reproduce the problem with a standard SphereGeometry
// try to convert it to a BufferGeometry
var sphereGeometry = new THREE.SphereGeometry(75, 20, 10);
var bufferGeometry = new THREE.BufferGeometry().fromGeometry(sphereGeometry);
my_object = new THREE.Mesh(bufferGeometry, material);
my_object.position.set(-400, 0, 200);
scene.add(my_object);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.autoClear = false;
renderer.autoClearDepth = false;
container.appendChild(renderer.domElement);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild(stats.domElement);
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//
function animate() {
requestAnimationFrame(animate);
render();
stats.update();
}
function render() {
frame_count++;
var timer = Date.now() * 0.0001;
camera.position.x = Math.cos(timer) * 800;
camera.position.z = Math.sin(timer) * 800;
camera.lookAt(scene.position);
//after a few frames I want to destroy completely the object
//means remove from the scene, remove texture, material, geometry
//note that here it's a Geometry, not a BufferGeometry
//may be different
if (frame_count > 60 * 5) {
if (my_object != null) {
console.log("destroy object buffer");
scene.remove(my_object);
my_object.material.map.dispose();
my_object.material.dispose();
my_object.geometry.dispose();
my_object = null;
}
}
for (var i = 0, l = scene.children.length; i < l; i++) {
var object = scene.children[i];
object.rotation.x = timer * 5;
object.rotation.y = timer * 2.5;
}
renderer.render(sceneBackground, cameraOrtho);
renderer.clearDepth();
renderer.render(scene, camera);
}
</script>
</body>
</html>
Any hints on how to fix this issue?
Thank you,
Pascal

Three js - Referencing individual meshes in imported blender scene

I am new to three.js and I have a basic blender scene with 2 different meshes which I have also named. I have managed to import the meshes into three but I would like to know how to reference and manipulate each mesh? is it possible if the 2 meshes are in the same file or should I load mesh1.js, mesh2.js etc?
This is the code:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body style="margin: 0;">
<script src="https://rawgithub.com/mrdoob/three.js/master/build/three.js"></script>
<script src="js/OrbitControls.js"></script>
<script>
// Set up the scene, camera, and renderer as global variables.
var scene, camera, renderer;
init();
animate();
// Sets up the scene.
function init() {
// Create the scene and set the scene size.
scene = new THREE.Scene();
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
// Create a renderer and add it to the DOM.
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(WIDTH, HEIGHT);
document.body.appendChild(renderer.domElement);
// Create a camera, zoom it out from the model a bit, and add it to the scene.
camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 20000);
camera.position.set(0,6,0);
scene.add(camera);
// Create an event listener that resizes the renderer with the browser window.
window.addEventListener('resize', function() {
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
});
// Set the background color of the scene.
renderer.setClearColorHex(0x333F47, 1);
// Create a light, set its position, and add it to the scene.
var light = new THREE.PointLight(0xffffff);
light.position.set(-100,-200,100);
scene.add(light);
var light2 = new THREE.PointLight(0xffffff);
light2.position.set(-100,200,100);
scene.add(light2);
// Load in the mesh and add it to the scene.
var loader = new THREE.JSONLoader();
loader.load( "tree-land.js", function( geometry, materials ){
var material = new THREE.MeshFaceMaterial( materials );
mesh = new THREE.Mesh( geometry, material );
scene.add(mesh);
});
// Add OrbitControls so that we can pan around with the mouse.
controls = new THREE.OrbitControls(camera, renderer.domElement);
}
// Renders the scene and updates the render as needed.
function animate() {
requestAnimationFrame(animate);
// Render the scene.
renderer.render(scene, camera);
controls.update();
}
</script>
</body>
</html>
The mesh variable you have declared is an Object3D, which can be manipulated using all the methods and properties as seen in the documentation: http://threejs.org/docs/#Reference/Core/Object3D
It looks like the call to JSONLoader.load returns a single geometry and material via the callback, so would not seem to support loading multiple files in a single call or multiple geometries in a single file. You might want to take a look at some of the other loaders for that purpose. I have successfully used the ColladaLoader (not in the documentation). Blender exports to Collada as well. The code is in examples/js/loaders of the repository.

three.js cube black but i added texture?

I tried adding texture to my cube I made using JS/THREE.JS.
But when I open it up in my browser its all black?
This is my code:
<html>
<head>
<title>My first Three.js app</title>
<style>canvas { width: 100%; height: 100% }</style>
</head>
<body>
<script src="https://rawgithub.com/mrdoob/three.js/master/build/three.js"></script>
<script>
// revolutions per second
var angularSpeed = 0.2;
var lastTime = 0;
// this function is executed on each animation frame
function animate(){
// update
var time = (new Date()).getTime();
var timeDiff = time - lastTime;
var angleChange = angularSpeed * timeDiff * 2 * Math.PI / 1000;
cube.rotation.y += angleChange;
lastTime = time;
// render
renderer.render(scene, camera);
// request new frame
requestAnimationFrame(function(){
animate();
});
}
// renderer
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// camera
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 500;
// scene
var scene = new THREE.Scene();
// material
var material = new THREE.MeshLambertMaterial({
map: THREE.ImageUtils.loadTexture('crate.jpg')
});
// cube
var cube = new THREE.Mesh(new THREE.CubeGeometry(200, 200, 200), material);
cube.overdraw = true;
cube.rotation.x = Math.PI * 0.1;
scene.add(cube);
// add subtle ambient lighting
var ambientLight = new THREE.AmbientLight(0xbbbbbb);
scene.add(ambientLight);
// directional lighting
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
// start animation
animate();
</script>
</body>
</html>
I used this guide to do it:
http://www.html5canvastutorials.com/three/html5-canvas-webgl-texture-with-three-js/
It might be because of having MeshLambertMaterial which needs ambient light, which you have but it may not be set correctly. Try using MeshBasicMaterial instead.
I've tested the same code you put and it works perfectly.
The only thing I've changed is the path to the image:
map: THREE.ImageUtils.loadTexture('img/textures/test.png')
Double check that the image is located in the current folder and if it is, try with another image (this one works perfect for me: https://aec-apps.com/sites/default/files/styles/app_160_160/public/Screen%20Shot%202013-10-25%20at%2000.28.49.png).
Hope it helps!

Resources