commit 55b9cff266e6f5ff1a2668ef29ff57a6aba770fe
parent e7843b73235ee1c20d789e80e18e402a6b06e438
Author: Martin Klöckner <mjkloeckner@gmail.com>
Date: Mon, 24 Jun 2024 23:08:49 -0300
add `parametricRailsFoundation` function
Diffstat:
M | tp/src/rails.js | | | 236 | +++++++++++++++++++++++++++++++++---------------------------------------------- |
1 file changed, 97 insertions(+), 139 deletions(-)
diff --git a/tp/src/rails.js b/tp/src/rails.js
@@ -8,6 +8,8 @@ import { ParametricGeometries } from 'three/examples/jsm/geometries/ParametricGe
let scene, camera, renderer, container, terrainMaterial, instancedTrees;
let spherePath;
+let railsPath;
+let railsFoundationShape;
const textures = {
tierra: { url: '/assets/tierra.jpg', object: null },
@@ -28,19 +30,15 @@ function createPathWithSpheres() {
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const lineMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });
- // const geometry = new THREE.TubeGeometry( railsPath, 50, 1, 25, false );
-
const material = new THREE.MeshPhongMaterial({ color: 0xFF0000 });
- const sphere = new THREE.SphereGeometry(0.5,20,20);
+ // const sphere = new THREE.SphereGeometry(0.5,20,20);
+ const sphere = new THREE.CylinderGeometry(0.50, 0.50, 5.0);
const instancedSphereGeo = new THREE.InstancedBufferGeometry();
instancedSphereGeo.copy(sphere);
let count = 10;
const instancedSpheres = new THREE.InstancedMesh(instancedSphereGeo, material, count);
- // const sphere = new THREE.Mesh( geometry, material );
- // scene.add( sphere );
-
const rotMatrix = new THREE.Matrix4();
const translationMatrix = new THREE.Matrix4();
const sphereMatrix = new THREE.Matrix4()
@@ -65,134 +63,56 @@ function createPathWithSpheres() {
scene.add(curveObject);
}
-function getParametricPlaneFunction(width, height) {
- return function (u, v, target) {
- const x = -width / 2 + u * width;
- const y = 0;
- const z = -width / 2 + v * height;
-
- target.set(x, y, z);
- };
-}
-
-// buffer
-const vertices = [];
-const normals = [];
-const uvs = [];
-const indices = [];
-
-const vertex = new THREE.Vector3();
-const normal = new THREE.Vector3();
-const uv = new THREE.Vector2();
-
-function generateIndices(tubularSegments, radialSegments) {
- for ( let j = 1; j <= tubularSegments; j ++ ) {
- for ( let i = 1; i <= radialSegments; i ++ ) {
- const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
- const b = ( radialSegments + 1 ) * j + ( i - 1 );
- const c = ( radialSegments + 1 ) * j + i;
- const d = ( radialSegments + 1 ) * ( j - 1 ) + i;
-
- // faces
- indices.push( a, b, d );
- indices.push( b, c, d );
- }
- }
-}
-
-function generateSegment(i, frames, path, segments) {
- // we use getPointAt to sample evenly distributed points from the given path
- P = path.getPointAt(i/segments, P);
+function parametricRailsFoundation(u, v, target) {
+ const rotMatrix = new THREE.Matrix4();
+ const translationMatrix = new THREE.Matrix4();
+ const levelMatrix = new THREE.Matrix4();
- // retrieve corresponding normal and binormal
- const N = frames.normals[i];
- const B = frames.binormals[i];
+ let railsPathPos = railsPath.getPointAt(u);
+ let railsFoundationShapePos = railsFoundationShape.getPointAt(v);
- // generate normals and vertices for the current segment
- for (let j = 0; j <= radialSegments; j++) {
- const v = j / radialSegments*Math.PI*2;
+ let tangente = new THREE.Vector3();
+ let binormal = new THREE.Vector3();
+ let normal = new THREE.Vector3();
- const sin = Math.sin(v);
- const cos = - Math.cos(v);
+ tangente = railsPath.getTangent(u);
- // normal
- normal.x = (cos*N.x + sin*B.x);
- normal.y = (cos*N.y + sin*B.y);
- normal.z = (cos*N.z + sin*B.z);
- normal.normalize();
+ tangente.normalize();
+ binormal = new THREE.Vector3(0, 1, 0);
+ normal.crossVectors(tangente, binormal);
- normals.push( normal.x, normal.y, normal.z );
+ translationMatrix.makeTranslation(railsPathPos);
- // vertex
- vertex.x = P.x + radius * normal.x;
- vertex.y = P.y + radius * normal.y;
- vertex.z = P.z + radius * normal.z;
+ rotMatrix.identity();
+ levelMatrix.identity();
- vertices.push(vertex.x, vertex.y, vertex.z);
- }
+ levelMatrix.makeTranslation(railsPathPos);
+ rotMatrix.makeBasis(normal, tangente, binormal);
+ levelMatrix.multiply(rotMatrix);
+ railsFoundationShapePos.applyMatrix4(levelMatrix);
+
+ const x = railsFoundationShapePos.x;
+ const y = railsFoundationShapePos.y;
+ const z = railsFoundationShapePos.z;
+ target.set(x, y, z);
}
-function generateBufferData(tubularSegments) {
- for (let i = 0; i < tubularSegments; i++) {
- generateSegment(i);
- }
-
- // if the geometry is not closed, generate the last row of vertices and normals
- // at the regular position on the given path
- //
- // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)
- generateSegment( ( closed === false ) ? tubularSegments : 0 );
-
- // uvs are generated in a separate function.
- // this makes it easy compute correct values for closed geometries
- generateUVs();
-
- // finally create faces
- generateIndices();
-}
-
-function createPath() {
- //Create a closed wavey loop
- const path = new THREE.CatmullRomCurve3([
- new THREE.Vector3(-10, 0, 10),
- new THREE.Vector3( 10, 0, 10),
- new THREE.Vector3( 10, 0, -10),
- new THREE.Vector3(-10, 0, -10),
- ], true);
-
- const points = path.getPoints(50);
- const geometry = new THREE.BufferGeometry().setFromPoints(points);
- const lineMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });
-
- const curveObject = new THREE.Line(geometry, lineMaterial);
- scene.add(curveObject);
-
- const pMaterial = new THREE.MeshPhongMaterial({
- color: 0xFF0000,
- side: THREE.DoubleSide,
- transparent: false,
- opacity: 0.7,
- shininess: 10,
- specular: 0XFFFFFF,
- });
-
- let close = true;
- let segments = 10;
-
- frames = path.computeFrenetFrames(segments, closed);
-
- let P = new THREE.Vector3();
-
- // setIndex( indices );
- setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
- setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
- setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
-
- let samplingFunction = getParametricPlaneFunction(10, 10);
-
- let pGeometry = new ParametricGeometry(samplingFunction, 50, 50);
- let pMesh = new THREE.Mesh(pGeometry, pMaterial);
- scene.add(pMesh);
+function railsFoundation() {
+ railsFoundationShape = new THREE.CatmullRomCurve3([
+ new THREE.Vector3( -2, 0, 0),
+ new THREE.Vector3( -1, 0, 1),
+ new THREE.Vector3( 1, 0, 1),
+ new THREE.Vector3( 2, 0, 0),
+ ], false);
+
+ // const points = railsFoundationShape.getPoints(50);
+ // const geometry = new THREE.BufferGeometry().setFromPoints(points);
+ // const lineMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });
+ // const curveObject = new THREE.Line(geometry, lineMaterial);
+ // scene.add(curveObject);
+
+ const pGeometry = new ParametricGeometry(parametricRailsFoundation, 100, 10);
+ return pGeometry;
}
function onResize() {
@@ -268,28 +188,66 @@ function loadTextures(callback) {
}
}
-
-function createMenu() {
- const gui = new dat.GUI({ width: 400 });
- gui.add(terrainMaterial.uniforms.scale1, 'value', 0, 10).name('Texture scale');
- gui.add(terrainMaterial.uniforms.mask1low, 'value', -1, 1).name('Mask1 Low');
- gui.add(terrainMaterial.uniforms.mask1high, 'value', -1, 1).name('Mask1 High');
- gui.add(terrainMaterial.uniforms.mask2low, 'value', -1, 1).name('Mask2 Low');
- gui.add(terrainMaterial.uniforms.mask2high, 'value', -1, 1).name('Mask2 High');
-}
-
function mainLoop() {
requestAnimationFrame(mainLoop);
renderer.render(scene, camera);
}
+function buildRailsFoundation() {
+ railsPath = new THREE.CatmullRomCurve3([
+ new THREE.Vector3(-10, 0, 10),
+ new THREE.Vector3( 10, 0, 10),
+ new THREE.Vector3( 10, 0, -10),
+ new THREE.Vector3(-10, 0, -10),
+ ], true);
+
+ const pGeometry = railsFoundation();
+
+ textures.tierra.object.wrapS = THREE.MirroredRepeatWrapping;
+ textures.tierra.object.wrapT = THREE.MirroredRepeatWrapping;
+ textures.tierra.object.repeat.set(25, 1);
+ textures.tierra.object.anisotropy = 16;
+
+ /*
+ const map = new THREE.TextureLoader().load('https://threejs.org/examples/textures/uv_grid_opengl.jpg');
+ map.wrapS = map.wrapT = THREE.RepeatWrapping;
+ map.repeat.set(25, 1);
+ map.anisotropy = 16;
+ */
+
+ const pMaterial = new THREE.MeshPhongMaterial({
+ side: THREE.DoubleSide,
+ transparent: false,
+ opacity: 1.0,
+ shininess: 10,
+ map: textures.tierra.object
+ });
+ const pMesh = new THREE.Mesh(pGeometry, pMaterial);
+ scene.add(pMesh);
+}
+
+function buildPlane() {
+ const geo = new THREE.PlaneGeometry(20, 20);
+ const mat = new THREE.MeshPhongMaterial({
+ side: THREE.DoubleSide,
+ transparent: false,
+ opacity: 1.0,
+ shininess: 10,
+ map: textures.tierra.object
+ });
+ const mesh = new THREE.Mesh(geo, mat);
+ scene.add(mesh);
+}
+
function main() {
buildScene();
- // createMenu();
+ buildRailsFoundation();
mainLoop();
}
setupThreeJs();
-createPath();
-main();
-// loadTextures(main);
+// buildRailsPath();
+// createPath();
+// createPathWithSpheres();
+// main();
+loadTextures(main);