代码拉取完成,页面将自动刷新
<!DOCTYPE html>
<html lang="en">
<head>
<title>Verge3D vr - roller coaster</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<script type="module">
import * as v3d from '../build/v3d.module.js';
import {
RollerCoasterGeometry,
RollerCoasterShadowGeometry,
RollerCoasterLiftersGeometry,
TreesGeometry,
SkyGeometry
} from './jsm/misc/RollerCoaster.js';
import { VRButton } from './jsm/webxr/VRButton.js';
let mesh, material, geometry;
const renderer = new v3d.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.xr.enabled = true;
renderer.xr.setReferenceSpaceType('local');
document.body.appendChild(renderer.domElement);
document.body.appendChild(VRButton.createButton(renderer));
//
const scene = new v3d.Scene();
scene.background = new v3d.Color(0xf0f0ff);
const light = new v3d.HemisphereLight(0xfff0f0, 0x606066);
light.position.set(1, 1, 1);
scene.add(light);
const train = new v3d.Object3D();
scene.add(train);
const camera = new v3d.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 500);
train.add(camera);
// environment
geometry = new v3d.PlaneBufferGeometry(500, 500, 15, 15);
geometry.rotateX(- Math.PI / 2);
const positions = geometry.attributes.position.array;
const vertex = new v3d.Vector3();
for (let i = 0; i < positions.length; i += 3) {
vertex.fromArray(positions, i);
vertex.x += Math.random() * 10 - 5;
vertex.z += Math.random() * 10 - 5;
const distance = (vertex.distanceTo(scene.position) / 5) - 25;
vertex.y = Math.random() * Math.max(0, distance);
vertex.toArray(positions, i);
}
geometry.computeVertexNormals();
material = new v3d.MeshLambertMaterial({
color: 0x407000
});
mesh = new v3d.Mesh(geometry, material);
scene.add(mesh);
geometry = new TreesGeometry(mesh);
material = new v3d.MeshBasicMaterial({
side: v3d.DoubleSide, vertexColors: true
});
mesh = new v3d.Mesh(geometry, material);
scene.add(mesh);
geometry = new SkyGeometry();
material = new v3d.MeshBasicMaterial({ color: 0xffffff });
mesh = new v3d.Mesh(geometry, material);
scene.add(mesh);
//
const PI2 = Math.PI * 2;
const curve = (function() {
const vector = new v3d.Vector3();
const vector2 = new v3d.Vector3();
return {
getPointAt: function(t) {
t = t * PI2;
const x = Math.sin(t * 3) * Math.cos(t * 4) * 50;
const y = Math.sin(t * 10) * 2 + Math.cos(t * 17) * 2 + 5;
const z = Math.sin(t) * Math.sin(t * 4) * 50;
return vector.set(x, y, z).multiplyScalar(2);
},
getTangentAt: function(t) {
const delta = 0.0001;
const t1 = Math.max(0, t - delta);
const t2 = Math.min(1, t + delta);
return vector2.copy(this.getPointAt(t2))
.sub(this.getPointAt(t1)).normalize();
}
};
})();
geometry = new RollerCoasterGeometry(curve, 1500);
material = new v3d.MeshPhongMaterial({
vertexColors: true
});
mesh = new v3d.Mesh(geometry, material);
scene.add(mesh);
geometry = new RollerCoasterLiftersGeometry(curve, 100);
material = new v3d.MeshPhongMaterial();
mesh = new v3d.Mesh(geometry, material);
mesh.position.y = 0.1;
scene.add(mesh);
geometry = new RollerCoasterShadowGeometry(curve, 500);
material = new v3d.MeshBasicMaterial({
color: 0x305000, depthWrite: false, transparent: true
});
mesh = new v3d.Mesh(geometry, material);
mesh.position.y = 0.1;
scene.add(mesh);
const funfairs = [];
//
geometry = new v3d.CylinderBufferGeometry(10, 10, 5, 15);
material = new v3d.MeshLambertMaterial({
color: 0xff8080,
//flatShading: true // Lambert does not support flat shading
});
mesh = new v3d.Mesh(geometry, material);
mesh.position.set(- 80, 10, - 70);
mesh.rotation.x = Math.PI / 2;
scene.add(mesh);
funfairs.push(mesh);
geometry = new v3d.CylinderBufferGeometry(5, 6, 4, 10);
material = new v3d.MeshLambertMaterial({
color: 0x8080ff,
//flatShading: true // Lambert does not support flat shading
});
mesh = new v3d.Mesh(geometry, material);
mesh.position.set(50, 2, 30);
scene.add(mesh);
funfairs.push(mesh);
//
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//
const position = new v3d.Vector3();
const tangent = new v3d.Vector3();
const lookAt = new v3d.Vector3();
let velocity = 0;
let progress = 0;
let prevTime = performance.now();
function render() {
const time = performance.now();
const delta = time - prevTime;
for (let i = 0; i < funfairs.length; i++) {
funfairs[i].rotation.y = time * 0.0004;
}
//
progress += velocity;
progress = progress % 1;
position.copy(curve.getPointAt(progress));
position.y += 0.3;
train.position.copy(position);
tangent.copy(curve.getTangentAt(progress));
velocity -= tangent.y * 0.0000001 * delta;
velocity = Math.max(0.00004, Math.min(0.0002, velocity));
train.lookAt(lookAt.copy(position).sub(tangent));
//
renderer.render(scene, camera);
prevTime = time;
}
renderer.setAnimationLoop(render);
</script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。