I was at the following site http://stemkoski.github.io/Three.js/ looking at three.js examples and came across the Constructive Solid Geometry example. This tutorial by example shows how to subtract a cube from a sphere. The example uses THREE.MeshNormalMaterial();. I would like to add an image to the sphere before subtracting the cube from it. I'm going to list the code below.
Code from the example
var materialNormal = new THREE.MeshNormalMaterial();
var cubeGeometry = new THREE.CubeGeometry( 100, 100, 100, 1, 1, 1 );
var cubeMesh = new THREE.Mesh( cubeGeometry );
var cubeBSP = new ThreeBSP( cubeMesh );
var sphereGeometry = new THREE.SphereGeometry( 60, 32, 32 );
var sphereMesh = new THREE.Mesh( sphereGeometry );
var sphereBSP = new ThreeBSP( sphereMesh );
// Example #2 - Sphere subtract Cube
var newBSP = sphereBSP.subtract( cubeBSP );
var newMesh = newBSP.toMesh( materialNormal );
newMesh.position.set(180, 60, 0);
scene.add( newMesh );
To achive my goal of adding an image I altered the code slightly. Changing materialNormal to materialBasic.
var spherImg2 = new THREE.ImageUtils.loadTexture( 'images/roomDoorsb.jpg' );
var materialBasic = new THREE.MeshBasicMaterial( { map: spherImg2, side:THREE.DoubleSide } );
var cubeGeometry = new THREE.CubeGeometry( 100, 100, 100, 1, 1, 1 );
var cubeMesh = new THREE.Mesh( cubeGeometry );
var cubeBSP = new ThreeBSP( cubeMesh );
var sphereGeometry = new THREE.SphereGeometry( 60, 32, 32 );
var sphereMesh = new THREE.Mesh( sphereGeometry );
var sphereBSP = new ThreeBSP( sphereMesh );
// Example #2 - Sphere subtract Cube
var newBSP = sphereBSP.subtract( cubeBSP );
var newMesh = newBSP.toMesh( materialBasic );
newMesh.position.set(180, 60, 0);
scene.add( newMesh );
The remaining sections of the sphere do not display the desired image. There just showing grey. Also I would like to note that the ThreeCSG.js file from the example was throwing an error. I think line 215 was out of date so I replaced it.
It was
mesh.rotation.setEulerFromRotationMatrix( this.matrix );
And I changed it to
mesh.quaternion.setFromRotationMatrix( this.matrix );
I would be very grateful for any help received. Thanks
Related
I have a basic scene in threejs that loads a .stl file, it loads normally, but it automatically changes color and I also want it to have its original color What do I have to do to fix it?
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 60, window.innerWidth/window.innerHeight, 1, 500 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.center = new THREE.Vector3();
// var geometry = new THREE.BoxGeometry( 3, 1, 1 );
// var material = new THREE.MeshBasicMaterial( { color: 'skyblue' } );
// var cube = new THREE.Mesh( geometry, material );
// scene.add( cube );
var loader = new THREE.STLLoader();
loader.load( 'js/novo/undefined.stl', function ( geometry ) {
console.log(geometry);
var mesh = new THREE.Mesh(geometry);
mesh.scale.set( 0.1, 0.1, 0.1 );
// mesh.rotation.set( - Math.PI / 2, Math.PI / 2, 0 );
// mesh.scale.set( 0.3, 0.3, 0.3 );
// mesh.receiveShadow = true;
scene.add( mesh );
});
camera.position.z = 300;
var animate = function () {
requestAnimationFrame( animate );
renderer.render(scene, camera);
};
animate();
How should be:
How are you doing:
You are not applying a material to your Mesh.
var mesh = new THREE.Mesh(geometry);
When a mesh is created, if you do not specify a material, a random colored BasicMaterial is applied which can be seen if you look at the THREE.Mesh source.
function Mesh( geometry, material ) {
Object3D.call( this );
this.type = 'Mesh';
this.geometry = geometry !== undefined ? geometry : new BufferGeometry();
this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } );
this.drawMode = TrianglesDrawMode;
this.updateMorphTargets();
}
So, to fix your problem, create some sort of material, and send it to the Mesh constructor as the second parameter.
eg.
// create a red material.
var myMaterial = new THREE.MeshBasicMaterial({color: 0xff0000})
// create mesh with red material applied
var mesh = new THREE.Mesh(geometry, myMaterial);
you can find here how to change color or texture for your loader
var loader = new THREE.STLLoader();
loader.load('./FA-FF/FA.STL', function (geometry) {
/* different texture */
var material = new THREE.MeshPhongMaterial({ map: THREE.ImageUtils.loadTexture('img/wood.jpg') });
/* for different color */
var material = new THREE.MeshPhongMaterial({ color: 0xAAAAAA, specular: 0x111111, shininess: 200 });
var mesh = new THREE.Mesh(geometry, material);
mesh.name = "first";
mesh.position.set(-1, 1, 0);
mesh.rotation.set(1.5707963267948963, -8.326672684688674, -1.570796326794894);
mesh.scale.set(0.005, 0.005, 0.005);
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add(mesh);
});
This my code:
var materialNormal = new THREE.MeshNormalMaterial();
var cubeGeometry = new THREE.CubeGeometry( 20, 500, 1000, 1, 1, 1 );
var cubeMesh = new THREE.Mesh( cubeGeometry );
cubeMesh.position.set(-50, 60, 0);
//scene.add(cubeMesh); //Meu
var cubeBSP = new ThreeBSP( cubeMesh );
var cubeGeometry = new THREE.CubeGeometry( 90, 90, 90, 1, 1, 1 );
var mat = new THREE.MeshBasicMaterial({color:0xffffff, shading: THREE.FlatShading, overdraw:0.5});
var cube3Mesh = new THREE.Mesh( cubeGeometry, mat );
cube3Mesh.position.set(-50, 60, 0);
//scene.add(cubeMesh); //Meu
var cubeOutroBSP = new ThreeBSP( cube3Mesh );
// Example #1 - Cube subtract
var newBSP = cubeBSP.subtract(cubeOutroBSP);
var newMesh = newBSP.toMesh(materialNormal);
newMesh.position.set(-180, 60, 0);
scene.add( newMesh );
How do I add texture to the object that was generated by subtraction?
The mesh returned by three.CSG is like a default three.js mesh where you can apply a material with a texture to.
In your example this would be newMesh, so do:
var texture = THREE.ImageUtils.loadTexture('yourtexture.jpg');
var material = new THREE.MeshPhongMaterial( { map: texture } );
//...
var newMesh = newBSP.toMesh( material );
newMesh.position.set(-180, 60, 0);
scene.add( newMesh );
I am trying to add a plane to the scene but if I check children's scene nothing is added.
var plane = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0xffff00, opacity: 0.25 } ) );
plane.visible = true;
this.scene.add( plane );
try this:
var geo = new THREE.PlaneBufferGeometry(2000, 2000, 8, 8);
var mat = new THREE.MeshBasicMaterial({ color: 0x000000, side: THREE.DoubleSide });
var plane = new THREE.Mesh(geo, mat);
scene.add(plane);
if you want to use the plane as a floor, you have to rotate it.
plane.rotateX( - Math.PI / 2);
I am using three.js and the scene is not rendering. I am getting following errors in console:
THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.
Uncaught SecurityError: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image at file:///F:/Study/3rd%20Sem/ES%20XXX%20-20Intro%20to%20Computer%20Graphics/Stick%20Baddy/images/crate.jpg may not be loaded.
Here are some of my code snippets:
Camera:
var scene = new THREE.Scene(); // Create a Three.js scene object
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
Light:
var light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 1, 1 ).normalize();
scene.add(light);
Adding a cube:
var geometry = new THREE.CubeGeometry(stickLenX, 20, 20);
var material = new THREE.MeshPhongMaterial( { map: THREE.ImageUtils.loadTexture('images/crate.jpg', {}, function() { renderer.render(scene); }) } );
var myStick = new THREE.Mesh(geometry, material); // Create a mesh based on the specified geometry (myStick) and material (normal).
scene.add(myStick); // at (0,0,0)
Rendering:
var render = function () {
document.addEventListener('mousemove', onDocumentMouseMove, false);
move();
renderer.render(scene, camera); // Each time we change the position of the cube object, we must re-render it.
requestAnimationFrame(render);
};
render();
It works fine with THREE.MeshNormalMaterial()
Like
var material = new THREE.MeshNormalMaterial();
In my code, there are other cubes and spheres, too. Could any of them be causing the problem? Please can anybody mention what could be the problem?
--------UPDATE:----------
Running the file with Wampserver worked. What is the reason for that and how to make it work without server?
I solved it by using ImageUtils.loadTexture and PlaneGeometry.
var geometry = new THREE.PlaneGeometry( 500, 300, 1, 1 );
geometry.vertices[0].uv = new THREE.Vector2( 0 , 0 );
geometry.vertices[1].uv = new THREE.Vector2( 2, 0 );
geometry.vertices[2].uv = new THREE.Vector2( 2, 2 );
geometry.vertices[3].uv = new THREE.Vector2( 0, 2 );
texture = THREE.ImageUtils.loadTexture("text.png",null,function(t){
});
var material = new THREE.MeshBasicMaterial ( {map: texture} );
var mesh = new THREE.Mesh ( geometry, material );
scene.add( mesh );
Maybe you can replace the material.map with:
map: THREE.ImageUtils.loadTexture('images/crate.jpg')
PRoblem: i'm trying to create (just for fun) a simple poker card (with a card back and a card front).
I have two different images, for back and front.
I easily created a Plane geometry with a single texture for both sides, but i really don't know how to assign a texture for a side and the other texture for the other side...
i tried this (without success :( ):
var textureBack = new THREE.ImageUtils.loadTexture( 'images/cardBack.png' );
var textureFront = new THREE.ImageUtils.loadTexture( 'images/cardFront.png' );
var material1 = new THREE.MeshBasicMaterial( { map: textureBack } );
var material2 = new THREE.MeshBasicMaterial( { map: textureFront } );
var geometry = new THREE.PlaneGeometry( 90, 110, 1, 1 );
geometry.faces[ 0 ].materials.push( material1 );
geometry.faces[ 1 ].materials.push( material2 );
var card = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial());
any help, please? :)
Was searching for solution without duplicating all my geometry.
Here you go ladies and gentlemen...
var materials = [new THREE.MeshBasicMaterial({map: texture, side: THREE.FrontSide}),
new THREE.MeshBasicMaterial({map: textureBack, side: THREE.BackSide})];
var geometry = new THREE.PlaneGeometry(width, height);
for (var i = 0, len = geometry.faces.length; i < len; i++) {
var face = geometry.faces[i].clone();
face.materialIndex = 1;
geometry.faces.push(face);
geometry.faceVertexUvs[0].push(geometry.faceVertexUvs[0][i].slice(0));
}
scene.add(new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials)));
BOOM a Two Faced Plane for ya, the loop will also work with geometries with more faces, replicating each face and applying the BackSide texture to it.
Enjoy!
You need to place two plane geometries back-to-back.
First, create a geometry for the front.
var geometry1 = new THREE.PlaneGeometry( 90, 110, 1, 1 );
Now create another geometry for the back.
var geometry2 = new THREE.PlaneGeometry( 90, 110, 1, 1 );
Spin it 180 degrees.
geometry2.applyMatrix( new THREE.Matrix4().makeRotationY( Math.PI ) );
After you load the materials, create the meshes, and add them as children of a "card" object.
// textures
var textureFront = new THREE.ImageUtils.loadTexture('images/cardFront.png' );
var textureBack = new THREE.ImageUtils.loadTexture('images/cardBack.png' );
// material
var material1 = new THREE.MeshBasicMaterial( { color: 0xffffff, map: textureFront } );
var material2 = new THREE.MeshBasicMaterial( { color: 0xffffff, map: textureBack } );
// card
card = new THREE.Object3D();
scene.add( card );
// mesh
mesh1 = new THREE.Mesh( geometry1, material1 );
card.add( mesh1 );
mesh2 = new THREE.Mesh( geometry2, material2 );
card.add( mesh2 );
You'll have an easier time with this if you use WebGLRenderer.
Fiddle: http://jsfiddle.net/mdAb7/11/
Updated to three.js r.69