You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.0 KiB
HTML
157 lines
4.0 KiB
HTML
<body>
|
|
<canvas id="c"></canvas>
|
|
</body>
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"three": "../../build/three.module.js",
|
|
"three/addons/": "../../examples/jsm/"
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<script type="module">
|
|
import * as THREE from 'three';
|
|
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
|
|
function main() {
|
|
|
|
const canvas = document.querySelector( '#c' );
|
|
const renderer = new THREE.WebGLRenderer( { antialias: true, canvas } );
|
|
|
|
const fov = 45;
|
|
const aspect = 2; // the canvas default
|
|
const near = 0.1;
|
|
const far = 10000;
|
|
const camera = new THREE.PerspectiveCamera( fov, aspect, near, far );
|
|
camera.position.set( 0, 1000, 2000 );
|
|
|
|
const controls = new OrbitControls( camera, canvas );
|
|
controls.target.set( 0, 5, 0 );
|
|
controls.update();
|
|
|
|
const scene = new THREE.Scene();
|
|
scene.background = new THREE.Color( 'black' );
|
|
|
|
scene.add( new THREE.GridHelper( 5000, 10 ) );
|
|
|
|
let curve;
|
|
let curveObject;
|
|
{
|
|
|
|
const controlPoints = [
|
|
[ 1.118281, 5.115846, - 3.681386 ],
|
|
[ 3.948875, 5.115846, - 3.641834 ],
|
|
[ 3.960072, 5.115846, - 0.240352 ],
|
|
[ 3.985447, 5.115846, 4.585005 ],
|
|
[ - 3.793631, 5.115846, 4.585006 ],
|
|
[ - 3.826839, 5.115846, - 14.736200 ],
|
|
[ - 14.542292, 5.115846, - 14.765865 ],
|
|
[ - 14.520929, 5.115846, - 3.627002 ],
|
|
[ - 5.452815, 5.115846, - 3.634418 ],
|
|
[ - 5.467251, 5.115846, 4.549161 ],
|
|
[ - 13.266233, 5.115846, 4.567083 ],
|
|
[ - 13.250067, 5.115846, - 13.499271 ],
|
|
[ 4.081842, 5.115846, - 13.435463 ],
|
|
[ 4.125436, 5.115846, - 5.334928 ],
|
|
[ - 14.521364, 5.115846, - 5.239871 ],
|
|
[ - 14.510466, 5.115846, 5.486727 ],
|
|
[ 5.745666, 5.115846, 5.510492 ],
|
|
[ 5.787942, 5.115846, - 14.728308 ],
|
|
[ - 5.423720, 5.115846, - 14.761919 ],
|
|
[ - 5.373599, 5.115846, - 3.704133 ],
|
|
[ 1.004861, 5.115846, - 3.641834 ],
|
|
];
|
|
const p0 = new THREE.Vector3();
|
|
const p1 = new THREE.Vector3();
|
|
curve = new THREE.CatmullRomCurve3(
|
|
controlPoints.map( ( p, ndx ) => {
|
|
|
|
p0.set( ...p );
|
|
p1.set( ...controlPoints[ ( ndx + 1 ) % controlPoints.length ] );
|
|
return [
|
|
( new THREE.Vector3() ).copy( p0 ),
|
|
( new THREE.Vector3() ).lerpVectors( p0, p1, 0.1 ),
|
|
( new THREE.Vector3() ).lerpVectors( p0, p1, 0.9 ),
|
|
];
|
|
|
|
} ).flat(),
|
|
true,
|
|
);
|
|
{
|
|
|
|
const points = curve.getPoints( 250 );
|
|
const geometry = new THREE.BufferGeometry().setFromPoints( points );
|
|
const material = new THREE.LineBasicMaterial( { color: 0xff0000 } );
|
|
curveObject = new THREE.Line( geometry, material );
|
|
curveObject.scale.set( 100, 100, 100 );
|
|
curveObject.position.y = - 621;
|
|
material.depthTest = false;
|
|
curveObject.renderOrder = 1;
|
|
scene.add( curveObject );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const geometry = new THREE.BoxGeometry( 100, 100, 300 );
|
|
const material = new THREE.MeshBasicMaterial( { color: 'cyan' } );
|
|
const cars = [];
|
|
for ( let i = 0; i < 10; ++ i ) {
|
|
|
|
const mesh = new THREE.Mesh( geometry, material );
|
|
scene.add( mesh );
|
|
cars.push( mesh );
|
|
|
|
}
|
|
|
|
// create 2 Vector3s we can use for path calculations
|
|
const carPosition = new THREE.Vector3();
|
|
const carTarget = new THREE.Vector3();
|
|
|
|
function render( time ) {
|
|
|
|
time *= 0.001; // convert to seconds
|
|
|
|
{
|
|
|
|
const pathTime = time * .01;
|
|
const targetOffset = 0.01;
|
|
cars.forEach( ( car, ndx ) => {
|
|
|
|
// a number between 0 and 1 to evenly space the cars
|
|
const u = pathTime + ndx / cars.length;
|
|
|
|
// get the first point
|
|
curve.getPointAt( u % 1, carPosition );
|
|
carPosition.applyMatrix4( curveObject.matrixWorld );
|
|
|
|
// get a second point slightly further down the curve
|
|
curve.getPointAt( ( u + targetOffset ) % 1, carTarget );
|
|
carTarget.applyMatrix4( curveObject.matrixWorld );
|
|
|
|
// put the car at the first point (temporarily)
|
|
car.position.copy( carPosition );
|
|
// point the car the second point
|
|
car.lookAt( carTarget );
|
|
|
|
// put the car between the 2 points
|
|
car.position.lerpVectors( carPosition, carTarget, 0.5 );
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
renderer.render( scene, camera );
|
|
|
|
requestAnimationFrame( render );
|
|
|
|
}
|
|
|
|
requestAnimationFrame( render );
|
|
|
|
}
|
|
|
|
main();
|
|
</script>
|