参考https://threejs.org/manual/#en/responsive和https://threejs.org/manual/#en/scenegraph
前者主要是说怎样创建一个响应式的three.js应用,就是在变化屏幕大小的时候,画面不会畸形。后者是再说,怎么组合小的组件变成一个大的组件(依赖于一个空组件object3D)
下面是示例代码:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
html, body {
margin: 0;
height: 100%;
}
#c {
width: 100%;
height: 100%;
display: block;
}
</style>
</head>
<body>
<script type="module" src="/main.js"></script>
<canvas id="c"></canvas>
<div id="info"></div>
</body>
</html>
main.js
import * as THREE from 'three';
import {FontLoader} from 'three/addons/loaders/FontLoader.js';
import {TextGeometry} from 'three/addons/geometries/TextGeometry.js';
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({antialias: true, canvas});
const fov = 40;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 120;
const scene = new THREE.Scene();
scene.background = new THREE.Color('white');
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
scene.add(light);
}
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(1, -2, -4);
scene.add(light);
}
const objects = [];
const spread = 15;
function addObject(x, y, obj) {
obj.position.x = x * spread;
obj.position.y = y * spread;
scene.add(obj);
objects.push(obj);
}
const myObjs = new Map();
function addMyObj(x, y, obj, objName) {
obj.position.x = x * spread;
obj.position.y = y * spread;
// scene.add(obj);
myObjs.set(objName, obj)
}
function makeObject3D(x, y, objName) {
const obj3D = new THREE.Object3D();
obj3D.position.x = x * spread;
obj3D.position.y = y * spread;
myObjs.set(objName, obj3D)
scene.add(obj3D);
}
function getObj(objName) {
return myObjs.get(objName)
}
function createMaterial() {
const material = new THREE.MeshPhongMaterial({
side: THREE.DoubleSide,
});
const hue = Math.random();
const saturation = 1;
const luminance = .5;
material.color.setHSL(hue, saturation, luminance);
return material;
}
function addSolidGeometry(x, y, geometry) {
const mesh = new THREE.Mesh(geometry, createMaterial());
addObject(x, y, mesh);
}
function addMySolidGeometry(x, y, geometry, objName) {
const mesh = new THREE.Mesh(geometry, createMaterial());
addMyObj(x, y, mesh, objName);
}
function addLineGeometry(x, y, geometry) {
const material = new THREE.LineBasicMaterial({color: 0x000000});
const mesh = new THREE.LineSegments(geometry, material);
addObject(x, y, mesh);
}
{
const width = 9;
const height = 9;
const widthSegments = 2;
const heightSegments = 2;
addSolidGeometry(-5.5, 2, new THREE.PlaneGeometry(width, height, widthSegments, heightSegments));
}
{
const shape = new THREE.Shape();
const x = -2.5;
const y = -5;
shape.moveTo(x + 2.5, y + 2.5);
shape.bezierCurveTo(x + 2.5, y + 2.5, x + 2, y, x, y);
shape.bezierCurveTo(x - 3, y, x - 3, y + 3.5, x - 3, y + 3.5);
shape.bezierCurveTo(x - 3, y + 5.5, x - 1.5, y + 7.7, x + 2.5, y + 9.5);
shape.bezierCurveTo(x + 6, y + 7.7, x + 8, y + 4.5, x + 8, y + 3.5);
shape.bezierCurveTo(x + 8, y + 3.5, x + 8, y, x + 5, y);
shape.bezierCurveTo(x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5);
addSolidGeometry(-4.5, 2, new THREE.ShapeGeometry(shape));
}
{
const radius = 7;
const widthSegments = 12;
const heightSegments = 8;
addSolidGeometry(-3.5, 2, new THREE.SphereGeometry(radius, widthSegments, heightSegments));
}
{
const loader = new FontLoader();
// promisify font loading
function loadFont(url) {
return new Promise((resolve, reject) => {
loader.load(url, resolve, undefined, reject);
});
}
async function doit() {
const font = await loadFont('helvetiker_regular.typeface.json');
const geometry = new TextGeometry('three.js', {
font: font,
size: 3.0,
height: .2,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.15,
bevelSize: .3,
bevelSegments: 5,
});
const mesh = new THREE.Mesh(geometry, createMaterial());
geometry.computeBoundingBox();
geometry.boundingBox.getCenter(mesh.position).multiplyScalar(-1);
const parent = new THREE.Object3D();
parent.add(mesh);
addObject(-2.5, 2, parent);
}
doit();
}
{
const radius = 3.5;
const tube = 1.5;
const radialSegments = 8;
const tubularSegments = 64;
const p = 2;
const q = 3;
addSolidGeometry(-1.5, 2, new THREE.TorusKnotGeometry(radius, tube, tubularSegments, radialSegments, p, q));
}
{
const width = 8;
const height = 8;
const depth = 8;
const thresholdAngle = 15;
addLineGeometry(-0.5, 2, new THREE.EdgesGeometry(
new THREE.BoxGeometry(width, height, depth),
thresholdAngle));
}
{
const width = 8;
const height = 8;
const depth = 8;
addLineGeometry(0.5, 2, new THREE.WireframeGeometry(new THREE.BoxGeometry(width, height, depth)));
}
{
makeObject3D(0, 0, 'system')
}
{
const objName = 'ground'
const width = 159;
const height = 159;
const widthSegments = 2;
const heightSegments = 2;
addMySolidGeometry(0, -1, new THREE.PlaneGeometry(width, height, widthSegments, heightSegments), objName);
const ground = getObj(objName)
ground.rotation.x = Math.PI * -.5;
const system = getObj('system')
system.add(ground)
}
// const groundGeometry = new THREE.PlaneGeometry(50, 50);
// const groundMaterial = new THREE.MeshPhongMaterial({color: 0xCC8866});
// const groundMesh = new THREE.Mesh(groundGeometry, groundMaterial);
// groundMesh.rotation.x = Math.PI * -.5;
// groundMesh.receiveShadow = true;
// scene.add(groundMesh);
{
const objName = 'player1'
const shape = new THREE.Shape();
const x = -2.5;
const y = -5;
shape.moveTo(x + 2.5, y + 2.5);
shape.bezierCurveTo(x + 2.5, y + 2.5, x + 2, y, x, y);
shape.bezierCurveTo(x - 3, y, x - 3, y + 3.5, x - 3, y + 3.5);
shape.bezierCurveTo(x - 3, y + 5.5, x - 1.5, y + 7.7, x + 2.5, y + 9.5);
shape.bezierCurveTo(x + 6, y + 7.7, x + 8, y + 4.5, x + 8, y + 3.5);
shape.bezierCurveTo(x + 8, y + 3.5, x + 8, y, x + 5, y);
shape.bezierCurveTo(x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5);
addMySolidGeometry(-5, -0.5, new THREE.ShapeGeometry(shape), objName);
const player1 = getObj(objName)
const system = getObj('system')
system.add(player1)
}
{
const objName = 'player2'
const shape = new THREE.Shape();
const x = -2.5;
const y = -5;
shape.moveTo(x + 2.5, y + 2.5);
shape.bezierCurveTo(x + 2.5, y + 2.5, x + 2, y, x, y);
shape.bezierCurveTo(x - 3, y, x - 3, y + 3.5, x - 3, y + 3.5);
shape.bezierCurveTo(x - 3, y + 5.5, x - 1.5, y + 7.7, x + 2.5, y + 9.5);
shape.bezierCurveTo(x + 6, y + 7.7, x + 8, y + 4.5, x + 8, y + 3.5);
shape.bezierCurveTo(x + 8, y + 3.5, x + 8, y, x + 5, y);
shape.bezierCurveTo(x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5);
addMySolidGeometry(5, -0.5, new THREE.ShapeGeometry(shape), objName);
const player2 = getObj(objName)
player2.rotation.x = Math.PI * -1;
const system = getObj('system')
system.add(player2)
}
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render(time) {
time *= 0.001;
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
objects.forEach((obj, ndx) => {
const speed = .1 + ndx * .05;
const rot = time * speed;
obj.rotation.x = rot;
obj.rotation.y = rot;
});
const system = getObj('system')
system.rotation.y = time * 0.05;
const player1 = getObj('player1')
player1.rotation.x = time * 0.5
player1.rotation.y = time * 0.5
player1.position.x += 0.01
const player2 = getObj('player2')
player2.rotation.x = time * 0.5
player2.rotation.y = time * 0.5
player2.position.x -= 0.01
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
下一步应该是,怎样面向对象开发three.js应用,如何去模块化。
标签:bezierCurveTo,const,04,THREE,Three,shape,new,js,2.5 From: https://www.cnblogs.com/xkxf/p/17367512.html