Three.js - Issues with shapes and inside holes - javascript

I'm having an issue, how can I obtain a kind of "open ring" like the torus but squared?
I tried with a shape plus a path as a hole:
var arcShape = new THREE.Shape();
arcShape.moveTo( 40, 0 );
arcShape.arc( 0, 0, 40, 0, 2*Math.PI, false );
var holePath = new THREE.Path();
holePath.moveTo( 30,0 )
holePath.arc( 0, 0, 30, 0, 2*Math.PI, true );
And until now, making a mesh:
new THREE.Mesh( arcShape.extrude({ amount: 5, bevelEnabled: false }), MATERIAL );
it works, but how to make a middle ring? I mean, with:
var arcShape = new THREE.Shape();
arcShape.moveTo( 40, 0 );
arcShape.arc( 0, 0, 40, 0, Math.PI, false );
var holePath = new THREE.Path();
holePath.moveTo( 30,0 );
holePath.arc( 0, 0, 30, 0, Math.PI, true );
It works, but it remains a subtle face between the terminal parts... is there a way to make it completely open?

Rather than start from square one, try changing the parameters in the Torus geometry constructor:
// Torus geometry parameters:
// radius of entire torus,
// diameter of tube (should be less than total radius),
// segments around radius,
// segments around torus ("sides")
var torusGeom = new THREE.TorusGeometry( 25, 10, 4, 4 );

Related

Load single image on multiple surface of BoxGeometry - Three.js

