When my code runs, I don't see anything drawn on the scene. There are no errors, but I don't see the three ArrowHelper members drawn.
However, if I create 3 local ArrowHelper variables in my draw() function and add those to the scene, it works.
The ArrowHelper's are drawn each time render is called with the above code. The reason I don't want to use that version is because I think it is adding new meshes to the scene at each render call. I would prefer to only add one mesh and then change it.
I have a common function for Frame that returns a new instance of Frame. I use that common function to instantiate the variable A.
Can anyone explain what's going wrong with my first method? (Any other info, advice, etc. is welcome)
My source code is:
main.js:
var init=false;
var scene, camera, controls, renderer;
var A;
function initScene()
{
// Create scene and camera
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 5;
// Create Renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// Create controls object for mouse control of the scene
controls = new THREE.OrbitControls( camera, renderer.domElement );
A = Frame.common.unit();
A.draw();
// Set init flag
init = true;
// Call render
render();
}
function render()
{
if(!init)
{
console.log("Calling initScene");
initScene();
}
// Request frame and call controls.update()
requestAnimationFrame(render);
controls.update();
// Render
renderer.render( scene, camera );
}
frame.js:
var Frame = function(p, i, j, k)
{
console.log("Frame instance created");
this.p = p;
this.i = i;
this.j = j;
this.k = k;
this.i_arrow = new THREE.ArrowHelper( this.i, this.p, 1, 0x0000ff );
this.j_arrow = new THREE.ArrowHelper( this.j, this.p, 1, 0x00ff00 );
this.k_arrow = new THREE.ArrowHelper( this.k, this.p, 1, 0xff0000 );
};
Frame.common =
{
unit: function()
{
console.log("\"Unit\" Frame instance being created");
var p = new vec3.fromValues(0, 0, 0);
var i = new vec3.fromValues(1, 0, 0);
var j = new vec3.fromValues(0, 1, 0);
var k = new vec3.fromValues(0, 0, 1);
var result = new Frame(p, i, j, k,);
return result;
},
rand: function()
{
console.log("Random Frame instance being created");
var p = {};
vec3.random(p);
var i_hat = {};
vec3.random(i_hat);
var j_hat = {};
vec3.random(j_hat);
var k_hat = {};
vec3.random(k_hat);
var result = new Frame(p, i_hat, j_hat, k_hat);
return result;
}
} // End common
Frame.prototype.draw = function(scene)
{
scene.add(this.i_arrow, this.j_arrow, this.k_arrow);
/*var i = new THREE.Vector3(this.i[0], this.i[1], this.i[2]);
var j = new THREE.Vector3(this.j[0], this.j[1], this.j[2]);
var k = new THREE.Vector3(this.k[0], this.k[1], this.k[2]);
var p = new THREE.Vector3(this.p[0], this.p[1], this.p[2]);
var i_arrow = new THREE.ArrowHelper( i, p, 1, 0x0000ff );
var j_arrow = new THREE.ArrowHelper( j, p, 1, 0x00ff00 );
var k_arrow = new THREE.ArrowHelper( k, p, 1, 0xff0000 );
scene.add(i_arrow);
scene.add(j_arrow);
scene.add(k_arrow);*/
}
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'/>
<title>HTM Tutorial</title>
<style>
body {margin: 0;}
canvas {width: 100%; height: 100%}
</style>
</head>
<body onload='initScene()'>
<script type="text/javascript" src="node_modules/three/three.min.js"></script>
<script type="text/javascript" src="node_modules/gl-matrix/dist/gl-matrix-min.js"></script>
<script type="text/javascript" src="js/lib/OrbitControls.js"></script>
<script type="text/javascript" src="js/frame.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
Related
i dynamically create some dots on 3D canvas with constructor (using three.js and javascript), using set of x y z coordinates, then i dynamically create lines also with constructor, between that dots. So then, when i want to pick that lines, raycaster wont recognize them. I tried to make the same lines without constructor, simply onload of browser, and then it works just fine. Also, dot picking is working fine.
all dots and beams i push in to arrays called allJoints[] and allBeams[].
i tried to create lines with THREE.MeshLIne using new Float32Array, MeshLine(), setGeometry, MeshLineMaterial and THREE.Mesh, but same problem occurs.
//dots:
function Joint(jointX,jointY,jointZ,jointCounter) {
console.log("nacrtaj tacku");
this.jointX = jointX;
this.jointY = jointY;
this.jointZ = jointZ;
this.jointNo = jointCounter;
this.dot;
this.deleteState = true;
this.makeDot = function () {
let dotGeometry = new THREE.Geometry();
dotGeometry.vertices.push(new THREE.Vector3( this.jointX,
this.jointY, this.jointZ));
let dotMaterial = new THREE.PointsMaterial( { size: 8,
color:"#ffccff", sizeAttenuation: false} );
this.dot = new THREE.Points( dotGeometry, dotMaterial )
}
this.drawDot = function () {
scene.add( this.dot );
renderer.render( scene, camera );
}
this.makeDot();
this.drawDot();
}
//Beams:
function Beam(firstNodeNo,secondNodeNo,beamCounter) {
this.deleteState = true;
this.firstNodeNo = allJoints[firstNodeNo].jointNo;
this.secondNodeNo = allJoints[secondNodeNo].jointNo;
this.beam;
this.makeBeam = function () {
let material = new THREE.LineBasicMaterial( { color: 0x0000ff
} );
let geometry = new THREE.Geometry();
geometry.vertices.push( new THREE.Vector3(
allJoints[firstNodeNo].jointX, allJoints[firstNodeNo].jointY,
allJoints[firstNodeNo].jointZ),
new THREE.Vector3( allJoints[secondNodeNo].jointX,
allJoints[secondNodeNo].jointY, allJoints[secondNodeNo].jointZ) );
this.beam = new THREE.Line( geometry, material );
}
this.drawBeam = function () {
scene.add( this.beam );
}
this.makeBeam();
this.drawBeam();
//raycaster:
class PickHelper {
constructor() {
this.raycaster = new THREE.Raycaster();
this.pickedObject0 = null;
this.pickedObjectSavedColor0 = 0;
}
pick(normalizedPosition, scene, camera) {
if (this.pickedObject0) {
this.pickedObject0.material.color.setHex(this.pickedObjectSavedColor0);
this.pickedObject0 = undefined;
}
this.raycaster.setFromCamera(normalizedPosition, camera);
const intersectedObjects =
this.raycaster.intersectObjects(scene.children, true);
if (intersectedObjects.length>0) {
console.log('intersectedObjects[ 0 ].object.geometry.type = ' +
intersectedObjects[ 0 ].object.geometry.type);
for (let i = 0; i < allJoints.length; i++) {
if (intersectedObjects[0].object === allJoints[i].dot) {
this.pickedObject0 = intersectedObjects[0].object;
this.pickedObjectSavedColor0 =
this.pickedObject0.material.color.getHex();
this.pickedObject0.material.color.setHex(0xFF0000);
}
}
for (let i = 0; i < allBeams.length; i++) {
if (intersectedObjects[0].object === allBeams[i].beam){
console.log('allBeams = ' + i);
}
}
}}}
//renderer:
function render() {if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
pickHelper.pick(pickPosition, scene, camera);
renderer.render(scene, camera);
requestAnimationFrame(render);
}
I'm new at ThreeJS and trying to learn so I have basically create a text which is rendered 3D and I'm using TextGeometry and I need that object's size like width/height to always center the object.
I'm trying like this;
var objToCenter = scene.getObjectById(textGeoID);
var hey = objToCenter.geometry.boundingSphere.center.x;
console.log(hey);
First, I find the object and then assign boundingSphere.center.x value to new variable.
But I get "boundingSphere is null" error.
When I try to console.log objectToCenter, object is there and also boundingSphere is NOT null but when I try objectToCenter.boundingSphere it says null.
And interestingly when I go console and write these lines it works perfectly.
My full Code: (somehow fontloader not load the font from source url but it works in localhost,so pls try code in localhost or you can't see the text here)
// Scene, Camera, Renderer, GUI
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 } );
var gui = new dat.GUI({name: 'Control Panel'});
// Renderer and Camera Settings
renderer.setSize( window.innerWidth, window.innerHeight-4 );
renderer.shadowMap.enabled = false;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild( renderer.domElement );
camera.position.set( 10, 10, 500 );
// Axiss Helper and Orbit Controls
var axesHelper = new THREE.AxesHelper( 500 );
scene.add( axesHelper );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
// Variables for TextGeometry
var textData = {
text: "Yunus Emre Uzun",
size: 40,
height: 5,
curveSegments: 12,
font: "helvetiker",
weight: "regular",
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 0.5,
bevelOffset: 0.0,
bevelSegments: 3
};
var textGeoID = null;
function generateTextGeometry() {
if (textGeoID!=null) {
console.log('ID: ' + textGeoID);
var object = scene.getObjectById(textGeoID);
//console.log('Object:');
//console.log(object);
object.geometry.dispose();
scene.remove(object);
}
var loader = new THREE.FontLoader();
loader.load( 'https://clofro.com/cdn/fonts/helvetiker_regular.typeface.json', function ( font ) {
var textGeometry = new THREE.TextGeometry( textData.text, {
font: font,
size: textData.size,
height: textData.height,
curveSegments: textData.curveSegments,
bevelEnabled: textData.bevelEnabled,
bevelThickness: textData.bevelThickness,
bevelSize: textData.bevelSize,
bevelOffset: textData.bevelOffset,
bevelSegments: textData.bevelSegments
} );
var textMaterial = new THREE.MeshBasicMaterial( { color: 0x444444, wireframe: true } );
var meshedObject = new THREE.Mesh( textGeometry, textMaterial );
meshedObject.position.set(-212, -15, 20 /* 15 */);
scene.add(meshedObject);
textGeoID = meshedObject.id;
centerTheText();
} );
}
function centerTheText() {
var objToCenter = scene.getObjectById(textGeoID);
console.log('Object bellow is objToCenter and its id is: ' + objToCenter.id);
console.log(objToCenter);
console.log('Error bellow is for: objToCenter.geometry.boundingSphere.center.x');
var hey = objToCenter.geometry.boundingSphere.center.x;
console.log(hey);
}
generateTextGeometry();
gui.add(textData, 'text').onChange(generateTextGeometry);
gui.add(textData, 'size', 5, 100).onChange(generateTextGeometry);
// Add Point Light
var pointLight = new THREE.PointLight(0xffffff, 0.3); pointLight.position.set(50, 0, 150);
pointLight.castShadow = true;
pointLight.shadow.mapSize.width = 2048;
pointLight.shadow.mapSize.height = 2048;
scene.add(pointLight);
// Random colors
//pointLight.color.setHSL(Math.random(), 1, 0.5);
// Add Ambiant Light - halogen ambient light
var ambientLight = new THREE.AmbientLight(0xFFF1E0, 0.4);
scene.add(ambientLight);
var width = 450;
var height = 60;
var intensity = 0.8;
var rectLight = new THREE.RectAreaLight( 0xff0000, intensity, width, height );
rectLight.position.set( 0, 0, 14 );
rectLight.rotation.y = 6.28;
rectLight.lookAt( 0,0,0 );
scene.add( rectLight )
gui.add(rectLight, 'intensity', 0,5);
rectLightHelper = new THREE.RectAreaLightHelper( rectLight );
rectLight.add( rectLightHelper );
// Create BackBox Shape
var backBoxGeo = new THREE.BoxGeometry(500, 75, 10);
// Create BackBox Material, color, texture
var backBoxMat = new THREE.MeshStandardMaterial( { color: 0xdaf1f9, wireframe: false, flatShading: false } );
var backBox = new THREE.Mesh( backBoxGeo, backBoxMat );
backBox.receiveShadow = true;
scene.add(backBox);
backBox.position.set(0, 0, 0);
// Resize Renderer Function
window.addEventListener('resize', function() {
renderer.setSize( window.innerWidth, window.innerHeight-4 );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
// Update scene
var update = function() {
controls.update();
};
// Draw scene
var render = function() {
renderer.render( scene, camera );
};
// Frame loop (update, render, repeat)
var frameLoop = function() {
requestAnimationFrame( frameLoop );
update();
render();
}
frameLoop();
* {
margin: 0;
padding: 0;
}
body { background-color: #000; }
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>threeJS</title>
</head>
<body>
<script src="https://clofro.com/cdn/three.js"></script>
<script src="https://clofro.com/cdn/dat.gui.min.js"></script>
<script src="https://clofro.com/cdn/OrbitControls.js"></script>
</body>
</html>
My explanations with SS;
Screenshot 1:
Screenshot 2:
Why it could be happening? or can I use something else to center my text.
(set position not a fix because 0,0,0 is different for box objects and texts)
When you create an instance of TextGeometry, the respective bounding sphere is not available yet. However, it is automatically computed by the renderer for view frustum culling.
So if you have to access the bounding sphere of the geometry right after its creation, call objToCenter.geometry.computeBoundingSphere();.
Live Demo: https://jsfiddle.net/zcn2tpqy/
three.js R107
I know this is too old to answer, but I just want to share my solution here.
First, I just added this code:
geometry.computeBoundingSphere()
Then, access the boundingSphere like so:
geometry.boundingSphere
Overall code
geometry.computeBoundingSphere()
console.log(geometry.boundingSphere.radius)
I am rendering a 3D human head using three.js and OBJLoader:
let renderer, camera, scene, head, light, projectiles;
new THREE.OBJLoader().load(objUrl, initialize);
function initialize(obj) {
renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight);
scene = new THREE.Scene();
head = obj.clone();
head.children.forEach(child => child.material = new THREE.MeshPhongMaterial({ color: "#ffc700" }));
head.position.y = -34;
head.position.z = -110;
scene.add(head);
light = new THREE.SpotLight();
light.target = head;
scene.add(light);
projectiles = [];
window.addEventListener("mousedown", createProjectile, false);
animate();
}
function animate() {
head.rotation.y += THREE.Math.degToRad(1);
projectiles.forEach(updateProjectile);
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function createProjectile() {
let projectile = new THREE.Mesh();
projectile.material = new THREE.MeshToonMaterial({ color: "#ff0000" });
projectile.geometry = new THREE.SphereGeometry(3, 20, 20);
projectile.position.copy(getMouthPosition());
scene.add(projectile);
projectiles.push(projectile);
}
function updateProjectile(projectile) {
// TODO: Move projectile in the direction the mouth was facing when projectile was first created.
projectile.position.x += 2;
}
function getMouthPosition() {
// TODO: Determine the world position of the mouth.
let box = new THREE.Box3().setFromObject(head);
return box.getCenter();
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
border: 0;
}
canvas {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/86/three.js">
</script>
<script src="https://wzrd.in/standalone/three-obj-loader#1.1.3">
</script>
<script>
threeObjLoader(THREE);
objUrl = "https://cdn.rawgit.com/mrdoob/three.js/f32fc45/examples/obj/walt/WaltHead.obj";
</script>
When the mouse is clicked, I want to "shoot" a projectile/bullet from the rotating head's mouth. But as you can see from the TODO comments in the code, there are two functions I don't know how to implement: getMouthPosition() and updateProjectile().
For getMouthPosition(), I want to determine the current position of the mouth and spawn the projectile at this location (ideally, just in front of the mouth).
For updateProjectile(), I want to move the projectile in the direction the head was facing at the time when the projectile was first created, like this:
If someone could shed light on how to write these functions, that would be great. Thanks.
Look. Somehow you'll get where the mouth locates (in coordinates of the head group it locates at about [0, 25, 20]). Then, to get position of the mouth of the spinning head, you can use .localToWorld(v) method, like so:
head.localToWorld(mouthPosition.copy(spawnPoint.position));
spawnPoint is a "helper" object to indicate where our spawn point is.
Further, you have to know where your head points at. You can get it with another method .getWorldDirection() of the head object.
Concluding all of this: you know position of the head's mouth, you know its direction, thus you can cast a projectile, using those values.
let renderer, camera, scene, head, light, projectiles, spawnPoint, clock = new THREE.Clock(), delta = 0;
new THREE.OBJLoader().load(objUrl, initialize);
function initialize(obj) {
renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight);
scene = new THREE.Scene();
head = obj.clone();
head.children.forEach(child => child.material = new THREE.MeshPhongMaterial({ color: Math.random() * 0xffffff }));
head.position.y = -34;
head.position.z = -110;
scene.add(head);
light = new THREE.SpotLight();
light.target = head;
scene.add(light);
spawnPoint = new THREE.Mesh(new THREE.SphereGeometry(1, 4, 2), new THREE.MeshBasicMaterial({color: "red", wireframe: true}));
spawnPoint.position.set(0, 25, 20);
head.add(spawnPoint);
projectiles = [];
window.addEventListener("mousedown", event => { createProjectile(); }, false);
animate();
}
function animate() {
delta = clock.getDelta();
requestAnimationFrame(animate);
head.rotation.y += THREE.Math.degToRad(20) * delta;
projectiles.forEach(p => {
p.position.addScaledVector(p.userData.direction, p.userData.speed * delta);
});
renderer.render(scene, camera);
}
function createProjectile() {
let projectile = new THREE.Mesh();
projectile.material = new THREE.MeshToonMaterial({ color: 0xff0000 });
projectile.geometry = new THREE.SphereGeometry(3, 16, 12);
let pos = getMouthPosition();
console.log("pos", pos);
projectile.position.copy(pos);
projectile.userData.direction = new THREE.Vector3().copy(head.getWorldDirection().normalize());
console.log(projectile.userData.direction);
projectile.userData.speed = 50;
scene.add(projectile);
projectiles.push(projectile);
console.log(projectiles);
}
function getMouthPosition() {
let mouthPosition = new THREE.Vector3();
console.log("spawnPoint", spawnPoint);
head.localToWorld(mouthPosition.copy(spawnPoint.position));
console.log("mouthPosition", mouthPosition);
return mouthPosition;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
border: 0;
}
canvas {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/86/three.js">
</script>
<script src="https://wzrd.in/standalone/three-obj-loader#1.1.3">
</script>
<script>
threeObjLoader(THREE);
objUrl = "https://cdn.rawgit.com/mrdoob/three.js/f32fc45/examples/obj/walt/WaltHead.obj";
</script>
It was hard to describe the problem in a single line so this is the situation.
I am going to build a big Javascript project with Three.js so I'm trying to grasp it's OOP concepts.
1) I created a 3D world Object
2) A base 3D_object class with child classes
3) In the sample bellow you see an option 1 and an option 2 these should produce the same result, but somehow they don't. Any idea why ? The complete source is in the snippet.
(Three.js should be included before the script and I am assuming there is a 'resources/object.json' file )
Here is a github link of the project, maybe someone will find it this way. (probably need to run it on a local python server for example to bypass the cross-origin file loading problem in chrome)
//create world
var myWorld = new World(500,500);
myWorld.AddWorldToPage();
//load simple model in the world
var cube = new Cube();
myWorld.addToScene(cube);
// load json model in the world
//option 1
// myWorld.addToSceneTemp();
//option 2 OO (not working)
var jsonObject = new Object_3D_JSON();
function afterModelLoaded(){
console.log("after loading is done");
myWorld.addToScene(jsonObject);
}
jsonObject.loadModel(afterModelLoaded);
myWorld.render();
// Inhertit convencience method
//=====================================================================================================
function inheritsF / rom(child, parent) {
child.prototype = new parent();
child.prototype.constructor = child;
}
// 3D Objects
//=====================================================================================================
// 3D object class
//=====================================================================================================
function Object_3DClass() {
this._geometry = new THREE.BoxGeometry(1, 1, 1);
this._material = new THREE.MeshBasicMaterial({
color: 0xff00ff
});
this._mesh = new THREE.Mesh(this._geometry, this._material);
}
//Get 3D mesh
Object_3DClass.prototype.getMesh = function() {
return this._mesh;
}
//Animate Object
Object_3DClass.prototype.animateFrame = function() {
this._mesh.rotation.x += 0.01;
this._mesh.rotation.y += 0.01;
}
Object_3DClass.prototype.setPosition = function(x, y, z) {
this._mesh.position.set(x, y, z);
}
// END 3D object class
//===================================================================================================
// 3D Cube class
//=====================================================================================================
function Cube() {
this._geometry = new THREE.BoxGeometry(1, 1, 1);
this._material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
this._mesh = new THREE.Mesh(this._geometry, this._material);
}
inheritsFrom(Cube, Object_3DClass)
// END OF 3D Cube class
//=====================================================================================================
// 3D JSON Model class
//=====================================================================================================
function Object_3D_JSON() {
// instantiate a loader
this._loader = new THREE.JSONLoader();
this._mesh = null;
}
inheritsFrom(Object_3D_JSON, Object_3DClass);
//loadModel
Object_3D_JSON.prototype.loadModel = function(whenReady_Fn) {
// _geometry = this._geometry;
var self = this;
// load a resource
this._loader.load(
// resource URL
'resources/object.json',
// Function when resource is loaded
function(geometry, materials) {
console.log("loading");
// this._material = new THREE.MultiMaterial( materials );
self._material = new THREE.MeshBasicMaterial({
color: 0xffffff
});
self._mesh = new THREE.Mesh(geometry, materials);
self._geometry = geometry;
whenReady_Fn();
// scene.add( this._mesh );
},
//onProgress
function() {},
//onError
function() {
console.log("resource not found");
}
);
}
// END OF 3D JSON Model class
//=====================================================================================================
// World class
//=====================================================================================================
var World = (function() {
// World constructor
function World(width, height) {
//private members
//===========================
this._width = width;
this._height = height;
this._scene = new THREE.Scene();
this._camera = new THREE.PerspectiveCamera(75, this._width / this._height, 0.1, 1000);
this._camera.position.set(6.8, 9.5, 12.2);
this._camera.lookAt(new THREE.Vector3(0, 0, 0));
this._renderer = new THREE.WebGLRenderer();
this._renderer.setSize(this._width, this._height);
this._worldName = "Tubrines";
this._object_3DList = [];
return _privatePrintMessage.call(this, "message");
}
//public
//===========================
//functions
World.prototype.AddWorldToPage = function() {
document.body.appendChild(this._renderer.domElement);
}
World.prototype.render = function() {
//zichzelf meegeven aan AnimationFrame
requestAnimationFrame(this.render.bind(this));
this._object_3DList[0].animateFrame();
this._renderer.render(this._scene, this._camera);
}
World.prototype.addToScene = function(object_3DClass) {
this._scene.add(object_3DClass.getMesh());
this._object_3DList.push(object_3DClass);
}
World.prototype.addToSceneTemp = function() {
_scene = this._scene;
_object_3DList = this._object_3DList;
// instantiate a loader
var loader = new THREE.JSONLoader();
// load a resource
loader.load(
// resource URL
'resources/object.json',
// Function when resource is loaded
function(geometry, materials) {
// var material = new THREE.MultiMaterial( materials );
var material = new THREE.MeshBasicMaterial({
color: 0xff00ff
});
var mesh = new THREE.Mesh(geometry, material);
_scene.add(mesh);
_object_3DList.push(mesh);
});
}
//private functions
//===========================
function _privatePrintMessage(message) {
// return prefix + this._foo;
console.log("World class: " + this._worldName + " " + message);
}
return World;
})();
// END OF World class
//=====================================================================================================
//create world
var myWorld = new World(500, 500);
myWorld.AddWorldToPage();
//load simple model in the world
var cube = new Cube();
myWorld.addToScene(cube);
// load json model in the world
//option 1
// myWorld.addToSceneTemp();
//option 2 OO (not working)
var jsonObject = new Object_3D_JSON();
function afterModelLoaded() {
console.log("after loading is done");
myWorld.addToScene(jsonObject);
}
jsonObject.loadModel(afterModelLoaded);
myWorld.render();
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title>My first three.js app</title>
<style>
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<script src="script.js"></script>
</body>
</html>
You are trying to pass a list of materials without telling three.js it's a multimaterial.
Change this line:
self._mesh = new THREE.Mesh( geometry , materials );
to:
var materialSet = new THREE.MultiMaterial( materials );
self._mesh = new THREE.Mesh( geometry , materialSet );
And now that you're using the proper json supplied material, you need to add a light to the scene, otherwise the lambert materials in your model will not show. (lambert materials require lights, basic materials do not, which is why the cube worked).
this._scene = new THREE.Scene();
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( 100, 1000, 100 );
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.camera.near = 500;
spotLight.shadow.camera.far = 4000;
spotLight.shadow.camera.fov = 30;
this._scene.add( spotLight );
i'm new in three.js and have a problem by scaling a object. I already looked at the documentation (https://github.com/mrdoob/three.js/wiki/Updates), but i don't really understand it at all.
My Problem: By changing a HTML-select-element the CubeGeometry should be scaled in the x-direction. That is already working BUT the "old" Cube do not disappear. So i have 2 Cubes. But i want only one Cube with the current size. I hope you can understand my problem ;-)
So here is my Code from the View:
$(document).on('change',".configurator > form select",function(event){
// update 3D-object - is that a nice way???
$.getScript("/javascripts/3D-animation.js.erb", function(){
// here comes the update
OBJECT3D.updateObject();
});
})
And here is my 3D-animation.js.erb:
var drawing_area;
var renderer;
var camera;
var obj;
var scene;
var OBJECT3D = {};
$(function() {
// get drawing_area
drawing_area = document.getElementById("canvas_wrapper");
// initialize renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(drawing_area.clientWidth, drawing_area.clientHeight);
renderer.setClearColor( 0xffffff, 1);
// add renderer to drawing_area
drawing_area.appendChild(renderer.domElement);
// initialize camera
camera = new THREE.PerspectiveCamera(45, drawing_area.clientWidth/drawing_area.clientHeight, 1, 100000);
camera.position.z = 1000;
camera.position.y = 100;
camera.position.x = 300;//-0.78;
// create texture
var texture = THREE.ImageUtils.loadTexture( "/images/materials/texture_1.jpg" );
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 1, 1 );
// create object
var obj_form = new THREE.CubeGeometry(250,250,250);
var obj_material = new THREE.MeshLambertMaterial( { map: texture,ambient: 0x999999 } );
OBJECT3D.obj = new THREE.Mesh(obj_form, obj_material);
// so what do i need here?
OBJECT3D.obj.geometry.dynamic = true;
// OBJECT3D.obj.geometry.__dirtyVertices = true;
// OBJECT3D.obj.geometry.__dirtyNormals = true;
// OBJECT3D.obj.geometry.verticesNeedUpdate = true;
// create scene
scene = new THREE.Scene();
scene.add(camera);
scene.add(OBJECT3D.obj);
// create lights
pointLight = new THREE.PointLight(0xFFFFFF);
pointLight.position.x = 400;
pointLight.position.y = 200;
pointLight.position.z = 1300;
scene.add(pointLight);
ambientLight = new THREE.AmbientLight( 0xffffff);
scene.add( ambientLight );
requestAnimationFrame(render);
function render(){
requestAnimationFrame(render);
OBJECT3D.obj.rotation.y += 0.005;
OBJECT3D.obj.rotation.z += 0.005;
renderer.render(scene, camera);
};
// update object
OBJECT3D.updateObject = function () {
console.log("in update");
OBJECT3D.obj.scale.x = 2.5; // SCALE
OBJECT3D.obj.geometry.needsUpdate = true;
//render();
}
});
Sorry, if the Code is not the best one, but i'm really new in this stuff! :) hope you can help me!
Thanks!
I think it is because you are using $.getScript method. This will load your script each time again and create a new instance of OBJECT3D.
I propose that you make sure that your code in 3D-animation.js.erb will be included and called only once upon the load of a page (include it just like any other regular javascript file) and then call your update directly like this:
$(document).on('change',".configurator > form select", function(event) {
OBJECT3D.updateObject();
});
also, I believe you can drop following lines of code:
OBJECT3D.obj.geometry.needsUpdate = true;
and
OBJECT3D.obj.geometry.dynamic = true;