three.js之Group
Group
<canvas id="mainCanvas"></canvas>
<script type="importmap">
{
"imports": {
"three": "./js/build/three.module.js",
"three/addons/": "./js/jsm/"
}
}
</script>
<script type="module">
import * as THREE from "three";
import { TrackballControls } from "three/addons/controls/TrackballControls.js";
import { GUI } from "three/addons/libs/lil-gui.module.min.js";
import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addPlane } from "./init.js";
function init() {
const gui = new GUI();
const renderer = initRenderer("mainCanvas");
const scene = new THREE.Scene();
const camera = initPerspectiveCamera();
scene.add(camera);
const spotLight = initSpotLight();
scene.add(spotLight);
const ambientLight = initAmbientLight();
scene.add(ambientLight);
const plane = addPlane({ width: 1000, height: 100 });
scene.add(plane);
let sphere;
let cube;
let group;
let box;
let arrow;
const step = 0.03;
const controls = setupControls();
controls.redraw();
render();
function render() {
if (controls.grouping && controls.rotate) {
group.rotation.y += step;
}
if (controls.rotate && !controls.grouping) {
sphere.rotation.y += step;
cube.rotation.y += step;
}
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function setupControls() {
const controls = new (function () {
this.cubePosX = 0;
this.cubePosY = 3;
this.cubePosZ = 10;
this.spherePosX = 10;
this.spherePosY = 5;
this.spherePosZ = 0;
this.groupPosX = 10;
this.groupPosY = 5;
this.groupPosZ = 0;
this.grouping = false;
this.rotate = false;
this.groupScale = 1;
this.cubeScale = 1;
this.sphereScale = 1;
this.redraw = function () {
scene.remove(group);
sphere = createMesh(new THREE.SphereGeometry(5, 10, 10));
cube = createMesh(new THREE.BoxGeometry(6, 6, 6));
sphere.position.set(controls.spherePosX, controls.spherePosY, controls.spherePosZ);
sphere.scale.set(controls.sphereScale, controls.sphereScale, controls.sphereScale);
cube.position.set(controls.cubePosX, controls.cubePosY, controls.cubePosZ);
cube.scale.set(controls.cubeScale, controls.cubeScale, controls.cubeScale);
group = new THREE.Group();
group.position.set(controls.groupPosX, controls.groupPosY, controls.groupPosZ);
group.scale.set(controls.groupScale, controls.groupScale, controls.groupScale);
group.add(sphere);
group.add(cube);
scene.add(group);
controls.positionBoundingBox();
if (arrow) scene.remove(arrow);
arrow = new THREE.ArrowHelper(new THREE.Vector3(0, 1, 0), group.position, 10, 0x0000ff);
scene.add(arrow);
};
this.positionBoundingBox = function () {
scene.remove(box);
const cbox = new THREE.Box3().setFromObject(group);
const size = cbox.getSize(new THREE.Vector3());
const pos = cbox.getCenter(new THREE.Vector3());
box = new THREE.Mesh(
new THREE.BoxGeometry(size.x, size.y, size.z),
new THREE.MeshBasicMaterial({
color: 0x000000,
vertexColors: false,
wireframeLinewidth: 2,
wireframe: true,
})
);
box.position.copy(pos);
scene.add(box);
};
})();
const sphereFolder = gui.addFolder("sphere");
sphereFolder.add(controls, "spherePosX", -20, 20).onChange(function (e) {
sphere.position.x = e;
controls.positionBoundingBox();
controls.redraw();
});
sphereFolder.add(controls, "spherePosZ", -20, 20).onChange(function (e) {
sphere.position.z = e;
controls.positionBoundingBox();
controls.redraw();
});
sphereFolder.add(controls, "spherePosY", -20, 20).onChange(function (e) {
sphere.position.y = e;
controls.positionBoundingBox();
controls.redraw();
});
sphereFolder.add(controls, "sphereScale", 0, 3).onChange(function (e) {
sphere.scale.set(e, e, e);
controls.positionBoundingBox();
controls.redraw();
});
const cubeFolder = gui.addFolder("cube");
cubeFolder.add(controls, "cubePosX", -20, 20).onChange(function (e) {
cube.position.x = e;
controls.positionBoundingBox();
controls.redraw();
});
cubeFolder.add(controls, "cubePosZ", -20, 20).onChange(function (e) {
cube.position.z = e;
controls.positionBoundingBox();
controls.redraw();
});
cubeFolder.add(controls, "cubePosY", -20, 20).onChange(function (e) {
cube.position.y = e;
controls.positionBoundingBox();
controls.redraw();
});
cubeFolder.add(controls, "cubeScale", 0, 3).onChange(function (e) {
cube.scale.set(e, e, e);
controls.positionBoundingBox();
controls.redraw();
});
const groupFolder = gui.addFolder("group");
groupFolder.add(controls, "groupPosX", -20, 20).onChange(function (e) {
group.position.x = e;
controls.positionBoundingBox();
controls.redraw();
});
groupFolder.add(controls, "groupPosZ", -20, 20).onChange(function (e) {
group.position.z = e;
controls.positionBoundingBox();
controls.redraw();
});
groupFolder.add(controls, "groupPosY", -20, 20).onChange(function (e) {
group.position.y = e;
controls.positionBoundingBox();
controls.redraw();
});
groupFolder.add(controls, "groupScale", 0, 3).onChange(function (e) {
group.scale.set(e, e, e);
controls.positionBoundingBox();
controls.redraw();
});
gui.add(controls, "grouping");
gui.add(controls, "rotate");
return controls;
}
}
init();
function createMesh(geom) {
const meshMaterial = new THREE.MeshNormalMaterial();
meshMaterial.side = THREE.DoubleSide;
const plane = new THREE.Mesh(geom, meshMaterial);
return plane;
}
</script>
合集:
three.js基础
分类:
javascript
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix