Hi I have this code that draws the image below
window.onload = function()
{
// init renderer
var renderer=new THREE.WebGLRenderer();
canvas_width=side; canvas_height=side;
renderer.setSize(canvas_width,canvas_height);
document.body.appendChild(renderer.domElement);
// init scene and camera
var scene=new THREE.Scene();
var camera=new THREE.PerspectiveCamera(90,canvas_width/canvas_height,1,100);
camera.position.y=5;
camera.position.z=25;
var texture = new THREE.TextureLoader().load( 'arrow.png' );
var img = new THREE.MeshBasicMaterial( { map: texture } );
// mesh
mesh = new THREE.Mesh(new THREE.PlaneGeometry(25,25),img);
mesh.overdraw = true;
scene.add(mesh);
// a light
var light=new THREE.HemisphereLight(0xffffff,0x000000,1.5);
light.position.set(1,1,1);
scene.add(light);
// render
requestAnimationFrame(function animate(){
requestAnimationFrame(animate);
renderer.render(scene,camera);
})
}
but I want to draw the PlaneGeometry horizontally instead of vertically, not rotating it with mesh.rotation.x=THREE.Math.degToRad(-90);, to get this at x=0 y=0 z=0:
so that with
mesh.rotation.x=THREE.Math.degToRad(-90);
the arrow will pointing down
and with:
mesh.rotation.x=THREE.Math.degToRad(90);
the arrow will pointing up
can you help me?
You can do it, rotating the geometry with .rotateX():
// init renderer
var renderer = new THREE.WebGLRenderer();
canvas_width = window.innerWidth;
canvas_height = window.innerHeight;
renderer.setSize(canvas_width, canvas_height);
document.body.appendChild(renderer.domElement);
// init scene and camera
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(90, canvas_width / canvas_height, 1, 100);
camera.position.y = 5;
camera.position.z = 25;
var texture = new THREE.TextureLoader().load('https://threejs.org/examples/textures/uv_grid_opengl.jpg');
var img = new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide
});
// mesh
geom = new THREE.PlaneGeometry(25, 25);
geom.rotateX(-Math.PI * 0.5); // this is how you can do it
mesh = new THREE.Mesh(geom, img);
mesh.overdraw = true;
scene.add(mesh);
// a light
var light = new THREE.HemisphereLight(0xffffff, 0x000000, 1.5);
light.position.set(1, 1, 1);
scene.add(light);
// render
requestAnimationFrame(function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
})
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
Related
I am trying to display a sprite in three on javascript and make it bigger. I tried the following:
THREE.ImageUtils.crossOrigin = '';
var spriteMap = THREE.ImageUtils.loadTexture( "https://cdn.iconscout.com/icon/premium/png-256-thumb/airplane-1993284-1683707.png" );
var spriteMaterial = new THREE.SpriteMaterial( { map: spriteMap } );
var sprite = new THREE.Sprite( spriteMaterial );
sprite.width = 10;
sprite.height = 10;
scene.add( sprite );
and
THREE.ImageUtils.crossOrigin = '';
var spriteMap = THREE.ImageUtils.loadTexture( "https://cdn.iconscout.com/icon/premium/png-256-thumb/airplane-1993284-1683707.png" );
var spriteMaterial = new THREE.SpriteMaterial( { map: spriteMap } );
var sprite = new THREE.Sprite( spriteMaterial );
sprite.size = THREE.Vector3(10,10,10);
scene.add( sprite );
but the sprite was very very tiny in the middle of the browser window. I saw no error on the console.
What am I doing wrong?
Sprite.size does not exist. Try to modify Sprite.scale instead. Check out the following live example:
var camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 5;
scene = new THREE.Scene();
var loader = new THREE.TextureLoader();
var map = loader.load("https://cdn.iconscout.com/icon/premium/png-256-thumb/airplane-1993284-1683707.png");
var material = new THREE.SpriteMaterial({
map: map
});
var sprite = new THREE.Sprite(material);
sprite.scale.set( 5, 5, 1 );
scene.add(sprite);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.119.1/build/three.js"></script>
If you want the scaling to happen based on the camera distance, you need to add a parameter to your material variable:
sizeAttenuation: false
Like this:
var material = new THREE.SpriteMaterial({
map: map,
sizeAttenuation: false});
This will make your sprite big when to camera is far away and smaller when the camera gets closer to it (based on the sprite.scale.set() values).
I am working in a three.js project. In the project I have to show all edges of geometries even those edges are intersecting with other objects' surfaces.
Here is the snippet code that illustrates my problem.
var camera, scene, renderer, material, stats, group, wireframeMaterial;
init();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer({antialias: true, alpha:true,clearAlpha:0,clearColor: 0xff0000});
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
// Create scene.
scene = new THREE.Scene();
group=new THREE.Group()
// Create material
material = new THREE.MeshBasicMaterial();
wireframeMaterial=new THREE.LineBasicMaterial( { color: 0x000000, side:THREE.FrontSide ,transparent:false,opacity:1,linewidth: 1 })
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(200, 200, 200);
var mesh1 = new THREE.Mesh(geometry, material);
group.add(mesh1);
var geometry2 = new THREE.BoxGeometry(100,100,100);
var mesh2 = new THREE.Mesh(geometry2, material);
group.add(mesh2);
mesh2.position.fromArray([0,150,0])
var edges = new THREE.EdgesGeometry( geometry );
var line = new THREE.LineSegments( edges, wireframeMaterial );
mesh1.add( line );
var edges2 = new THREE.EdgesGeometry( geometry2 );
var line2 = new THREE.LineSegments( edges2, wireframeMaterial );
mesh2.add( line2 );
scene.add(group)
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
}
function animate() {
requestAnimationFrame(animate);
group.rotation.x += 0.005;
group.rotation.y += 0.01;
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
padding: 0;
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
In fiddle code you can see there are two cubes top of each other. I want bottom edges of small cube to become visible. One solution is making mesh basic material transparent. However in that situation edges that are behind cubes it self will be visible too which is not allowed in the project.
So are there any alternative solution for this issue?
Found a good solution, you need to use the polygonOffset parameters of the basic material.
var material = new THREE.MeshBasicMaterial({
polygonOffset: true,
polygonOffsetFactor: 1, // positive value pushes polygon further away
polygonOffsetUnits: 1
});
Found it on this question: three.js EdgesHelper showing certain diagonal lines on Collada model
EdgesGeometry will render the hard edges only.
WireframeGeometry will render all edges.
var camera, scene, renderer, material, stats, group, wireframeMaterial;
init();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer({antialias: true, alpha:true,clearAlpha:0,clearColor: 0xff0000});
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
// Create scene.
scene = new THREE.Scene();
group=new THREE.Group()
// Create materials
var material = new THREE.MeshBasicMaterial({
polygonOffset: true,
polygonOffsetFactor: 1, // positive value pushes polygon further away
polygonOffsetUnits: 1
});
var wireframeMaterial= new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 2 } );
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(200, 200, 200);
var edges = new THREE.EdgesGeometry(geometry);
var line = new THREE.LineSegments( edges, wireframeMaterial );
var mesh = new THREE.Mesh(geometry, material);
group.add(mesh, line);
var geometry2 = new THREE.BoxGeometry(100,100,100);
var wire = new THREE.EdgesGeometry(geometry2);
var line2 = new THREE.LineSegments( wire, wireframeMaterial );
var mesh2 = new THREE.Mesh(geometry2, material);
line2.position.fromArray([0,150,0]);
mesh2.position.fromArray([0,150,0]);
group.add(mesh2, line2);
scene.add(group)
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
// Add stats to page.
stats = new Stats();
document.body.appendChild( stats.dom );
}
function animate() {
requestAnimationFrame(animate);
group.rotation.x += 0.005;
group.rotation.y += 0.01;
renderer.render(scene, camera);
stats.update();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
<script type="text/javascript" src="https://rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/mrdoob/stats.js/r17/build/stats.min.js"></script>
I have a problem with javascript .
it shows me the error that I wrote in the title to the line:
this.color = cubeMaterial.color.getHex();
I can not understand where I'm wrong. I am beginner.
I tried to declare the variable "var cubeMaterial;" outside function "createCube" but it gives the error " Can not read property ' color' of undefined " Thanks!
var scene,camera,renderer;
function createScene() {
// create a scene, that will hold all our elements such as objects,cameras and lights.
scene = new THREE.Scene();
//screate a camera, which defines where we're looking at
camera = new THREE.PerspectiveCamera(45, window.innerWidth/ window.innerHeight, 0.1, 1000);
camera.updateProjectionMatrix();
//position and point the camera to the center of the scene
camera.position.x=-30;
camera.position.y=40;
camera.position.z=30;
camera.lookAt(scene.position);
// create a render and set the size
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setClearColor(new THREE.Color(0xEEEEcE));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
//add the output of the renderer to the html element
document.body.appendChild( renderer.domElement );
}
var ambientLight,spotLight;
function createLights(){
ambientLight = new THREE.AmbientLight(0x0c0c0c);
//add spotlight for the shadow
spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40,60,-10);
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
scene.add(ambientLight);
scene.add(spotLight);
}
var cube,sphere,plane;
function createPlane(){
// create a plane
var planeGeometry = new THREE.PlaneGeometry(60,40,11);
var planeMaterial = new THREE.MeshLambertMaterial({color:0Xcccccc });
plane= new THREE.Mesh(planeGeometry,planeMaterial);
//rotate and position the plane
plane.rotation.x= -0.5*Math.PI;
plane.position.x= 15;
plane.position.y= 0;
plane.position.z=0;
plane.receiveShadow = true;
//add the plane to the scene
scene.add(plane);
}
function createCube(){
//create a cube
var cubeGeometry = new THREE.CubeGeometry( 5, 5, 5 );
var cubeMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff00, transparent:true} );
cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
//position the cube
cube.position.x = -4;
cube.position.y = 3;
cube.position.z =0;
cube.castShadow= true;
//add cube to the scene
cube.name = "cube"
scene.add(cube);
}
function createSphere(){
//create a sphere
var sphereGeometry= new THREE.SphereGeometry(4,20,20);
var sphereMaterial= new THREE.MeshLambertMaterial({color: 0x7777ff});
sphere= new THREE.Mesh(sphereGeometry,sphereMaterial);
//position the sphere
sphere.position.x=20;
sphere.position.y=0;
sphere.position.z=2;
sphere.castShadow = true;
//add the sphere ti the scene
scene.add(sphere);
}
var controls = new function() {
this.rotationSpeed = 0.02;
this.bouncingSpeed = 0.03;
this.opacity= 0.6;
this.color = cubeMaterial.color.getHex();
}
function addControlGui(controlObject){
var gui = new dat.GUI();
gui.add(controlObject, 'rotationSpeed',0,0.5);
gui.add(controlObject, 'bouncingSpeed',0,0.5);
gui.add(controlObject,"opacity", 0.1, 1 );
gui.add(controlObject,"color");
}
var step = 0;
function render(){
//rotate the cube aroun its axes
cube.rotation.x += controls.rotationSpeed;
cube.rotation.y += controls.rotationSpeed;
cube.rotation.z += controls.rotationSpeed;
scene.getObjectByName("cube").material.opacity= controls.opacity;
scene.getObjectByName("cube").material.color = new THREE.Color(controls.color);
//bounce the sphere up and down
step+=controls.bouncingSpeed;
sphere.position.x= 20+(10*(Math.cos(step+=0.01)));
sphere.position.y = 2 +( 10*Math.abs(Math.sin(step+=0.03)));
requestAnimationFrame(render);
renderer.render(scene,camera);
//render using requestAnimationFrame
}
function init(){
createScene();
createLights();
createPlane();
createCube();
createSphere();
addControlGui(controls);
render();
}
window.addEventListener('load', init, false);
This is a scope problem! When you declare cubeMaterial inside the createSphere function, it will only exist inside that function.
Variables declared at the top of the code, outside of the functions, such as on the line var scene,camera,renderer; will exist in all the inner functions.
Does that make sense? So all you have to do is make sure you declare the cubeMaterial in the right scope. Try putting it at the top next to the scene declaration.
I need to add an additional function to change the Z rotation value of the teapot from within the updateTeapot function. I saw this answer Three.js camera tilt up or down and keep horizon level, but how do I incorporate a z rotation function within this function?
function updateTeapot() {
if (teapot != null) {
teaPotHeight+=1;
teapot.position.y = teaPotHeight%200;
}
}
(function ( lab3 , $, undefined) {
lab3.init = function(hook) {
// Create a renderer
var WIDTH = 600,
HEIGHT = 500;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(WIDTH, HEIGHT);
hook.append(renderer.domElement);
var scene = new THREE.Scene();
// Create lights
var pointLight =
new THREE.PointLight(0xFFFFFF);
pointLight.position = new THREE.Vector3(-10, 100, 100);
scene.add(pointLight);
// Add ambient light
var ambient = new THREE.AmbientLight( 0x555555 );
scene.add( ambient );
// Create a camera
var VIEW_ANGLE = 65, //65 FOV is most 'natural' FOV
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1, //these elements are needed for cameras to
FAR = 10000; //partition space correctly
var camera = new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR);
camera.position.z = 300;
scene.add(camera);
// Create and add controls
var controls = new THREE.TrackballControls( camera );
controls.target.set( 0, 0, 0 );
// Create a cube
var material =
new THREE.MeshLambertMaterial(
{
color: 0x00bbcc
});
var cube = new THREE.Mesh(
new THREE.CubeGeometry(
40, 55, 30),
material);
scene.add(cube);
// Animation
function renderLoop() {
renderer.render(scene, camera);
controls.update();
window.requestAnimationFrame(renderLoop);
updateTeapot();
}
window.requestAnimationFrame(renderLoop);
////////////////////////////////////////////////
var teapot = null;
var teaPotHeight=0;
loader = new THREE.JSONLoader();
loader.load( "models/utah-teapot.json", function( geometry ) {
teapot = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial({
color: 0x00bb00,
side: THREE.DoubleSide
}));
teapot.scale.set( 20, 20, 20 );
teapot.position = new THREE.Vector3(-30, 100, 20);
function updateTeapot() {
if (teapot != null) {
teaPotHeight+=1;
teapot.position.y = teaPotHeight%200;
}
}
//add it to the scene
scene.add(teapot);
});
}
})(window.lab3 = window.lab3 || {} , jQuery)
Add
teapot.rotation.z = numInRadians;
I'm having trouble creating a particle using an image as a map on a texture. Below is my code:
var camera, scene, renderer, material, img, texture;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 8000;
scene.add(camera);
img = new Image();
texture = new THREE.Texture(img);
img.onload = function() {
texture.needsUpdate = true;
makeParticle();
};
img.src = "http://www.aerotwist.com/tutorials/creating-particles-with-three-js/images/particle.png";
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function makeParticle() {
material = new THREE.ParticleBasicMaterial({
color: 0xE60000,
size: 20,
map: texture,
blending: THREE.AdditiveBlending,
transparent: true
});
// make the particle
particle = new THREE.Particle(material);
particle.scale.x = particle.scale.y = 1;
scene.add(particle);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
A fiddle with this code is here: jsfiddle
I am aware I can use the Three Image Helper as follows:
map: THREE.ImageUtils.loadTexture(
"FILE PATH"
),
But I am implementing my own asset loader and so do not wish to use it on an individual basis. Currently my code above shows no errors but no particle is displayed.
The particle is being displayed, but the camera is very far of it.
Change this line:
camera.position.z = 8000;
To something like this:
camera.position.z = 50;