Skip to content

Commit 9d30556

Browse files
committed
Attribute
1 parent 3e86b1d commit 9d30556

File tree

2 files changed

+90
-9
lines changed

2 files changed

+90
-9
lines changed

public/vite.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/main.js

Lines changed: 90 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { CopyShader } from "./jsm/shaders/CopyShader"
2929
import { VerticalBlurShader } from "./jsm/shaders/VerticalBlurShader"
3030
import { BufferGeometry } from "./core/BufferGeometry"
3131
import { MeshStandardMaterial } from "./materials/MeshStandardMaterial"
32-
import { BufferAttribute } from "./core/BufferAttribute"
32+
import { BufferAttribute, Float32BufferAttribute, Uint16BufferAttribute } from "./core/BufferAttribute"
3333
import { SphereGeometry } from "./geometries/SphereGeometry"
3434
import { MeshPhysicalMaterial } from "./materials/MeshPhysicalMaterial"
3535
import { TextureLoader } from "./loaders/TextureLoader"
@@ -56,6 +56,11 @@ import { RectAreaLight } from "./lights/RectAreaLight"
5656

5757
import { environments } from "./environments.js"
5858
import { BokehPass } from "./jsm/postprocessing/BokehPass"
59+
import { MeshBasicMaterial } from "./materials/MeshBasicMaterial"
60+
import { CylinderGeometry } from "./geometries/CylinderGeometry"
61+
import { Bone } from "./objects/Bone"
62+
import { SkinnedMesh } from "./objects/SkinnedMesh"
63+
import { Skeleton } from "./objects/Skeleton"
5964

6065
const loadingManager = new LoadingManager()
6166
loadingManager.onProgress = (url, loaded, total) => {
@@ -276,6 +281,13 @@ export class App {
276281
vnh
277282
vth
278283

284+
sizing = {
285+
halfHeight: 2.5,
286+
segmentHeight: 1.0,
287+
segments: 5,
288+
}
289+
skeleton
290+
279291
constructor() {
280292
this.createRenderer()
281293
this.createScene()
@@ -284,10 +296,11 @@ export class App {
284296
this.createClock()
285297
this.createControls()
286298
this.createLights()
287-
// this.setupCube()
288-
this.loadTexure()
289-
this.loadMaterial()
290-
this.loadModel()
299+
// this.createCube()
300+
this.createCylinder()
301+
// this.loadTexure()
302+
// this.loadMaterial()
303+
// this.loadModel()
291304
// this.loadGLTF()
292305
// this.loadHair()
293306
// this.loadJSON()
@@ -410,13 +423,72 @@ export class App {
410423
this.controls.screenSpacePanning = true
411424
}
412425

413-
setupCube() {
426+
createCube() {
414427
const geometry = new BoxGeometry(1, 1, 1)
415428
const material = new MeshPhongMaterial({ color: 0x00ff00 })
416429
this.cube = new Mesh(geometry, material)
417430
this.scene.add(this.cube)
418431
}
419432

433+
createCylinder() {
434+
const geometry = new CylinderGeometry(5, 5, 5, 5, this.sizing.segments, true)
435+
const material = new MeshBasicMaterial({
436+
color: 0x156289,
437+
wireframe: true,
438+
skinning: true,
439+
})
440+
441+
// 3. Tạo xương (bones) theo segment
442+
const bones = []
443+
let prevBone = null
444+
445+
for (let i = 0; i <= this.sizing.segments; i++) {
446+
const bone = new Bone()
447+
bone.position.y = i * this.sizing.segmentHeight
448+
if (prevBone) {
449+
prevBone.add(bone)
450+
}
451+
bones.push(bone)
452+
prevBone = bone
453+
}
454+
455+
// 4. Tạo skin indices và skin weights thủ công
456+
const position = geometry.attributes.position
457+
const vertex = new Vector3()
458+
459+
const skinIndices = []
460+
const skinWeights = []
461+
462+
for (let i = 0; i < position.count; i++) {
463+
vertex.fromBufferAttribute(position, i)
464+
465+
// Chuyển vertex.y về hệ tọa độ 0 -> chiều cao hình trụ
466+
const y = vertex.y + this.sizing.halfHeight
467+
468+
const skinIndex = Math.floor(y / this.sizing.segmentHeight)
469+
const skinWeight = (y % this.sizing.segmentHeight) / this.sizing.segmentHeight
470+
471+
// Mỗi vertex chịu ảnh hưởng bởi 2 bone liền kề
472+
skinIndices.push(skinIndex, skinIndex + 1, 0, 0)
473+
skinWeights.push(1 - skinWeight, skinWeight, 0, 0)
474+
}
475+
476+
geometry.setAttribute("skinIndex", new Uint16BufferAttribute(skinIndices, 4))
477+
geometry.setAttribute("skinWeight", new Float32BufferAttribute(skinWeights, 4))
478+
479+
// 5. Tạo SkinnedMesh và Skeleton
480+
const mesh = new SkinnedMesh(geometry, material)
481+
this.skeleton = new Skeleton(bones)
482+
483+
// Thêm xương gốc vào mesh
484+
mesh.add(bones[0])
485+
486+
// Gắn skeleton vào mesh
487+
mesh.bind(this.skeleton)
488+
489+
this.scene.add(mesh)
490+
}
491+
420492
createLights() {
421493
// const ambientLight = new AmbientLight(0xffffff, 0.63)
422494
// this.scene.add(ambientLight)
@@ -1418,6 +1490,12 @@ export class App {
14181490
this.meshFolder = this.gui.addFolder("Mesh")
14191491
this.meshFolder.close()
14201492
// this.gui.close()
1493+
1494+
const skeletonFolder = this.gui.addFolder("Skeleton")
1495+
skeletonFolder.close()
1496+
skeletonFolder.add(this.sizing, "halfHeight", -10, 10, 0.01).name("halfHeight")
1497+
skeletonFolder.add(this.sizing, "segmentHeight", -10, 10, 0.01).name("segmentHeight")
1498+
skeletonFolder.add(this.sizing, "segments", -10, 10, 0.01).name("segments")
14211499
}
14221500

14231501
addHelpers() {
@@ -1525,7 +1603,7 @@ export class App {
15251603

15261604
getEnvironmentTexture(environment) {
15271605
const { id, path } = environment
1528-
// neutral (THREE.RoomEnvironment)
1606+
// neutral (RoomEnvironment)
15291607
// if (id === "neutral") {
15301608
// return Promise.resolve({ envMap: this.neutralEnvironment })
15311609
// }
@@ -1617,9 +1695,13 @@ export class App {
16171695
// // Rotate the cube
16181696
// this.cube.rotation.x += 0.01
16191697
// this.cube.rotation.y += 0.01
1698+
if (this.skeleton) {
1699+
this.skeleton.bones[0].rotation.x = Math.sin(Date.now() * 0.001) * 0.3
1700+
this.skeleton.bones[1].rotation.x = Math.sin(Date.now() * 0.001 + 1) * 0.5
1701+
}
16201702

1703+
this.controls.update()
16211704
if (this.controls) {
1622-
this.controls.update()
16231705
}
16241706

16251707
if (this.state.postProcessing) {

0 commit comments

Comments
 (0)