I am using three.js for creating 3D Objects. I want to create 3d canvas similar like this in my project.
I want to render a single image on all side of object (box) except back.
I have found one similar example here:
https://www.geofx.com/graphics/nehe-three-js/lessons17-24/lesson17/lesson17.html.
I am planing to BoxGeomatry along with 2D faceVertexUvs (custom alignment) to cover surfaces.Is there any way I can do it easily rather than managing Vector2 (2D)? Any way I can use Vector3 (3D) or provide pixel to manage easily?
As I am new to Threejs, please suggest better approach if any?
An option with uvs of BoxBufferGeometry:
body {
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://threejs.org/build/three.module.js";
import {OrbitControls} from "https://threejs.org/examples/jsm/controls/OrbitControls.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 controls = new OrbitControls(camera, renderer.domElement);
var g = new THREE.BoxBufferGeometry(10, 5, 1);
var uv = g.getAttribute("uv");
// +x
uv.setXY(0, 1, 1);
uv.setXY(1, 0.9, 1);
uv.setXY(2, 1, 0);
uv.setXY(3, 0.9, 0);
// -x
uv.setXY(4, 0.1, 1);
uv.setXY(5, 0, 1);
uv.setXY(6, 0.1, 0);
uv.setXY(7, 0, 0);
// +y
uv.setXY(8, 0, 0.8);
uv.setXY(9, 1, 0.8);
uv.setXY(10, 0, 1);
uv.setXY(11, 1, 1);
// -y
uv.setXY(12, 0, 0);
uv.setXY(13, 1, 0);
uv.setXY(14, 0, 0.2);
uv.setXY(15, 1, 0.2);
// -z ("back") - white area from 0,0 of map
uv.setXY(20, 0, 0);
uv.setXY(21, 0, 0);
uv.setXY(22, 0, 0);
uv.setXY(23, 0, 0);
var m = new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/uv_grid_opengl.jpg")});
var o = new THREE.Mesh(g, m);
scene.add(o);
renderer.setAnimationLoop(()=>{
renderer.render(scene, camera);
});
</script>

Extrude 3d shape from THREE.Line object in three.js

In three.js I have created an ellipseCurve for which I want to extrude and make 3d.
CODE USE TO MAKE THIS:
var curve = new THREE.EllipseCurve(
0, 0, // ax, aY
10, 13.3, // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
var path = new THREE.Path( curve.getPoints( 100 ) );
var geometrycirc = path.createPointsGeometry( 50 );
var materialcirc = new THREE.LineBasicMaterial( {
color : 0xff0000
} );
// Create the final object to add to the scene
var ellipse = new THREE.Line( geometrycirc, materialcirc );
this.scene.add( ellipse );
I want to use this ellipseCurve as a basis to create an extruded shape similar to these examples.
https://threejs.org/examples/#webgl_geometry_extrude_splines
These examples seem to use vectors to do this, so I assume I need to convert the curve into one.
I am not sure how to do this since I have been unable to find references on this matter.
Any help to do this?
UPDATE: 22/03/2017
Right so I tried to implement the same method of extrusion as found on:
https://threejs.org/examples/#webgl_geometry_extrude_splines
I was able to but this spline into my scene:
HERE IS THE CODE TO DO THIS:
/////////////////////////////////////////////////////////////////////////
// My line curve //
/////////////////////////////////////////////////////////////////////////
var curve = new THREE.EllipseCurve(
0, 0, // ax, aY
10, 13.3, // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
var path = new THREE.Path( curve.getPoints( 100 ) );
var geometrycirc = path.createPointsGeometry( 50 );
var materialcirc = new THREE.LineBasicMaterial( {
color : 0xff0000
} );
// Create the final object based on points and material
var ellipse = new THREE.Line( geometrycirc, materialcirc );
this.scene.add( ellipse );
////////////////////////////////////////////////////////////////////////
// Example of sample closed spine //
////////////////////////////////////////////////////////////////////////
var sampleClosedSpline = new THREE.CatmullRomCurve3( [
new THREE.Vector3( 0, -40, -40 ),
new THREE.Vector3( 0, 40, -40 ),
new THREE.Vector3( 0, 140, -40 ),
new THREE.Vector3( 0, 40, 40 ),
new THREE.Vector3( 0, -40, 40 )
] );
sampleClosedSpline.type = 'catmullrom';
sampleClosedSpline.closed = true;
//////////////////////////////////////////////////////////////////////////////
// Extrusion method to covert the spline/vector data into 3d object //
//////////////////////////////////////////////////////////////////////////////
// I used this method and have tried the following properties but these do not work
//
// var tube = new THREE.TubeBufferGeometry( curve, 12, 2, 20, true);
//
// 1. ellipse.clone()
// 2. geometrycirc.clone()
// 3. materialcirc.clone()
// 4. path.clone()
// 5. curve
//
// Therefore I am either doing something wrong or there must be a further process that needs
// to be implemented.
// this works as standard
var tube = new THREE.TubeBufferGeometry( sampleClosedSpline, 12, 2, 20, true);
var tubeMesh = THREE.SceneUtils.createMultiMaterialObject( tube, [
new THREE.MeshLambertMaterial( {
color: 0xffffff
} ),
new THREE.MeshBasicMaterial( {
color: 0xff00ff,
opacity: 0.3,
wireframe: true,
transparent: true
} ) ] );
tubeMesh.scale.set( .2, .2, .2 );
this.scene.add( tubeMesh );
///////////////////////////////////////////////////////////////////////////////
So when I place the spline property for the one that I have created i get a black screen and the following error msgs:
var curve;
and the other variables used (refer to code to see what I have tried)
EDIT: 23/03/2017
WestLangley's method was the ideal solution
You want to create a TubeGeometry or TubeBufferGeometry in the shape of an ellipse.
Here is one way to do it that is general enough for others to use, too.
First, create a new class that defines your path:
// Ellipse class, which extends the virtual base class Curve
class Ellipse extends THREE.Curve {
constructor( xRadius, yRadius ) {
super();
// add radius as a property
this.xRadius = xRadius;
this.yRadius = yRadius;
}
getPoint( t, optionalTarget = new THREE.Vector3() ) {
const point = optionalTarget;
var radians = 2 * Math.PI * t;
return new THREE.Vector3( this.xRadius * Math.cos( radians ),
this.yRadius * Math.sin( radians ),
0 );
}
}
Then create the geometry from the path.
// path
var path = new Ellipse( 5, 10 );
// params
var pathSegments = 64;
var tubeRadius = 0.5;
var radiusSegments = 16;
var closed = true;
var geometry = new THREE.TubeBufferGeometry( path, pathSegments, tubeRadius, radiusSegments, closed );
Super easy. :)
Fiddle: http://jsfiddle.net/62qhxags/
three.js r.129

three.js shape holes height

I'm trying to build a Mesh with holes from an original Shape and then an ExtrudedGeometry. The problem is that the holes I add always go trough the whole height of the resulting Mesh. Is there any way to make the holes shorter in height, so in the end these don't go across the whole shape?
Reference code for the shape to extruded:
var heartShape = new THREE.Shape();
heartShape.moveTo( 25, 25 );
heartShape.bezierCurveTo( 25, 25, 20, 0, 0, 0 );
blah
var innerCircle = new THREE.Path();
innerCircle.moveTo(blah);
heartShape.holes.push(innerCircle);
var extrudeSettings = { amount: 8, bevelEnabled: true, bevelSegments: 2, steps: 2, bevelSize: 1, bevelThickness: 1 };
var geometry = new THREE.ExtrudeGeometry( heartShape, extrudeSettings );
var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial() );
Thanks!
There is no separate argument for hole depth in THREE.ExtrudeGeometry. You will need two separate operations to solve it.
One solution could be to "plug" it with another extrude based on your inner circle path (convert to Shape first).
var extrudeSettingsForPlug = { amount: 4, bevelEnabled: true, bevelSegments: 2, steps: 2, bevelSize: 1, bevelThickness: 1 };
var geometry = new THREE.ExtrudeGeometry( innerCircleShape, extrudeSettingsForPlug );

How to arrange objects in a straight line in three.js

I'm making a chess board with three.js. I have all of the files rendering properly (stl loader) but I can't seem to make them load on the correct position. I am setting all the pieces in a straight line as far as I thought but they appear staggered.
here is my code:
function renderPiece(loader, piece, coor, color) {
loader.load(piece, function(geometry) {
var material = new THREE.MeshPhongMaterial({color:color})
var mesh = new THREE.Mesh(geometry, material)
chessBoard.objects.push(mesh)
// mesh.position.set(coor[0], coor[1], coor[2])
mesh.position.x = coor[0]
mesh.position.y = coor[1]
mesh.position.z = coor[2]
mesh.scale.set(0.75,0.75, 0.75);
chessBoard.scene.add(mesh)
})
}
and here are the fn calls with coordinates:
var oStlLoader = new THREE.STLLoader()
renderPiece(oStlLoader, pieces.rook, [0, 0, -210], 0x000000)
renderPiece(oStlLoader, pieces.bishop, [0, 0, -140], 0x000000)
renderPiece(oStlLoader, pieces.knight, [0, 0, -70], 0x000000)
renderPiece(oStlLoader, pieces.king, [0, 0, 0], 0x000000)
renderPiece(oStlLoader, pieces.queen, [0, 0, 70], 0x000000)
renderPiece(oStlLoader, pieces.knight, [0, 0, 140], 0x000000)
renderPiece(oStlLoader, pieces.bishop, [0, 0, 210], 0x000000)
renderPiece(oStlLoader, pieces.rook, [0, 0, 280], 0x000000)
You must create 3D models with a XYZ zero vector in the place, where should be center of your chess field.
After that, you can use more simple method to set correct positions, use predefined vector array for that:
var fields = [];
fields['a1'] = new THREE.Vector3(10,0,10);
fields['a2'] = new THREE.Vector3(10,0,20);
fields['b1'] = new THREE.Vector3(20,0,10);
and then set a position of your model:
mymodel.position.set(fields['a2'].x,fields['a2'].y,fields['a2'].z);
//or
mymodel.position = new THREE.Vector3.copy(fields['a2']);

How to make a rectangular pyramid in three.js r68?

I'm on r68 and I'm trying to find an example of someone creating a rectangular pyramid which I can apply THREE.MeshFaceMaterial() to, most of the examples seem fairly out of date and throw errors with my current build.
I just need to be able to
Texturise each face
Rotate it so the rectangular face is at the -y position
Thanks in advance!
The accepted answer works only for pyramids with a base that has equal sides. In case you want a pyramid with a rectangular foot you can do like this:
var geometry = new THREE.Geometry();
geometry.vertices = [
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 0, 1, 0 ),
new THREE.Vector3( 1, 1, 0 ),
new THREE.Vector3( 1, 0, 0 ),
new THREE.Vector3( 0.5, 0.5, 1 )
];
geometry.faces = [
new THREE.Face3( 0, 1, 2 ),
new THREE.Face3( 0, 2, 3 ),
new THREE.Face3( 1, 0, 4 ),
new THREE.Face3( 2, 1, 4 ),
new THREE.Face3( 3, 2, 4 ),
new THREE.Face3( 0, 3, 4 )
];
Now you have a pyramid geometry with a square base of 1 x 1 and a height of 1. By applying a scaling matrix we can make this pyramid to any desired width/length/height combination:
var transformation = new THREE.Matrix4().makeScale( width, length, height );
geometry.applyMatrix( transformation );
This can also be wrapped in a custom Pyramid geometry class so you can use it like this:
new THREE.Pyramid( width, length, height );
As #WestLangley stated, using a THREE.CylinderGeometry() to do this is the correct way, here's how I did mine
var geometry = new THREE.CylinderGeometry( 1, TILE_SIZE*3, TILE_SIZE*3, 4 );
var material = new THREE.MeshBasicMaterial( {color: 0xffff00 , wireframe:true} );
var cylinder = new THREE.Mesh( geometry, material );
this.scene.add( cylinder );
Works perfect!
Use ConeBufferGeometry geometry and change radialSegments to 4
BufferGeometry are faster than normal Geometry
Other parameters you can tweak:
ConeBufferGeometry(radius : Float, height : Float, radialSegments : Integer, heightSegments : Integer, openEnded : Boolean, thetaStart : Float, thetaLength : Float)
Result:
Live Demo:
https://threejs.org/docs/#api/en/geometries/ConeBufferGeometry

Categories

Resources