Source file: /examples/mesh/skinning.js
import Stats from "stats.js";
import {
WebGLRenderer,
PerspectiveProjection,
GLTFLoader,
Camera,
Quaternion,
SkeletonHelper,
MeshMaterial3D,
WebGLRenderDevice,
Bone3D,
Object3D,
MeshMaterialPlugin,
SkeletonHelperPlugin,
BasicMaterial,
CanvasTarget,
CameraPlugin
} from 'webgllis';
// performance monitor
const stats = new Stats()
stats.showPanel(1)
document.body.append(stats.dom)
stats.dom.removeAttribute('style')
stats.dom.classList.add('performance-monitor')
/**@type {Object3D[]} */
const objects = []
const canvas = document.createElement('canvas')
const renderTarget = new CanvasTarget(canvas)
const renderDevice = new WebGLRenderDevice(canvas,{
depth:true
})
const renderer = new WebGLRenderer({
plugins:[
new MeshMaterialPlugin(),
new CameraPlugin(),
new SkeletonHelperPlugin()
]
})
const camera = new Camera(renderTarget)
const loader = new GLTFLoader()
const material = new BasicMaterial()
loader.asyncLoad({
paths: ["/assets/models/gltf/pirate_girl/index.gltf"]
}).then((model) => {
const entityMap = new Map()
const clone = model.clone(entityMap)
// NOTE: Maybe make this internal to the loader?
clone.traverseDFS((object) => {
if (object instanceof MeshMaterial3D) {
object.material = material
if(object.skin){
object.skin.bones = object.skin.bones.map((bone) => entityMap.get(bone))
}
}
return true
})
objects.push(clone)
clone.traverseDFS((item) => {
if (item instanceof MeshMaterial3D && item.skin) {
const root = item.skin.bones[0]
if (root instanceof Bone3D) {
const helper = new SkeletonHelper(root, item)
objects.push(helper)
return false
}
}
return true
})
})
camera.transform.position.z = 5
camera.transform.position.y = 2
if (camera.projection instanceof PerspectiveProjection) {
camera.projection.fov = Math.PI / 180 * 120
camera.projection.aspect = innerWidth / innerHeight
}
const rotation = Quaternion.fromEuler(0, Math.PI / 1000, 0)
document.body.append(canvas)
updateView()
addEventListener("resize", updateView)
requestAnimationFrame(update)
function update() {
stats.begin()
if (objects[0]) {
objects[0].traverseDFS((mesh)=>{
if(mesh instanceof MeshMaterial3D){
mesh.transform.orientation.multiply(rotation)
}
return true
})
objects[0].traverseDFS((bone)=>{
if(bone instanceof Bone3D){
if(
bone.name === 'metarig.001_thigh.L' ||
bone.name === 'metarig.001_shin.L'
){
bone.transform.orientation.multiply(Quaternion.fromEuler(Math.PI / 120,0, 0))
}
if(
bone.name === 'metarig.001_thigh.R' ||
bone.name === 'metarig.001_shin.R'
){
bone.transform.orientation.multiply(Quaternion.fromEuler(-Math.PI / 120,0, 0))
}
}
return true
})
}
if (objects.length > 0) {
renderer.render([...objects, camera], renderDevice, )
}
stats.end()
requestAnimationFrame(update)
}
function updateView() {
canvas.style.width = innerWidth + "px"
canvas.style.height = innerHeight + "px"
canvas.width = innerWidth * devicePixelRatio
canvas.height = innerHeight * devicePixelRatio
if (camera.projection instanceof PerspectiveProjection) {
camera.projection.aspect = innerWidth / innerHeight
}
}