I want to replace a plane in ThreeJS to a specific Z value.
I create a shapeBufferGeometry with shape which contains Vector3s containing the x y and z value.
here is my code and what I obtain. I want the white plane to match the position of aqua lines.
The code bellow allow me to render the scene with my plane the different points in it and the vertices around it.
I know that I can use translate to move the plane but I don't know how to properly use it. And how can I know on which axis should a translate my geometry depending on my vector values.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<canvas id="c" width="800" height="500"></canvas>
<script>
</script>
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/build/three.module.js';
import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/controls/OrbitControls.js';
import {GUI} from 'https://threejsfundamentals.org/threejs/../3rdparty/dat.gui.module.js';
import { ConvexGeometry } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/geometries/ConvexGeometry.js'
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.set(0, 20, 40);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new OrbitControls(camera, renderer.domElement);
controls.target = new THREE.Vector3(10, 0, 10);
controls.update();
var grid = new THREE.GridHelper(50, 50, 0x808080, 0x202020); // xy-grid
grid.geometry.rotateX(Math.PI * 0.5);
scene.add(grid);
var points = [ // all of them are on the xz-plane
// new THREE.Vector3(5, 0, 5),
// new THREE.Vector3(25, 0, 5),
// new THREE.Vector3(25, 0, 15),
// new THREE.Vector3(15, 0, 15),
// new THREE.Vector3(15, 0, 25),
// new THREE.Vector3(5, 0, 25),
// new THREE.Vector3(5, 0, 5)
new THREE.Vector3(199.2353333,7.6714966, 32),
new THREE.Vector3(199.0974316,276.6667291, 32),
new THREE.Vector3(75.2343077,276.6715748, 32),
new THREE.Vector3(75.2343077,232.6714966, 32),
new THREE.Vector3(101.1792999,232.6714966, 32),
new THREE.Vector3(101.1792999,194.6807462, 32),
new THREE.Vector3(75.2343077,194.6714966, 32),
new THREE.Vector3(75.2343077,7.6714966, 32),
new THREE.Vector3(199.2353333,7.6714966, 32)
]
var geom = new THREE.BufferGeometry().setFromPoints(points);
var pointsObj = new THREE.Points(geom, new THREE.PointsMaterial({
color: "red"
}));
scene.add(pointsObj);
var line = new THREE.LineLoop(geom, new THREE.LineBasicMaterial({
color: "aqua"
}));
scene.add(line);
// normals
var normal = new THREE.Vector3(0, 0, 1); // I already know the normal of xz-plane ;)
scene.add(new THREE.ArrowHelper(normal, new THREE.Vector3(10, 0, 10), 5, 0xffff00)); //yellow
var normalZ = new THREE.Vector3(0, 0, 1); // base normal of xy-plane
scene.add(new THREE.ArrowHelper(normalZ, scene.position, 5,'#FF001F' )); // aqua
// 1 quaternions
var quaternion = new THREE.Quaternion().setFromUnitVectors(normal, normalZ);
var quaternionBack = new THREE.Quaternion().setFromUnitVectors(normalZ, normal);
// 2 make it parallel to xy-plane
points.forEach(p => {
p.applyQuaternion(quaternion)
});
// 3 create shape and shapeGeometry
var shape = new THREE.Shape(points);
var shapeGeom = new THREE.ShapeBufferGeometry(shape);
shapeGeom.computeFaceNormals();
shapeGeom.computeVertexNormals();
// 4 put our points back to their origins
points.forEach(p => {
p.applyQuaternion(quaternionBack)
});
// 5 assign points to .vertices
shapeGeom.vertices = points;
var shapeMesh = new THREE.Mesh(shapeGeom, new THREE.MeshBasicMaterial({
color: '#FF001F ',
side: THREE.DoubleSide
}));
scene.add(shapeMesh);
// scene.add( new THREE.FaceNormalsHelper( shapeMesh ) );
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
</script>
</body>
</html>
the result I have:
No need to add the last point to close the contour.
And your step // 5 assign points to .vertices needs the check for CCW for points via ShapeUtils. Assigning an array of Vector3 to .vertices of a buffer geometry is useless, as that type of geometry doesn't have that property, so you're working with buffer attributes. Calling of shapeGeom.computeFaceNormals(); is also useless.
body{
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/build/three.module.js';
import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/controls/OrbitControls.js';
import {GUI} from 'https://threejsfundamentals.org/threejs/../3rdparty/dat.gui.module.js';
import { ConvexGeometry } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/geometries/ConvexGeometry.js'
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.set(0, 20, 40).setLength(500).add(new THREE.Vector3(150, 150, 0));
camera.lookAt(150, 150, 0);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new OrbitControls(camera, renderer.domElement);
controls.target = new THREE.Vector3(10, 0, 10);
controls.update();
var grid = new THREE.GridHelper(50, 50, 0x808080, 0x202020); // xy-grid
grid.geometry.rotateX(Math.PI * 0.5);
scene.add(grid);
var points = [ // all of them are on the xz-plane
// new THREE.Vector3(5, 0, 5),
// new THREE.Vector3(25, 0, 5),
// new THREE.Vector3(25, 0, 15),
// new THREE.Vector3(15, 0, 15),
// new THREE.Vector3(15, 0, 25),
// new THREE.Vector3(5, 0, 25),
// new THREE.Vector3(5, 0, 5)
new THREE.Vector3(199.2353333,7.6714966, 32),
new THREE.Vector3(199.0974316,276.6667291, 32),
new THREE.Vector3(75.2343077,276.6715748, 32),
new THREE.Vector3(75.2343077,232.6714966, 32),
new THREE.Vector3(101.1792999,232.6714966, 32),
new THREE.Vector3(101.1792999,194.6807462, 32),
new THREE.Vector3(75.2343077,194.6714966, 32),
new THREE.Vector3(75.2343077,7.6714966, 32)/*,
new THREE.Vector3(199.2353333,7.6714966, 32)*/
]
var geom = new THREE.BufferGeometry().setFromPoints(points);
var pointsObj = new THREE.Points(geom, new THREE.PointsMaterial({
color: "red"
}));
scene.add(pointsObj);
var line = new THREE.LineLoop(geom, new THREE.LineBasicMaterial({
color: "aqua"
}));
scene.add(line);
// normals
var normal = new THREE.Vector3(0, 0, 1); // I already know the normal of xz-plane ;)
scene.add(new THREE.ArrowHelper(normal, new THREE.Vector3(10, 0, 10), 5, 0xffff00)); //yellow
var normalZ = new THREE.Vector3(0, 0, 1); // base normal of xy-plane
scene.add(new THREE.ArrowHelper(normalZ, scene.position, 5,'#FF001F' )); // aqua
// 1 quaternions
var quaternion = new THREE.Quaternion().setFromUnitVectors(normal, normalZ);
var quaternionBack = new THREE.Quaternion().setFromUnitVectors(normalZ, normal);
// 2 make it parallel to xy-plane
points.forEach(p => {
p.applyQuaternion(quaternion)
});
// 3 create shape and shapeGeometry
var shape = new THREE.Shape(points);
var shapeGeom = new THREE.ShapeBufferGeometry(shape);
shapeGeom.computeFaceNormals();
shapeGeom.computeVertexNormals();
// 4 put our points back to their origins
points.forEach(p => {
p.applyQuaternion(quaternionBack)
});
// 5 assign points to .vertices
if (!THREE.ShapeUtils.isClockWise(points)) points.reverse(); // CCW order
points.forEach((p, idx) => {
shapeGeom.attributes.position.setXYZ(idx, p.x, p.y, p.z);
});
console.log(points.length, shapeGeom.attributes.position.count);
var shapeMesh = new THREE.Mesh(shapeGeom, new THREE.MeshBasicMaterial({
color: "#FF001F",
//side: THREE.DoubleSide
}));
scene.add(shapeMesh);
// scene.add( new THREE.FaceNormalsHelper( shapeMesh ) );
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
</script>
Related
Blending multiple transparent meshes causes strange behavior: only the first mesh is drawn, the inner meshes are hidden at the intersection. This only happens within a certain camera angle range.
Can is be fixed? Why does this only happen at certain angles?
Tested with r142 and r143. Browser Chrome 104.0.5112.81.
Partially expected behaviour:
Strange blending:
Expected behaviour:
canvas {
position: absolute;
top: 0;
left: 0;
}
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three#0.142.0/build/three.module.js",
"OrbitControls": "https://unpkg.com/three#0.142.0/examples/jsm/controls/OrbitControls.js"
}
}
</script>
<script type="module">
import * as THREE from "three";
import { OrbitControls } from "OrbitControls";
/* -- */
const renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111);
const ambientLight = new THREE.AmbientLight(0xffffff);
scene.add(ambientLight);
const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
camera.position.set(0, 0, 5);
const controls = new OrbitControls(camera, renderer.domElement);
/* -- */
const length = 7;
const points = [
new THREE.Vector3(0, -length / 2, 0),
new THREE.Vector3(0, length / 2, 0)
];
const curve = new THREE.CatmullRomCurve3(points);
const createMeshOnScene = (scene, geometry, material, position) => {
const mesh = new THREE.Mesh(geometry, material);
mesh.position.copy(position);
scene.add(mesh);
return mesh;
};
const transparentMaterial = (color) => {
return new THREE.MeshStandardMaterial({
color: color,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.6,
metalness: 0,
roughness: 1
});
};
const opaqueMaterial = new THREE.MeshStandardMaterial({
color: 0xffffff,
metalness: 0,
roughness: 1
});
createMeshOnScene(
scene,
new THREE.TubeGeometry(curve, 2, 0.2, 16),
opaqueMaterial,
new THREE.Vector3(0, -0.4, 0)
);
createMeshOnScene(
scene,
new THREE.ConeGeometry(2, 2, 4, 1, true, 0, Math.PI * 1.6),
transparentMaterial(0xaa0000),
new THREE.Vector3(0, 0, 0)
);
createMeshOnScene(
scene,
new THREE.ConeGeometry(2, 2, 4, 1, true, 0, Math.PI * 1.6),
transparentMaterial(0xaaaa00),
new THREE.Vector3(0, -0.3, 0)
);
createMeshOnScene(
scene,
new THREE.ConeGeometry(2, 2, 4, 1, true, 0, Math.PI * 1.6),
transparentMaterial(0x00aa00),
new THREE.Vector3(0, -0.6, 0)
);
createMeshOnScene(
scene,
new THREE.ConeGeometry(2, 2, 4, 1, true, 0, Math.PI * 1.6),
transparentMaterial(0x00aaaa),
new THREE.Vector3(0, -0.9, 0)
);
/* -- */
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
/* -- */
window.addEventListener("resize", resize);
function resize() {
let width = window.innerWidth;
let height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
}
resize();
</script>
I've created a Ring and would like to have only half of it. And after that animate it, that it builds itself up from 0 to half.
var geometry = new THREE.RingGeometry(10, 9, 32);
var material = new THREE.MeshBasicMaterial({
color: 0xffff00,
side: THREE.DoubleSide,
});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
How can I archive it? I'm new to three.js.
Use thetaStart and thetaLength to animate the half-ring.
body{
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/three#0.118.3/build/three.module.js";
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
var grid = new THREE.GridHelper(10, 10);
grid.rotation.x = Math.PI * 0.5;
scene.add(grid);
var innerRadius = 1;
var outerRadius = 2;
// re-building geometry
var usualRingGeom = new THREE.RingBufferGeometry(innerRadius, outerRadius, 32, 1, 0, 1);
var usualRingMat = new THREE.MeshBasicMaterial({color: 0xffff00});
var usualRing = new THREE.Mesh(usualRingGeom, usualRingMat);
scene.add(usualRing);
var clock = new THREE.Clock();
renderer.setAnimationLoop(()=>{
let t = clock.getElapsedTime();
// re-building geometry
usualRingGeom = new THREE.RingBufferGeometry(innerRadius, outerRadius, 32, 1, 0, (Math.sin(t) * 0.5 + 0.5) * Math.PI);
usualRing.geometry.dispose();
usualRing.geometry = usualRingGeom;
renderer.render(scene, camera);
});
</script>
PS You also can achieve the same result without re-building a geometry. For that, you can bend a plane in js (changing vertices) or in shaders :)
I would like to make IcosahedronGeometry in three.js and reflect an image on the front side of the geometry.
I already made a IcosahedronGeometry and made it rotate on it's axis.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// RENDERER
var renderer = new THREE.WebGLRenderer({
antialias: true
});
// RENDERER - SIZE OF CANVAS
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor('#ffffff');
document.body.appendChild(renderer.domElement);
// RESPONSIVE RENDERING
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
var groundMaterial = new THREE.MeshPhongMaterial({
shininess: 100,
color: 0xffffff,
specular: 0xffffff
});
const cubeCamera = new THREE.CubeCamera(75, 1000, 512);
scene.add(cubeCamera);
// GEOMETRY
var geometry = new THREE.IcosahedronGeometry(2, 1);
var material = new THREE.MeshStandardMaterial({
color: 0x98bbbd,
side: THREE.FrontSides,
roughness: 1,
metalness: 0.5,
envMap: cubeCamera.renderTarget
});
material.roughness = 0;
material.metalness = 1;
material.flatShading = true;
material.envMap = cubeCamera.renderTarget.texture;
var sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
console.log(sphere.position);
console.log(cubeCamera.position);
cubeCamera.position.copy(sphere.position);
cubeCamera.update(renderer, scene);
// FLOOR
var floorTexture = new THREE.ImageUtils.loadTexture('images/woman.png');
// floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
// floorTexture.repeat.set(1000, 1000);
var floorMaterial = new THREE.MeshBasicMaterial({
map: floorTexture,
side: THREE.BackSide
});
var floorGeometry = new THREE.PlaneGeometry(5, 5, 1, 1);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = 0;
floor.position.x = 0;
floor.position.z = 3;
scene.add(floor);
cubeCamera.lookAt(floor);
// CONTROLS
var orbit = new THREE.OrbitControls(camera, renderer.Mesh);
camera.position.z = 5;
// LIGHTS
var topLeftLight = new THREE.PointLight(0xffffff, 1, 1);
topLeftLight.position.set(-50, 50, -25);
scene.add(topLeftLight);
var topRightLight = new THREE.PointLight(0xffffff, 1, 10);
topRightLight.position.set(50, 150, -25);
scene.add(topRightLight);
var lightBottomRight = new THREE.PointLight(0xffffff, 1, 100);
lightBottomRight.position.set(40, -50, 25);
scene.add(lightBottomRight);
var lightBottomLeft = new THREE.PointLight(0xffffff, 1, 100);
lightBottomLeft.position.set(-40, -50, 25);
scene.add(lightBottomLeft);
var lightTopRight = new THREE.PointLight(0xffffff, 1, 100);
lightTopRight.position.set(40, 50, 25);
scene.add(lightTopRight);
var lightTopLeft = new THREE.PointLight(0xffffff, 1, 100);
lightTopLeft.position.set(-40, 50, 25);
scene.add(lightTopLeft);
var backLight = new THREE.PointLight(0xffffff, 1, 100);
backLight.position.set(0, 0, -25);
scene.add(backLight);
var light = new THREE.AmbientLight(0x404040, 2); // soft white light
scene.add(light);
// update function
function render() {
requestAnimationFrame(render);
sphere.rotation.x += 0.005;
sphere.rotation.y += 0.005;
sphere.visible = false;
cubeCamera.update(renderer, scene);
sphere.visible = true;
renderer.render(scene, camera);
}
render();
I would like to see a rotating IcosahedronGeometry which reflects an image on the front side. I tried adding a cube camera and pointing it at the PlaneGeometry with an image texture but nothing is reflecting.
I would like to simulate something like this, but it doesn't have to be exactly the same.
The desired result.
3 issues.
you have to call cubeCamera.update before you access cubeCamera.renderTarget.texture
The parameters to CubeCamera are new CubeCamera(near, far, size).
The code had new CubeCamera(75, 1000, 512) which means only things 75 to 1000 units away from the camera would be visible. The image plane you had is 3 units away so would not be visible.
You don't call lookAt with the CubeCamera as it's always looking in all directions.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// RENDERER
var renderer = new THREE.WebGLRenderer({
antialias: true
});
// RENDERER - SIZE OF CANVAS
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor('#ffffff');
document.body.appendChild(renderer.domElement);
// RESPONSIVE RENDERING
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
var groundMaterial = new THREE.MeshPhongMaterial({
shininess: 100,
color: 0xffffff,
specular: 0xffffff
});
const cubeCamera = new THREE.CubeCamera(0.001, 10, 512);
scene.add(cubeCamera);
// GEOMETRY
var geometry = new THREE.IcosahedronGeometry(2, 1);
var material = new THREE.MeshStandardMaterial({
color: 0x98bbbd,
side: THREE.FrontSide,
roughness: 1,
metalness: 0.5,
});
cubeCamera.update(renderer, scene);
material.roughness = 0;
material.metalness = 1;
material.flatShading = true;
material.envMap = cubeCamera.renderTarget.texture;
var sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
// FLOOR
var loader = new THREE.TextureLoader();
var floorTexture = loader.load('https://i.imgur.com/UKBsvV0.jpg');
var floorMaterial = new THREE.MeshBasicMaterial({
map: floorTexture,
side: THREE.BackSide
});
var floorGeometry = new THREE.PlaneGeometry(5, 5, 1, 1);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = 0;
floor.position.x = 0;
floor.position.z = 3;
scene.add(floor);
// CONTROLS
var orbit = new THREE.OrbitControls(camera, renderer.Mesh);
camera.position.z = 5;
// LIGHTS
var topLeftLight = new THREE.PointLight(0xffffff, 1, 1);
topLeftLight.position.set(-50, 50, -25);
scene.add(topLeftLight);
var topRightLight = new THREE.PointLight(0xffffff, 1, 10);
topRightLight.position.set(50, 150, -25);
scene.add(topRightLight);
var lightBottomRight = new THREE.PointLight(0xffffff, 1, 100);
lightBottomRight.position.set(40, -50, 25);
scene.add(lightBottomRight);
var lightBottomLeft = new THREE.PointLight(0xffffff, 1, 100);
lightBottomLeft.position.set(-40, -50, 25);
scene.add(lightBottomLeft);
var lightTopRight = new THREE.PointLight(0xffffff, 1, 100);
lightTopRight.position.set(40, 50, 25);
scene.add(lightTopRight);
var lightTopLeft = new THREE.PointLight(0xffffff, 1, 100);
lightTopLeft.position.set(-40, 50, 25);
scene.add(lightTopLeft);
var backLight = new THREE.PointLight(0xffffff, 1, 100);
backLight.position.set(0, 0, -25);
scene.add(backLight);
var light = new THREE.AmbientLight(0x404040, 2); // soft white light
scene.add(light);
// update function
function render() {
sphere.rotation.x += 0.005;
sphere.rotation.y += 0.005;
sphere.visible = false;
cubeCamera.update(renderer, scene);
sphere.visible = true;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/js/controls/OrbitControls.js"></script>
I want to have shadows, I set as follows, really wondering what's the problem? I have a grid, with cubic and sphere as a child of it, and also I set the castShadow and Receive shadow for them but it has no result for shadow.
some parts of my code:
var camera, scene, renderer, dice, dice1;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(35,window.innerWidth/window.innerHeight, 0.1, 1000);
// Z is up for objects intended to be 3D printed.
camera.up.set(0, 0, 1);
scene.add(camera);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setClearColor(0x999999);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
var light = new THREE.PointLight(0x000000, 1, 1000);
light.position.set(10, 10,10);
light.castShadow = true; // default false
scene.add(light);
//Set up shadow properties for the light;
light.shadow.mapSize.width = 1024; // default
light.shadow.mapSize.height = 1024; // default
light.shadow.camera.near = 1; // default
light.shadow.camera.far = 1000 // default
var grid = new THREE.GridHelper(50, 50, 0xffffff, 0x555555);
grid.colorGrid = 0x00ff00;
grid.rotateOnAxis(new THREE.Vector3(1, 0, 0), 90 * (Math.PI / 180));
scene.add(grid);
objects.push(grid); // add to the array for DragControls
grid.receiveShadow=true;
//Create a sphere that cast shadows (but does not receive them)
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.castShadow = true; //default is false
sphere.receiveShadow = false; //default
sphere.position.set(10, 15, 10);
scene.add(sphere);
//initializing the color cubic
var material = new THREE.MeshBasicMaterial({
color: 0xff0000});
dice = new THREE.Mesh(new THREE.BoxGeometry(5, 5, 5, 1, 1, 1), material);
dice.position.set(10, 2.5, 10);
dice.castShadow = true;
grid.add(dice);
You cannot cast shadow on a grid. it is just lines.
Add this in your code to see shadows.
var plane = new THREE.Mesh(new THREE.PlaneGeometry(50,50), new THREE.MeshStandardMaterial( {color: 0x00ff00 }));
plane.castShadow = false;
plane.receiveShadow = true;
plane.position.set(0, 0, -1);
scene.add(plane);
I am triyng to learn three.js I want to dra a basic triangle however my codes do not work.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 70, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.z = 10;
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.Geometry();
geometry.vertices= [new THREE.Vector3(2,1,0), new THREE.Vector3(1,3,0), new THREE.Vector3(3,4,0)];
geometry.faces = [new THREE.Face3(0,1,2)];
var mesh= new THREE.Mesh( geometry, new THREE.MeshBasicMaterial({ color: 0xffff00 }) );
scene.add(mesh);
renderer.render(scene, camera);
Where i am doing it wrong?
With Faces
var geom = new THREE.Geometry();
var v1 = new THREE.Vector3(0, 0, 0);
var v2 = new THREE.Vector3(30, 0, 0);
var v3 = new THREE.Vector3(30, 30, 0);
var triangle = new THREE.Triangle(v1, v2, v3);
var normal = triangle.normal();
geom.vertices.push(triangle.a);
geom.vertices.push(triangle.b);
geom.vertices.push(triangle.c);
geom.faces.push(new THREE.Face3(0, 1, 2, normal));
var mesh = new THREE.Mesh(geom, new THREE.MeshNormalMaterial());
scene.add(mesh);
Just Outline
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(-30, 2, 2));
geometry.vertices.push(new THREE.Vector3(2, 30, 2));
geometry.vertices.push(new THREE.Vector3(30, 2, 2));
geometry.vertices.push(new THREE.Vector3(-30, 2, 2));
var line = new THREE.Line(
geometry,
new THREE.LineBasicMaterial({ color: 0x00ff00 })
);
scene.add(line);
It's funny how hard was to find an updated answer, since Geometry was deprecated in recent versions of Three.js the way I found to draw a plane triangle is with Shape primitive.
const shape = new THREE.Shape();
const x = 0;
const y = 0;
shape.moveTo(x - 2, y - 2);
shape.lineTo(x + 2, y - 2);
shape.lineTo(x, y + 2);
const TriangleGeometry = new THREE.ShapeGeometry(shape);
based on https://threejs.org/docs/index.html?q=ShapeGeometry#api/en/geometries/ShapeGeometry
You have to be careful with the order in which you add the vertices to the face. If the order follows a clockwise order, the normal vector of the surface will point down. And since your camera looks from above, you won't see the triangle. If the order is counterclockwise, the normal will point towards your camera.
It will work if you change:
geometry.faces = [new THREE.Face3(0,1,2)];
To:
geometry.faces = [new THREE.Face3(1,0,2)];
You can also use the argument side, which applies it to both sides of the face.new THREE.MeshBasicMaterial({ color: 0xffff00, side: THREE.DoubleSide };