My Bumblebee Mara no longer works on https://codepen.io/hofk/pen/eWdZMb ,
because the old Geometry removed with r125 is used.
UPDATE January 21 - I got it to work on codepen.
On my page the old variant remains (see Mara above) and the new one can reached here under Mara.
Decisive was my sloppiness, I used twice the same data fields for skin with push. You can see it below.
I try to change it to BufferGeometry and have a display error. I cannot find the cause.
For a better search I only created the body (it works correctly) and a limb ( that’s where the error is).
Actually boneLimbSegCount = 3;
then the representation is completely meaningless.
With boneLimbSegCount = 32;
it appears partly as expected.
I have tried different variations, so far without success.
See Skeleton_x
= 3
= 32
<!DOCTYPE html>
<!-- https://discourse.threejs.org/t/problem-porting-skinnedmesh-from-old-geometry-to-buffergeometry/33748 -->
<head> <meta charset="utf-8">
<title> Skeleton_x </title>
</head>
<body>
<div style="position: absolute; top: 20px; left: 25px; text-align:left;">
<div > Skeleton </br>
<label><input type="checkbox" id="move" > move </label>
</div>
</body>
<script type ="module">
// @author hofk
import * as THREE from '../jsm/three.module.136.js';
import { mergeBufferGeometries, mergeBufferAttributes } from '../jsm/BufferGeometryUtils.136.js'
import {OrbitControls} from '../jsm/OrbitControls.136.js';
document.getElementById('move').checked = true;
window.addEventListener( 'resize', function ( ) {
camera.aspect = window.innerWidth / window.innerHeight;
renderer.setSize( window.innerWidth, window.innerHeight ); }, false
);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 20000 );
camera.position.set(-200,100,300);
const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xbbffcc, 1 );
const container = document.createElement('div');
document.body.appendChild(container);
container.appendChild(renderer.domElement);
new OrbitControls( camera, renderer.domElement );
const light1 = new THREE.PointLight(0xffffff,1,0);
const light2 = light1.clone();
light1.position.set( -100, 300, 1000 );
light2.position.set( 0, 800, -500 );
scene.add(light1);
scene.add(light2);
const clock = new THREE.Clock( true );
const materialHead = new THREE.MeshPhongMaterial( { color: 0x997711, emissive: 0xaa6600, wireframe: true } );
const materialBody = new THREE.MeshBasicMaterial( { color: 0x897429, wireframe: true } );
const materialLimb = new THREE.MeshPhongMaterial( { color: 0x896215, emissive: 0xa96415, wireframe: true } );
const geometryNeck = new THREE.OctahedronBufferGeometry( 10, 2 );
const bodyHeight = 80;
const boneBodyCount = 4;
const boneBodySegCount = 4;
const bodySegHeightCount = boneBodySegCount * boneBodyCount;
const boneBodyHeight = bodyHeight / boneBodyCount;
const outlineBody = [
[0.01,-bodyHeight ],[10,-79.75],[20,-79.25],[30,-76],[35,-75],[40,-70],[42,-65],[44,-60],[45,-55],[45,-50],[44,-45],[41,-35],[36,-27],[31,-20],[17.5,-10],[10,0] // -bodyHeight --> 0
];
const pointsBody = [];
for ( let i = 0; i < outlineBody.length ; i++ ) {
pointsBody.push(new THREE.Vector2( outlineBody[ i ][ 0 ], outlineBody[ i ][ 1 ] ) );
}
const rSegmentCount = 18;
const geometryBody = new THREE.LatheBufferGeometry( pointsBody, rSegmentCount );
const vertex = new THREE.Vector3( );
const skinIndices = [];
const skinWeights = [];
const positionBody = geometryBody.attributes.position;
for ( let i = 0; i < positionBody.count; i ++ ) {
vertex.fromBufferAttribute( positionBody, i );
const skinIndex = boneBodyCount - 1 - Math.floor( ( i % bodySegHeightCount) / boneBodySegCount );
const skinWeight = ( ( bodyHeight - vertex.y ) % boneBodyHeight ) / boneBodyHeight;
skinIndices.push( skinIndex, skinIndex + 1, 0, 0 );
skinWeights.push( 1 - skinWeight, skinWeight , 0, 0 );
}
geometryBody.setAttribute( 'skinIndex', new THREE.Uint16BufferAttribute( skinIndices, 4 ) );
geometryBody.setAttribute( 'skinWeight', new THREE.Float32BufferAttribute( skinWeights, 4 ) );
const meshBody = new THREE.SkinnedMesh( geometryBody, materialBody );
// .... limb ....
const limbRadius = 3;
const limbHeight = 60;
const boneLimbCount = 3;
const boneLimbSegCount = 32; // original 3; // !!!!!!!
const limbRadSegCount = 0.5 * rSegmentCount;
const limbHeightSegCount = boneLimbSegCount * boneLimbCount;
const boneLimbHeight = limbHeight / boneLimbCount;
const limbHalfHeight = limbHeight * 0.5;
const openEnded = false;
const cylinderGeometry = new THREE.CylinderBufferGeometry( limbRadius, limbRadius, limbHeight, limbRadSegCount, limbHeightSegCount, openEnded );
const sphereGeometrie = new THREE.SphereBufferGeometry( 7, 16, 16 );
sphereGeometrie.translate ( 0, limbHalfHeight + boneLimbHeight / 4, 0 );
const geos = [ cylinderGeometry, sphereGeometrie ]
const geometryLimb = mergeBufferGeometries( geos );
const positionLimb = geometryLimb.attributes.position;
for ( let i = 0; i < positionLimb.count; i ++ ) {
vertex.fromBufferAttribute( positionLimb, i );
const y = vertex.y + limbHalfHeight;
const skinIndex = Math.floor( y / limbHeight );
const skinWeight = ( y % limbHeight ) / limbHeight;
skinIndices.push( skinIndex, skinIndex + 1, 0, 0 );
skinWeights.push( 1 - skinWeight, skinWeight, 0, 0 );
}
geometryLimb.setAttribute( 'skinIndex', new THREE.Uint16BufferAttribute( skinIndices, 4 ) );
geometryLimb.setAttribute( 'skinWeight', new THREE.Float32BufferAttribute( skinWeights, 4 ) );
const meshLimb = new THREE.SkinnedMesh( geometryLimb, materialLimb );
const bonesBody = createBones( 0 ,-boneBodyHeight, boneBodyCount);
const bonesLimb = createBones( -limbHalfHeight, boneLimbHeight, boneLimbCount );
const meshNeck = new THREE.Mesh( geometryNeck, materialHead );
meshBody.add( meshNeck );
meshLimb.rotation.z = 1.57;
meshLimb.position.x = -limbHalfHeight;
const skeletonBody = new THREE.Skeleton( bonesBody );
meshBody.add( bonesBody[ 0 ] );
meshBody.bind( skeletonBody );
scene.add( meshBody );
const skeletonHelperBody = new THREE.SkeletonHelper( meshBody );
scene.add( skeletonHelperBody );
const skeletonLimb = new THREE.Skeleton( bonesLimb );
meshLimb.add( bonesLimb[ 0 ] );
meshLimb.bind( skeletonLimb );
meshBody.add( meshLimb );
const skeletonHelperLimb = new THREE.SkeletonHelper( meshLimb ); ;
scene.add( skeletonHelperLimb );
let time;
animate();
//...............
function createBones( positionY, height, boneCount ) {
const bones = [];
const basicBone = new THREE.Bone();
bones.push( basicBone );
basicBone.position.y = positionY;
let prevBone = basicBone;
for ( let i = 1; i < boneCount+1; i ++ ) {
const bone = prevBone.clone();
bone.position.y = height;
bones.push( bone );
prevBone.add( bone );
prevBone = bone;
}
return bones;
}
function animate() {
requestAnimationFrame( animate );
time = clock.getElapsedTime(); //Date.now() * 0.001;
if ( document.getElementById( "move" ).checked) {
for ( var i = 1; i < meshBody.skeleton.bones.length; i ++ ) {
meshBody.skeleton.bones[ i ].rotation.z = 0.2 * Math.sin( 1.8 * time ) / meshBody.skeleton.bones.length;
}
for ( var i = 0; i < boneLimbCount + 1; i ++ ) {
meshLimb.skeleton.bones[ i ].rotation.x = 0.6 * Math.cos( 1.2 * time ) / boneLimbCount;
meshLimb.skeleton.bones[ i ].rotation.z = 0.6 * Math.sin( 1.2 * time ) / boneLimbCount;
}
meshNeck.rotation.x = -0.20 * ( 0.8 + Math.sin( -1.57 + 1.2 * time ) );
meshNeck.rotation.y = -0.15 * ( 0.6 + Math.sin( -1.57 + 1.9 * time ) );
meshBody.rotation.x = 0.2;
}
renderer.render( scene, camera );
}
</script>
</html>