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>
Related
My project uses geometry where each face is its own mesh. I need to clip the geometry to cut away a portion of it and have a stenciled cap face cover the clipped edges. I examined and tinkered with the Three.js clipping stencil example and I understand how to use a stencil to cap trimmed solid geometry, but when I try it on collections of face geometries it doesn't work. Here is some code I have been tinkering with, based on the example:
body { margin: 0; }
canvas { display: block; }
<script type="module">
import * as THREE from 'https://unpkg.com/three#0.120.1/build/three.module.js';
import { OrbitControls } from 'https://unpkg.com/three#0.120.1/examples/jsm/controls/OrbitControls.js';
import { BufferGeometryUtils } from 'https://unpkg.com/three#0.120.1/examples/jsm/utils/BufferGeometryUtils.js';
var camera, scene, renderer;
var planes, planeObjects;
init();
animate();
function createPlaneStencilGroup( geometry, plane, renderOrder )
{
var group = new THREE.Group();
var baseMat = new THREE.MeshBasicMaterial();
baseMat.depthWrite = false;
baseMat.depthTest = false;
baseMat.colorWrite = false;
baseMat.stencilWrite = true;
baseMat.stencilFunc = THREE.AlwaysStencilFunc;
// back faces
var mat0 = baseMat.clone();
mat0.side = THREE.BackSide;
mat0.clippingPlanes = [ plane ];
mat0.stencilFail = THREE.IncrementWrapStencilOp;
mat0.stencilZFail = THREE.IncrementWrapStencilOp;
mat0.stencilZPass = THREE.IncrementWrapStencilOp;
var mesh0 = new THREE.Mesh( geometry, mat0 );
mesh0.renderOrder = renderOrder;
group.add( mesh0 );
// front faces
var mat1 = baseMat.clone();
mat1.side = THREE.FrontSide;
mat1.clippingPlanes = [ plane ];
mat1.stencilFail = THREE.DecrementWrapStencilOp;
mat1.stencilZFail = THREE.DecrementWrapStencilOp;
mat1.stencilZPass = THREE.DecrementWrapStencilOp;
var mesh1 = new THREE.Mesh( geometry, mat1 );
mesh1.renderOrder = renderOrder;
group.add( mesh1 );
return group;
}
function init()
{
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 36, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.set( 2, 2, 2 );
initLights();
planes = [
new THREE.Plane( new THREE.Vector3( 0, - 1, 0 ), 0.42 ),
new THREE.Plane( new THREE.Vector3( 0, 0, - 1 ), 0.25 )
];
var material = new THREE.MeshStandardMaterial( {
color: 0x00ff00,
metalness: 0.1,
roughness: 0.75,
side: THREE.DoubleSide,
clippingPlanes: planes,
clipShadows: true,
shadowSide: THREE.DoubleSide,
} );
// Simple sphere geometry. Something I know works, for comparison.
var sphereGeom = new THREE.SphereBufferGeometry( 0.5, 32, 32 );
sphereGeom.translate( -1.1, 0, 0 );
// Make a cube out of 6 planes and merge them together
var planeGeoms = [];
for(var i = 0; i < 6; i++)
{
planeGeoms.push( new THREE.PlaneBufferGeometry( 1, 1 ) );
}
var mergedBufferGeom = BufferGeometryUtils.mergeBufferGeometries( planeGeoms );
// Set up clip plane rendering
planeObjects = [];
var planeGeom = new THREE.PlaneBufferGeometry( 4, 4 );
for ( var i = 0; i < 2; i ++ )
{
var poGroup = new THREE.Group();
var plane = planes[ i ];
var stencilGroup_sphere = createPlaneStencilGroup( sphereGeom, plane, i + 1 );
var stencilGroup_Box = createPlaneStencilGroup( mergedBufferGeom, plane, i + 1 )
// plane is clipped by the other clipping planes
var planeMat = new THREE.MeshStandardMaterial( {
color: 0x0000ff,
metalness: 0.1,
roughness: 0.75,
clippingPlanes: planes.filter( p => p !== plane ),
stencilWrite: true,
stencilRef: 0,
stencilFunc: THREE.NotEqualStencilFunc,
stencilFail: THREE.ReplaceStencilOp,
stencilZFail: THREE.ReplaceStencilOp,
stencilZPass: THREE.ReplaceStencilOp,
} );
var po = new THREE.Mesh( planeGeom, planeMat );
po.onAfterRender = function ( renderer ) {
renderer.clearStencil();
};
po.renderOrder = i + 1.1;
plane.coplanarPoint( po.position );
po.lookAt(
po.position.x - plane.normal.x,
po.position.y - plane.normal.y,
po.position.z - plane.normal.z,
);
scene.add( stencilGroup_sphere );
scene.add( stencilGroup_Box );
poGroup.add( po );
planeObjects.push( po );
scene.add( poGroup );
}
var sphereMesh = new THREE.Mesh( sphereGeom, material );
sphereMesh.renderOrder = 6;
scene.add( sphereMesh );
var planeMeshes = [];
for(var i = 0; i < 6; i++)
{
planeMeshes.push( new THREE.Mesh(planeGeoms[i], material) );
}
planeMeshes[0].position.copy(new THREE.Vector3(.5, 0, 0));
planeMeshes[1].position.copy(new THREE.Vector3(0, .5, 0));
planeMeshes[2].position.copy(new THREE.Vector3(0, 0, .5));
planeMeshes[3].position.copy(new THREE.Vector3(-.5, 0, 0));
planeMeshes[4].position.copy(new THREE.Vector3(0, -.5, 0));
planeMeshes[5].position.copy(new THREE.Vector3(0, 0, -.5));
planeMeshes[0].lookAt(new THREE.Vector3(2, 0, 0));
planeMeshes[1].lookAt(new THREE.Vector3(0, 2, 0));
planeMeshes[2].lookAt(new THREE.Vector3(0, 0, 2));
planeMeshes[3].lookAt(new THREE.Vector3(-2, 0, 0));
planeMeshes[4].lookAt(new THREE.Vector3(0, -2, 0));
planeMeshes[5].lookAt(new THREE.Vector3(0, 0, -2));
for(var i = 0; i < 6; i++)
scene.add( planeMeshes[i] );
// Renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.shadowMap.enabled = true;
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x263238 );
renderer.localClippingEnabled = true;
window.addEventListener( 'resize', onWindowResize, false );
document.body.appendChild( renderer.domElement );
// Controls
var controls = new OrbitControls( camera, renderer.domElement );
controls.minDistance = 2;
controls.maxDistance = 20;
controls.update();
}
function initLights()
{
scene.add( new THREE.AmbientLight( 0xffffff, 0.5 ) );
var dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
dirLight.position.set( 5, 10, 7.5 );
dirLight.castShadow = true;
dirLight.shadow.camera.right = 2;
dirLight.shadow.camera.left = - 2;
dirLight.shadow.camera.top = 2;
dirLight.shadow.camera.bottom = - 2;
dirLight.shadow.mapSize.width = 1024;
dirLight.shadow.mapSize.height = 1024;
scene.add( dirLight );
}
function onWindowResize()
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate()
{
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
</script>
It contains 2 clipping planes, a cube made from 6 separate PlaneGeometries, and a solid sphere for comparison. I made the stencil for the cube using an additional BufferGeometry made from merging the planes together into a single geometry object. The stencil for the cube appears to be the right shape and size, but only one cap face is drawn and it is not at the location of either of the clipping planes. Is there anything else I'm supposed to do with the stencil or the clipping plane beyond what the example already does to make it work on geometry of this type?
Turns out the PlaneBufferGeometries that were getting merged for the stencil were not in the same positions as the plane meshes that used those geometries. That is why the cap face wasn't being drawn properly. I had not considered the fact that if you apply a transform to a Mesh, then get the Mesh's geometry to use elsewhere, that geometry won't reflect the transform applied to the Mesh. I got it to work by applying the transform matrices from the plane meshes to the PlaneBufferGeometries that needed to be merged.
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 used this cool codepen to have my camera follow a spline :
https://codepen.io/wiledal/pen/WvNvEq
This works great but I want to have a uniform speed during my camera movement.
I played with all the parameters of the CatmullRomCurve3() function but to no avail.
In the following example you can see that it slows down at once when it reaches the curves.
Should I try to have the same intensity of points everywhere all along my spline ? If so how can I do that ?
Thank you very much.
var renderer, scene, camera, spline, camPos, camPosIndex;
function init(){
renderer = new THREE.WebGLRenderer();
scene = new THREE.Scene();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const W = window.innerWidth;
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, .1, 2000 );
spline = new THREE.CatmullRomCurve3([
new THREE.Vector3( -70, 9 ),
new THREE.Vector3( -20, 9 ),
new THREE.Vector3( -13, 9 ),
new THREE.Vector3( 13, -9 ),
new THREE.Vector3( 20, -9 ),
new THREE.Vector3( 70, -9 ),
]);
var points = spline.getPoints(500);
var geometry = new THREE.BufferGeometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color : 0xffffff } );
// Create the final object to add to the scene
var splineObject = new THREE.Line( geometry, material );
scene.add(splineObject);
camPosIndex = 0;
}
let speed = 1000;
function update() {
renderer.render(scene, camera);
requestAnimationFrame(update);
camPosIndex++;
if (camPosIndex > speed) {
camPosIndex = 0;
}
var camPos = spline.getPoint(camPosIndex / speed);
var camRot = spline.getTangent(camPosIndex / speed);
camera.position.x = camPos.x;
camera.position.y = camPos.y;
camera.position.z = camPos.z + 40; // so I can watch my spline
camera.rotation.x = camRot.x;
camera.rotation.y = camRot.y;
camera.rotation.z = camRot.z;
camera.lookAt(spline.getPoint((camPosIndex+1) / speed));
}
init();
update();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
I'm implementing the function to rotate the mesh using the mouse.
referencing code is linked site.
("http://3dit.bordeaux.inria.fr/testbed.html#navigation_Map_Navigation")
I would like to know how to use the mouse to rotate around the Z axis (red line).
I have found that all of the examples in Three.js have only a way to rotate around the x or y axis.
Really need help.
My code : https://jsfiddle.net/pfk7j7a3/3/
<script type="text/javascript">
CustomOrbit = function () {
var EPS = 0.000001;
var rotateStart = new THREE.Vector2();
var rotateEnd = new THREE.Vector2();
var rotateDelta = new THREE.Vector2();
var phiDelta = 0;
var thetaDelta = 0;
var target = new THREE.Vector3();
/// How far you can orbit vertically, upper and lower limits.
var minPolarAngle = Math.PI / 2;
var maxPolarAngle = Math.PI * 0.91;
var onMouseDownPosition = new THREE.Vector2();
this.Initialize = function () {
renderer.domElement.addEventListener('mousedown', onMouseDown, false);
}
var onMouseMove = function (event) {
event.preventDefault();
rotateEnd.set(event.clientX, event.clientY);
rotateDelta.subVectors(rotateEnd, rotateStart);
thetaDelta -= 2 * Math.PI * rotateDelta.x / renderer.domElement.clientWidth;
phiDelta -= 2 * Math.PI * rotateDelta.y / renderer.domElement.clientHeight;
var position = camera.position;
var offset = position.clone().sub(target);
// angle from z-axis around y-axis
var theta = Math.atan2(offset.x, offset.z);
theta += thetaDelta;
// angle from y-axis
var phi = Math.atan2(Math.sqrt(offset.x * offset.x + offset.z * offset.z), offset.y);
phi += phiDelta;
phi = Math.max(minPolarAngle, Math.min(maxPolarAngle, phi));// restrict phi to be between desired limits
phi = Math.max(EPS, Math.min(Math.PI - EPS, phi)); // restrict phi to be between EPS and PI-EPS
var radius = offset.length();
radius = Math.max(0, Math.min(Infinity, radius)); // restrict radius to be between desired limits
offset.x = radius * Math.sin(phi) * Math.sin(theta);
offset.y = radius * Math.cos(phi);
offset.z = radius * Math.sin(phi) * Math.cos(theta);
position.copy(target).add(offset);
camera.lookAt(target);
thetaDelta = 0;
phiDelta = 0;
rotateStart.copy(rotateEnd);
}
var onMouseUp = function (event) {
renderer.domElement.removeEventListener('mousemove', onMouseMove, false);
renderer.domElement.removeEventListener('mouseup', onMouseUp, false);
}
var onMouseDown = function (event) {
event.preventDefault();
vector = new THREE.Vector3(0, 0, camera.near);
vector.unproject(camera);
raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize(), camera.near, camera.far);
intersects = raycaster.intersectObject(pickingMesh);
if (intersects.length > 0) {
target = intersects[0].point;
rotateStart.set(event.clientX, event.clientY);
renderer.domElement.addEventListener('mousemove', onMouseMove, false);
renderer.domElement.addEventListener('mouseup', onMouseUp, false);
}
}
};
</script>
<script type="text/javascript">
var camera, scene, renderer, pickingMesh, rendWidth = 500, rendHeight = 500;
init();
makeMesh();
makeAxis(200);
animate();
function init() {
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false });
renderer.setSize(500, 500);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(55, 500 / 500, 0.1, 10000);
camera.position.x = 200000;
camera.position.y = 400000;
camera.position.z = 300;
camera.lookAt(new THREE.Vector3(200000, 400000, 0.0));
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
//create red square mesh
function makeMesh() {
var geometry = new THREE.BufferGeometry();
var vertices = new Float32Array([
200000 - 100.0, 400000 - 100.0, 0.0,
200000 + 100.0, 400000 + 100.0, 0.0,
200000 - 100.0, 400000 + 100.0, 0.0,
200000 - 100.0, 400000 - 100.0, 0.0,
200000 + 100.0, 400000 - 100.0, 0.0,
200000 + 100.0, 400000 + 100.0, 0.0
]);
geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
var material = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: true, opacity: 0.5 });
material.side = THREE.DoubleSide;
pickingMesh = new THREE.Mesh(geometry, material);
scene.add(pickingMesh);
}
function makeAxis(axisLength) {
var x_axis = new THREE.Geometry(); x_axis.vertices.push(new THREE.Vector3(200000 - axisLength, 400000, 0), new THREE.Vector3(200000 + axisLength, 400000, 0));
var y_axis = new THREE.Geometry(); y_axis.vertices.push(new THREE.Vector3(200000, 400000 - axisLength, 0), new THREE.Vector3(200000, 400000 + axisLength, 0));
var z_axis = new THREE.Geometry(); z_axis.vertices.push(new THREE.Vector3(200000, 400000, -axisLength), new THREE.Vector3(200000, 400000, axisLength));
var x_axis_line = new THREE.Line(x_axis, new THREE.LineBasicMaterial({ linewidth: 1, transparent: true, color: 0x0000ff }));
var y_axis_line = new THREE.Line(y_axis, new THREE.LineBasicMaterial({ linewidth: 1, transparent: true, color: 0x00ff00 }));
var z_axis_line = new THREE.Line(z_axis, new THREE.LineBasicMaterial({ linewidth: 1, transparent: true, color: 0xff0000 }));
scene.add(x_axis_line);
scene.add(y_axis_line);
scene.add(z_axis_line);
};
var myOrbit = new CustomOrbit();
myOrbit.Initialize();
</script>
If you try to rotate out of 0,0,0 position (camera around something, object on some position around center), mathematics will start to be more complicated.
My best experience is with orbit controls.
https://threejs.org/examples/misc_controls_orbit.html
You can set a angle limitation and pan limitation.
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 );