I am trying to add a mesh on an onclick event in a running ThreeJS scene. The mesh shows up when I add it to the scene object. However when I try to add it to an existing group in the scene, the box remains invisible. What am I missing?:
onclick_function(){
//find group object
var group = scene.getObjectByName('myGroupName');
//create box
var geometry = new THREE.BoxBufferGeometry();
var material = new THREE.MeshPhongMaterial();
var obj = new THREE.Mesh(geometry, material);
//this works:
//scene.add(obj);
//however when added to the group object, the box remains invisible:
group.add(obj);
}
Ok, it appeared that the object was indeed out of view, my mistake. Thanks for your attempts to help!
Related
In three.js, I want to add a mesh to a position in the scene
I've tried:
// mesh is an instance of THREE.Mesh
// scene is an instance of THREE.Scene
scene.add(mesh)
scene.updateMatrixWorld(true)
mesh.matrixWorld.setPosition(new THREE.Vector3(100, 100, 100))
scene.updateMatrix()
BUT it didn't affect anything.
What should I do ?
I would recommend you to check the documentation over here:
http://threejs.org/docs/#Reference/Objects/Mesh
As you can see on the top of the docu-page, Mesh inherits from "Object3D". That means that you can use all methods or properties that are provided by Object3D. So click on the "Object3D" link on the docu-page and check the properties list. You will find the property ".position". Click on ".position" to see what data-type it is. Paha..its Vector3.
So try to do the following:
// scene is an instance of THREE.Scene
scene.add(mesh);
mesh.position.set(100, 100, 100);
i saw it on a github earlier. (three.js r71 )
mesh.position.set(100, 100, 100);
and can be done for individuals
mesh.position.setX(200);
mesh.position.setZ(200);
reference: https://threejs.org/docs/#api/math/Vector3
detailed explanation is below:
since mesh.position is "Vector3". Vector3() has setX() setY() and setZ() methods. we can use it like this.
mesh.position = new THREE.Vector3() ; //see position is Vector3()
vector1 = new THREE.Vector3();
mesh.position.setX(100); //or this
vector1.setX(100) // because all of them is Vector3()
camera1.position.setZ(100); // or this
light1.position.setY(100) // applicable to any object.position
I prefer to use Vector3 to set position.
let group = new THREE.Group();
// position of box
let vector = new THREE.Vector3(10, 10, 10);
// add wooden Box
let woodenBox = new THREE.Mesh(boxGeometry, woodMaterial);
//update postion
woodenBox.position.copy(vector);
// add to scene
group.add(woodenBox)
this.scene.add(group);
If some one looking for way to update position from Vector3
const V3 = new THREE.Vector3(0,0,0) // Create variable in zero position
const box = new THREE.Mesh(geometry, material) // Create an object
Object.assign(box.position, V3) // Put the object in zero position
OR
const V3 = new THREE.Vector3(0,0,0) // Create variable in zero position
const box = new THREE.Mesh(geometry, material) // Create an object
box.position.copy(V3)
UPDATE: Issue was that texData object was recreated each time and thus reference for DataTexture was lost. Solution by WestLangley was to overwrite the data in texData instead of recreating texData object.
I have a simple threejs scene with a DataTexture in a ShaderMaterial. The data array passed to it once during initialization is updated on mouse events. However the DataTexture does not seem to update.
Did i assign uniforms or texture data wrongly? Or using the needsUpdate flags wrongly? It does work when deleting and recreating the texture, material, mesh and scene objects each time, but this shouldnt really be necessary as i have seen from many examples which i could however not reproduce.
Note that the data itself is updated nicely, just not the DataTexture.
// mouse event triggers request to server
// server then replies and this code here is called
// NOTE: this code **is** indeed called on every mouse update!
// this is the updated data from the msg received
// NOTE: texData **does** contain the correct updated data on each event
texData = new Float32Array(evt.data.slice(0, msgByteLength));
// init should happen only once
if (!drawContextInitialized) {
// init data texture
dataTexture = new THREE.DataTexture(texData, texWidth, texHeight, THREE.LuminanceFormat, THREE.FloatType);
dataTexture.needsUpdate = true;
// shader material
material = new THREE.ShaderMaterial({
vertexShader: document.querySelector('#vertexShader').textContent.trim(),
fragmentShader: document.querySelector('#fragmentShader').textContent.trim(),
uniforms: {
dataTexture: { value: dataTexture }
}
});
// mesh with quad geometry and material
geometry = new THREE.PlaneGeometry(width, height, 1, 1);
mesh = new THREE.Mesh(geometry, material);
// scene
scene = new THREE.Scene();
scene.add(mesh);
// camera + renderer setup
// [...]
drawContextInitialized = true;
}
// these lines seem to have no effect
dataTexture.needsUpdate = true;
material.needsUpdate = true;
mesh.needsUpdate = true;
scene.needsUpdate = true;
renderer.render(scene, camera);
When updating the DataTexture data, do not instantiate a new array. Instead, update the array elements like so:
texData.set( javascript_array );
Also, the only flag you need to set when you update the texture data is:
dataTexture.needsUpdate = true;
three.js r.83
I had a real hard time for some reason seeing any change to modifactions . In desperation i just made a new DataTexture . Its important to set needsUpdate to true
imgData.set(updatedData)
var newDataTex = new THREE.DataTexture( imgData,...
var newDataTex.needsUpdate = true
renderMesh.material.uniforms.texture.value = newDataTex
I'm trying to apply a texture to a planeGeometry using the three.js engine.
I should be seeing a football field, I'm actually seeing black.
If I replace the map:texture argument with color:0x80ff80, I get a field of solid green, demonstrating that the geometry is in the correct place.
The page contains an which appears in the files before any scripts. I can display that image, demonstrating that there isn't a problem with the image.
The files are being served locally by an http server.
The code I'm using to build the material and PlaneGeometry is below. Any ideas appreciated. Thank you.
function buildField( fieldLength, fieldWidth, scene) {
var image = document.getElementById("fieldTexture");
var texture = new THREE.Texture(image);
texture.minFilter = THREE.LinearFilter;
var geometry = new THREE.PlaneGeometry(fieldLength, fieldWidth, 5, 5);
var material = new THREE.MeshBasicMaterial( {map:texture, side:THREE.DoubleSide});
var field = new THREE.Mesh(geometry, material);
field.rotation.x = -Math.PI/2;
scene.add(field);
}
THREE.ImageUtils is already deprecated. (source)
Use THREE.TextureLoader().load('field.png') instead
Try this, own THREE.js methods usually work better...:
texture = THREE.ImageUtils.loadTexture('field.png');
material = new THREE.MeshBasicMaterial({map: texture});
var field = new THREE.Mesh(geometry, material);
I am trying to render a scene of a room with multiple lights inside it. The weird part is that the effects of the lights is visible on three sides of the room but the right side of the room doesn't reflect any light and is pitch black. The material on all sides of the room is same and is THREE.MeshPhongMaterial. I used THREE.DoubleSide as well but it didn't help.
Am I missing something?
Following is the code for loading the room.
var loader = new THREE.JSONLoader();
loader.load(model, function(geometry, materials){
for(i=0;i<materials.length;i++){
materials[i].shading = THREE.SmoothShading;
materials[i].wrapAround = true;
}
var jsmesh = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));
jsmesh.scale.set(100,100,100);
jsmesh.position.y=159;
jsmesh.position.x=177;
jsmesh.position.z=-180;
jsmesh.name = model;
jsmesh.receiveShadow = true;
jsmesh.overdraw = true;
scene.add(jsmesh);
});
pointLight = new THREE.PointLight(0xffffff, 0.5 , 800);
scene.add(pointLight);
I am adding few point lights to this mesh (which is a room). The effects of light come on left, top and front walls. But the right wall is black.
I'm doing a student project at involves a gift box where users can change how it looks.
I started learning what to do by making a cube, importing a texture and setting a gui.dat control to allow the user to change the texture.
I'm now trying to replace the cube with a blender model of a gift box but I'm having trouble changing the texture.
EDIT: The full code is on github here:
https://github.com/GitKiwi/GiftBox/blob/master/Workspace/Proto%208c%20Changing%20textures%20on%20giftbox.html
The coding for the working cube model is:
`// add cube with texture
var cubeGeometry = new THREE.CubeGeometry(4,4,4);
var cubeMaterial = new THREE.MeshLambertMaterial({ map:
THREE.ImageUtils.loadTexture("birthday.jpg") });
var cube = new THREE.Mesh(cubeGeometry,cubeMaterial);
cube.position.set (0,0,0);
cube.rotation.set (0,-1.2,0);
cube.receiveShadow = true;
// add the cube to scene
scene.add(cube); `
//gui texture change
`var controls = new function()
{ this.changeTexture = "birthday";
this.changeTexture = function (e){
var texture = THREE.ImageUtils.loadTexture
("../assets/textures/general/" + e + ".jpg");
cube.material.map = texture; }`
//gui control
var gui = new dat.GUI();
gui.add(controls, "changeTexture", ['christmas', 'valentine', 'birthday']).onChange(controls.changeTexture);
I'm loading the gift box in four parts and I'm just trying to get the first part, the box, to change texture. I load it with:
var box;
var loaderOne = new THREE.JSONLoader();
loaderOne.load('../assets/models/box.js', function (geometry)
{
var material = new THREE.MeshLambertMaterial({color: 0xffff00});
box = new THREE.Mesh(geometry, material);
box.position.set (5,0,5);
box.scale.set (1,1,1);
//box.name = "mybox";
scene.add(box);
});
I can't get it to change texture with the gui control. I've tried changing the "cube" to "box" in the gui texture change code and I've tried naming the box and calling it(commented out in the code above) but those didn't work. I've searched for answers to this in a number of places but I'm just really stuck. I feel I'm perhaps missing something obvious?
Any help to would really be appreciated.
The code wasn't working because there were no texture maps for the model I was importing.
What I did was go back to Blender and create a model with two textures that could each be applied to the whole model. The exported JSON file then had the model geometry and the two textures (with their texture maps).
In three.js I loaded it:
// load in geometry and textures
var loader = new THREE.JSONLoader();
loader.load('../models/two textures on cube.js', function (geometry, material)
{
matOne = new THREE.MeshLambertMaterial(material[1]);
matTwo = new THREE.MeshLambertMaterial(material[2]);
box = new THREE.Mesh(geometry, matOne);
//position, scale
box.position.set (0,0,0);
box.rotation.set (0,-1.2,0);
box.scale.set (2,2,2);
box.receiveShadow = true;
scene.add(box);
}, '../models');
and then used this code to switch the textures:
//gui control panel
var controls = new function()
{
//changing the texture
this.changeTexture = function (e)
{
switch (e)
{
case "birthday":
box.material = matOne;
break;
case "christmas":
box.material = matTwo;
break;
}
}
}
with this code for the gui.dat controls:
//gui control panel
var gui = new dat.GUI();
gui.add(controls, "changeTexture", ['birthday', 'christmas']).onChange(controls.changeTexture);