I'm trying to create a right triangular prism.
Here is my code so far :
var triangleGeometry = new THREE.Geometry();
triangleGeometry.vertices.push(new THREE.Vector3(-1.0, 1.5, 0.95));
triangleGeometry.vertices.push(new THREE.Vector3(-1.0, -1.5, 0.95));
triangleGeometry.vertices.push(new THREE.Vector3( 1.0, -1.5, 0.95));
triangleGeometry.vertices.push(new THREE.Vector3(-1.0, 1.5, 1.2));
triangleGeometry.vertices.push(new THREE.Vector3(-1.0, -1.5, 1.2));
triangleGeometry.vertices.push(new THREE.Vector3( 1.0, -1.5, 1.2));
triangleGeometry.faces.push(new THREE.Face3(0, 1, 2));
triangleGeometry.faces.push(new THREE.Face3(3, 4, 5));
// Points 1,4,3 and 6 form a rectangle which I'm trying to construct using triangles 0,2,5 and 0,3,5
triangleGeometry.faces.push(new THREE.Face3(0, 2, 5));
triangleGeometry.faces.push(new THREE.Face3(0, 3, 5));
var triangleMaterial = new THREE.MeshBasicMaterial({
color:0xFFFFFF,
side:THREE.DoubleSide
});
var triangleMesh = new THREE.Mesh(triangleGeometry, triangleMaterial);
triangleMesh.position.set(1, 0.0, 0.0);
scene.add(triangleMesh);
I'm able to get what I want, but I want to know if there is any other good solution to get a right triangular prism.
Create class
PrismGeometry = function ( vertices, height ) {
var Shape = new THREE.Shape();
( function f( ctx ) {
ctx.moveTo( vertices[0].x, vertices[0].y );
for (var i=1; i < vertices.length; i++) {
ctx.lineTo( vertices[i].x, vertices[i].y );
}
ctx.lineTo( vertices[0].x, vertices[0].y );
} )( Shape );
var settings = { };
settings.amount = height;
settings.bevelEnabled = false;
THREE.ExtrudeGeometry.call( this, Shape, settings );
};
PrismGeometry.prototype = Object.create( THREE.ExtrudeGeometry.prototype );
example use
var A = new THREE.Vector2( 0, 0 );
var B = new THREE.Vector2( 30, 10 );
var C = new THREE.Vector2( 20, 50 );
var height = 12;
var geometry = new PrismGeometry( [ A, B, C ], height );
var material = new THREE.MeshPhongMaterial( { color: 0x00b2fc, specular: 0x00ffff, shininess: 20 } );
var prism1 = new THREE.Mesh( geometry, material );
prism1.rotation.x = -Math.PI / 2;
scene.add( prism1 );
Example here
I like #Almaz Vildanov's solution. Works great. Since I use typescript, I ported the class definition to .ts:
import {ExtrudeGeometry, Shape, Vector2} from "three";
class PrismGeometry extends ExtrudeGeometry {
constructor(vertices: Vector2[], height) {
super(new Shape(vertices), {depth: height, bevelEnabled: false});
}
}
example use (as in #Almaz Vildanov's original, but could leave out THREE because of imports):
var A = new Vector2( 0, 0 );
var B = new Vector2( 30, 10 );
var C = new Vector2( 20, 50 );
var height = 12;
var geometry = new PrismGeometry( [ A, B, C ], height );
var material = new MeshPhongMaterial( { color: 0x00b2fc, specular: 0x00ffff, shininess: 20 } );
var prism1 = new Mesh( geometry, material );
prism1.rotation.x = -Math.PI / 2;
scene.add( prism1 );
Related
i use TreeJs to modelise a form and i want to move 2 parameter in the same slider i want to know if its possible :
like moving x position of two differents vertices at the same time and not only one.
I already use datGui to move one vertice but i want to move more than one with the same slider.
<script src="js/three.js"></script>
<script>
//camera
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set( 0, -2, 10);
camera.lookAt( 0, -2, 0 );
//rendu
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight);
document.body.appendChild( renderer.domElement );
//coté gauche---------------------------------------------
var material = new THREE.LineBasicMaterial( { color: 0xffffff } );
//trait A1 (haut vertical)
var a1 = new THREE.Geometry();
a1.vertices = [new THREE.Vector3(-2, 0, 0),
new THREE.Vector3(-2, 2, 0) ];
var A1 = new THREE.Line( a1, material );
//trait A2 (haut horizontal)
var a2 = new THREE.Geometry();
a2.vertices = [new THREE.Vector3( -2, 0, 0),
new THREE.Vector3(-4, 0, 0) ];
var A2 = new THREE.Line( a2, material );
//trait A3 (centre vertical)
var a3 = new THREE.Geometry();
a3.vertices.push(new THREE.Vector3( -4, 0, 0) );
a3.vertices.push(new THREE.Vector3(-4, -2, 0) );
var A3 = new THREE.Line( a3, material );
//trait A4 (bas horizontal)
var a4 = new THREE.Geometry();
a4.vertices.push(new THREE.Vector3( -4, -2, 0) );
a4.vertices.push(new THREE.Vector3(-2, -2, 0) );
var A4 = new THREE.Line( a4, material );
//trait A5 (bas horizontal)
var a5 = new THREE.Geometry();
a5.vertices.push(new THREE.Vector3( -2, -2, 0) );
a5.vertices.push(new THREE.Vector3(-2, -4, 0) );
var A5 = new THREE.Line( a5, material );
//render-------------------------------------------------
scene.add(A1,A2,A3,A4,A5);
var render = function () {
requestAnimationFrame( render );
camera.updateProjectionMatrix();
//maj refresh
A3.geometry.verticesNeedUpdate = true;
renderer.render(scene, camera);
};
render();
// dat gui----------------------------------------------
var gui = new dat.GUI();
var cameraGui = gui.addFolder("camera position");
cameraGui.add(camera.position, 'x').min(-20).max(20).step(0.25);
cameraGui.add(camera.position, 'y').min(-20).max(20).step(0.25);
cameraGui.add(camera.position, 'z').min(-20).max(20).step(0.25);
cameraGui.open();
var A3Gui = gui.addFolder("position a3");
A3Gui.add(A3.position,'x');
A3Gui.open();
</script>
Just use the built-in .onChange() function explained in their docs: https://workshop.chromeexperiments.com/examples/gui/#7--Events
var A3Gui = gui.addFolder("position a3");
var posSlider = A3Gui.add(A3.position,'x');
posSlider.onChange(function(value){
// Change all the things you want
// with 'value' as the new result
});
i create walls by creating faces with some points i have.
The creation of the walls does work without an issue.
Now i want to add some thickness to my walls but iam not quite sure how to.
here is my code for creating my walls:
makeWall(start, end) {
let v1 = this.helpers.toVec3(start); //0
let v2 = this.helpers.toVec3(end); //1
let v3 = v2.clone(); //2
v3.y = this.wallHeight;
let v4 = v1.clone(); //3
v4.y = this.wallHeight;
let points = [ v1.clone(), v2.clone(), v3.clone(), v4.clone() ];
console.log("Points", points )
let mesh:THREE.Mesh;
let geometry = new THREE.Geometry();
let label: THREE.Sprite;
let walldirection;
geometry.vertices = [v1, v2, v3, v4];
geometry.faces.push(new THREE.Face3(0, 1, 2));
geometry.faces.push(new THREE.Face3(0, 2, 3));
geometry = this.helpers.assignUVs(geometry);
mesh = new THREE.Mesh(geometry, this.wallMaterial);
...
}
at the end the walls form a closed Room together.
For Example the points are:
(4) [p, p, p, p]
0: p {x: 200, y: 0, z: -500}
1: p {x: 200, y: 0, z: 300}
2: p {x: 200, y: 277, z: 300}
3: p {x: 200, y: 277, z: -500}
length: 4
thanks for looking into it
Update//
i think iam on the right track now.
i added 4 more points with a offset and created faces for them but there is still something wrong. Probably the Faces are wrong ?
let v1ex = v1.clone(); // 4
v1ex.x = v1ex.x - 10;
let v2ex = v2.clone(); // 5
v2ex.x = v1ex.x + 10;
let v3ex = v3.clone(); // 6
v3ex.x = v3ex.x + 10;
let v4ex = v4.clone(); // 7
v4ex.x = v4ex.x - 10;
let points = [ v1.clone(), v2.clone(), v3.clone(), v4.clone() , v1ex , v2ex , v3ex , v4ex ];
let mesh:THREE.Mesh;
let geometry = new THREE.Geometry( );
let label: THREE.Sprite;
let walldirection;
geometry.vertices = [v1, v2, v3, v4 , v1ex , v2ex , v3ex , v4ex];
geometry.faces.push(new THREE.Face3( 0 , 1 , 2 ) );
geometry.faces.push(new THREE.Face3( 0 , 2 , 3 ) );
geometry.faces.push(new THREE.Face3( 4 , 5 , 6 ) );
geometry.faces.push(new THREE.Face3( 4 , 6 , 7 ) );
geometry.faces.push(new THREE.Face3( 7 , 3 , 6 ) );
geometry.faces.push(new THREE.Face3( 7 , 3 , 2 ) );
geometry.faces.push(new THREE.Face3( 0 , 5 , 1 ) );
geometry.faces.push(new THREE.Face3( 0 , 5 , 4 ) );
Just a concept of how you can do it, using a mesh with thin THREE.BoxGeometry():
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(2, 3, 5).setLength(10);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(10, 10));
var pointStart = new THREE.Vector3(-1, 0, 3);
var pointEnd = new THREE.Vector3(-1, 0, -3);
var height = 4;
var thickness = 0.1;
var boxW = pointEnd.clone().sub(pointStart).length();
var boxH = height;
var boxD = thickness;
var boxGeometry = new THREE.BoxGeometry(boxW, boxH, boxD);
boxGeometry.translate(boxW * 0.5, boxH * 0.5, 0);
boxGeometry.rotateY(-Math.PI * 0.5);
var wall = new THREE.Mesh(boxGeometry, new THREE.MeshBasicMaterial({
color: "red",
wireframe: true
}));
wall.position.copy(pointStart);
wall.lookAt(pointEnd);
scene.add(wall);
addPoint(pointStart, "green");
addPoint(pointEnd, "yellow");
function addPoint(position, color) {
let p = new THREE.Mesh(new THREE.SphereGeometry(0.125, 4, 2), new THREE.MeshBasicMaterial({
color: color
}));
p.position.copy(position);
scene.add(p);
}
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
How can a triangle, made with three.js, be rotated around one of its edges? When I try to rotate it, it does around its center as it seems.
The triangle is made by:
var triangleMesh;
var triangleGeometry = new THREE.Geometry();
triangleGeometry.vertices.push( new THREE.Vector3( 0.0, 1.0, 0.0 ) );
triangleGeometry.vertices.push( new THREE.Vector3( -1.0, -1.0, 0.0 ) );
triangleGeometry.vertices.push( new THREE.Vector3( 1.0, -1.0, 0.0 ) );
triangleGeometry.faces.push( new THREE.Face3( 0, 1, 2 ) );
triangleGeometry.faces[0].vertexColors[0] = new THREE.Color(0xFF0000);
triangleGeometry.faces[0].vertexColors[1] = new THREE.Color(0x00FF00);
triangleGeometry.faces[0].vertexColors[2] = new THREE.Color(0x0000FF);
var triangleMaterial = new THREE.MeshBasicMaterial({ vertexColors:THREE.VertexColors, side:THREE.DoubleSide });
triangleMesh = new THREE.Mesh( triangleGeometry, triangleMaterial );
triangleMesh.position.set(-1.5, 0.0, 4.0 );
triangleMesh.position.z -= 5;
triangleMesh.rotation.z += angle * Math.PI / 180; // angle is from outer for loop
parent.add( triangleMesh );
I would need to rotate it around one edge to build prisms/hexagons.
To rotate a triangle around one of its corners, that corner must be in the center of coordinates. For this purpose you can use .translate ( x, y, z ) method of THREE.Geometry().
Take a look at the code snippet.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 5);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var ngon = 11;
var radius = 2;
var angle = Math.PI / ngon;
var triHeight = Math.cos(angle) * radius;
var triWidth = Math.sin(angle) * radius;
var triangleMesh;
var triangleGeometry = new THREE.Geometry();
triangleGeometry.vertices.push(new THREE.Vector3(0.0, triHeight, 0.0));
triangleGeometry.vertices.push(new THREE.Vector3(-triWidth, 0, 0.0));
triangleGeometry.vertices.push(new THREE.Vector3(triWidth, 0, 0.0));
triangleGeometry.faces.push(new THREE.Face3(0, 1, 2));
triangleGeometry.faces[0].vertexColors[0] = new THREE.Color(0xFF0000);
triangleGeometry.faces[0].vertexColors[1] = new THREE.Color(0x00FF00);
triangleGeometry.faces[0].vertexColors[2] = new THREE.Color(0x0000FF);
triangleGeometry.translate(0, -triHeight, 0); // the upper vertex is at the center now
var triangleMaterial = new THREE.MeshBasicMaterial({
vertexColors: THREE.VertexColors,
side: THREE.DoubleSide
});
triangleMesh = new THREE.Mesh(triangleGeometry, triangleMaterial);
for (var i = 1; i < ngon; i++) {
var newTri = triangleMesh.clone();
newTri.rotation.z = i * angle * 2;
scene.add(newTri);
}
scene.add(triangleMesh);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
I added texture to my triangle geometry. But all was one plain colour base on the lightest value. Then I learn that I should assign UVs. But same problem but with darkest colour of my texture (see picture).
Here the code:
var material = new THREE.MeshBasicMaterial( { map: new THREE.TextureLoader().load(texture), overdraw: true } );
var geometry = new THREE.Geometry();
// 1re marche de 3 (30 degrées)
geometry.vertices.push(new THREE.Vector3(0.0, 0.0, 0.0));
geometry.vertices.push(new THREE.Vector3(longueurTotalFacteur, largeur, 0.0));
geometry.vertices.push(new THREE.Vector3(0.0, largeur, 0.0));
geometry.vertices.push(new THREE.Vector3(0.0, 0.0, -epaisseur));
geometry.vertices.push(new THREE.Vector3(longueurTotalFacteur, largeur, -epaisseur));
geometry.vertices.push(new THREE.Vector3(0.0, largeur, -epaisseur));
geometry.faces.push(new THREE.Face3(0, 1, 2)); // Dessus
geometry.faces.push(new THREE.Face3(5, 4, 3)); // Dessous
geometry.faces.push(new THREE.Face3(3, 1, 0)); // Côté long
geometry.faces.push(new THREE.Face3(4, 1, 3)); // Côté long
geometry.faces.push(new THREE.Face3(4, 2, 1)); // Côté court
geometry.faces.push(new THREE.Face3(5, 2, 4)); // Côté court
geometry.faces.push(new THREE.Face3(5, 0, 2)); // Côté moyen
geometry.faces.push(new THREE.Face3(3, 0, 5)); // Côté moyen
assignUVs(geometry);
... (snipped)...
function assignUVs(geometry) {
geometry.faceVertexUvs[0] = [];
geometry.faces.forEach(function(face) {
var components = ['x', 'y', 'z'].sort(function(a, b) {
return Math.abs(face.normal[a]) > Math.abs(face.normal[b]);
});
var v1 = geometry.vertices[face.a];
var v2 = geometry.vertices[face.b];
var v3 = geometry.vertices[face.c];
geometry.faceVertexUvs[0].push([
new THREE.Vector2(v1[components[0]], v1[components[1]]),
new THREE.Vector2(v2[components[0]], v2[components[1]]),
new THREE.Vector2(v3[components[0]], v3[components[1]])
]);
});
geometry.uvsNeedUpdate = true;
}
Here what I get:
You cannot do like this:
var material = new THREE.MeshBasicMaterial( { map: new THREE.TextureLoader().load(texture), overdraw: true } );
Texture loading is an asynchronous process. You need to apply the texture in the onLoad callback. Please refer to the documents for THREE.TextureLoader here.
For your example:
var material = new THREE.MeshBasicMaterial( { overdraw: true } );
var url = //your texture path...
var onLoad = function(texture){
material.map = texture;
material.needsUpdate = true;
}
var loader = new THREE.TextureLoader();
loader.load(url, onLoad);
UPDATE
When you calculate your UV's you need to do something with offset and range. Check the computeUVs from this example fiddle; you might need to change it a bit for your stairs geometry...
function computeUVs(geometry) {
geometry.computeBoundingBox();
var max = geometry.boundingBox.max,
min = geometry.boundingBox.min;
var offset = new THREE.Vector2(0 - min.x, 0 - min.y);
var range = new THREE.Vector2(max.x - min.x, max.y - min.y);
var faces = geometry.faces;
var vertices = geometry.vertices;
geometry.faceVertexUvs[0] = [];
for (var i = 0, il = faces.length; i < il; i++) {
var v1 = vertices[faces[i].a],
v2 = vertices[faces[i].b],
v3 = vertices[faces[i].c];
geometry.faceVertexUvs[0].push([
new THREE.Vector2((v1.x + offset.x) / range.x, (v1.y + offset.y) / range.y),
new THREE.Vector2((v2.x + offset.x) / range.x, (v2.y + offset.y) / range.y),
new THREE.Vector2((v3.x + offset.x) / range.x, (v3.y + offset.y) / range.y)
]);
}
geometry.uvsNeedUpdate = true;
}
This code is based on this stackoverflow answer.
How to show a cube map reflection on a object without showing the cubemap in the background?
I like to receive a reflection on a lever mechanism without showing a cubemap in the background. The background should be with a gradient from blue to white.
So basicially, the cubemap should be only visible on the object.
Thank you very much in advance!
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container;
var loader;
var camera, cameraTarget, controls, scene, renderer;
init();
animate();
function init() {
var previewDiv = document.getElementById("preview");
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 15 );
camera.position.set( 3, 0.15, 3 );
cameraTarget = new THREE.Vector3( 0, -0.25, 0 );
controls = new THREE.OrbitControls( camera );
controls.maxPolarAngle = Math.PI / 2.2;
controls.minDistance = 3;
controls.maxDistance = 8;
// controls.noPan = true;
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xdae1e6, 2, 15 );
// Ground
var plane = new THREE.Mesh(
new THREE.PlaneBufferGeometry( 40, 40 ),
new THREE.MeshPhongMaterial( { color: 0x999999, specular: 0x101010 } )
);
plane.rotation.x = -Math.PI/2;
plane.position.y = -0.5;
scene.add( plane );
plane.receiveShadow = true;
// feinleinen
var feinleinen = THREE.ImageUtils.loadTexture( 'textures/feinleinen.jpg' );
feinleinen.anisotropy = 1;
feinleinen.wrapS = feinleinen.wrapT = THREE.RepeatWrapping;
feinleinen.repeat.set( 5, 5 );
// create a cube
var basisGeometry = new THREE.BoxGeometry(3,0.02,3);
var basisMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, map: feinleinen } );
var basis = new THREE.Mesh(basisGeometry, basisMaterial);
basis.castShadow = false;
basis.receiveShadow = true;
// position the cube
basis.position.set( 0, -0.47, 0 );
// add the cube to the scene
scene.add(basis);
var loader = new THREE.JSONLoader();
loader.load('/models/hebelmechanik.js', function(geo, mat){
var chrome = new THREE.MeshLambertMaterial( { ambient: 0x444444, color: 0x111111, shininess: 800, specular: 0x111111, shading: THREE.SmoothShading, reflectivity: 1.1 } );
var mesh = new THREE.Mesh(geo, chrome);
mesh.position.set( 0, - 0.497, 0 );
mesh.rotation.set( 0, - Math.PI / 2, 0 );
mesh.scale.set( 0.008, 0.008, 0.008 );
mesh.castShadow = true;
mesh.receiveShadow = true;
loadJson(mesh );
});
function loadJson(mesh){
scene.add( mesh );
}
// Lights
scene.add( new THREE.AmbientLight( 0x777777 ) );
addShadowedLight( 1, 1, 1, 0xffffff, 1.35 );
addShadowedLight( 0.5, 1, -1, 0xffffff, 1 );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setClearColor( scene.fog.color );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
renderer.shadowMapCullFace = THREE.CullFaceBack;
previewDiv.appendChild (renderer.domElement);
// resize
window.addEventListener( 'resize', onWindowResize, false );
}
function addShadowedLight( x, y, z, color, intensity ) {
var directionalLight = new THREE.DirectionalLight( color, intensity );
directionalLight.position.set( x, y, z )
scene.add( directionalLight );
directionalLight.castShadow = true;
// directionalLight.shadowCameraVisible = true;
var d = 1;
directionalLight.shadowCameraLeft = -d;
directionalLight.shadowCameraRight = d;
directionalLight.shadowCameraTop = d;
directionalLight.shadowCameraBottom = -d;
directionalLight.shadowCameraNear = 1;
directionalLight.shadowCameraFar = 4;
directionalLight.shadowMapWidth = 2048;
directionalLight.shadowMapHeight = 2048;
directionalLight.shadowBias = -0.005;
directionalLight.shadowDarkness = 0.15;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
camera.lookAt( cameraTarget );
controls.update();
renderer.render( scene, camera );
}
</script>
You can add a cubemap reflection to your model by specifying the envMap property of the model's material.
Use a pattern like this one:
var path = "textures/cube/foo/";
var format = '.png';
var urls = [
path + 'px' + format, path + 'nx' + format,
path + 'py' + format, path + 'ny' + format,
path + 'pz' + format, path + 'nz' + format
];
var envMap = THREE.ImageUtils.loadTextureCube( urls, THREE.CubeReflectionMapping, callback ); // callback function is optional
var material = new THREE.MeshPhongMaterial( {
color : 0x999999,
specular : 0x050505,
shininess : 50,
envMap : envMap,
combine : THREE.MixOperation, // or THREE.AddOperation, THREE.MultiplyOperation
reflectivity : 0.5
} );
three.js r.71