SkinnedMesh.js 3.6 KB
Newer Older
R
Rich Harris 已提交
1 2 3 4 5 6
import { Mesh } from './Mesh';
import { Vector4 } from '../math/Vector4';
import { Skeleton } from './Skeleton';
import { Bone } from './Bone';
import { Matrix4 } from '../math/Matrix4';

7 8
/**
 * @author mikael emtinger / http://gomo.se/
A
alteredq 已提交
9
 * @author alteredq / http://alteredqualia.com/
10
 * @author ikerr / http://verold.com
11 12
 */

M
Mr.doob 已提交
13
function SkinnedMesh( geometry, material, useVertexTexture ) {
14

R
Rich Harris 已提交
15
	Mesh.call( this, geometry, material );
16

17 18
	this.type = 'SkinnedMesh';

19
	this.bindMode = "attached";
R
Rich Harris 已提交
20 21
	this.bindMatrix = new Matrix4();
	this.bindMatrixInverse = new Matrix4();
22 23 24 25 26 27 28 29 30 31

	// init bones

	// TODO: remove bone creation as there is no reason (other than
	// convenience) for THREE.SkinnedMesh to do this.

	var bones = [];

	if ( this.geometry && this.geometry.bones !== undefined ) {

32
		var bone, gbone;
33

G
gero3 已提交
34
		for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
35

36
			gbone = this.geometry.bones[ b ];
37

38
			bone = new Bone();
39
			bones.push( bone );
40

41
			bone.name = gbone.name;
42 43 44
			bone.position.fromArray( gbone.pos );
			bone.quaternion.fromArray( gbone.rotq );
			if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );
45 46

		}
47

G
gero3 已提交
48
		for ( var b = 0, bl = this.geometry.bones.length; b < bl; ++ b ) {
49

50
			gbone = this.geometry.bones[ b ];
51

52 53
			if ( gbone.parent !== - 1 && gbone.parent !== null &&
					bones[ gbone.parent ] !== undefined ) {
54 55 56

				bones[ gbone.parent ].add( bones[ b ] );

57
			} else {
58

59
				this.add( bones[ b ] );
60

61
			}
62

M
Mr.doob 已提交
63
		}
64

65
	}
66

67
	this.normalizeSkinWeights();
68

69
	this.updateMatrixWorld( true );
R
Rich Harris 已提交
70
	this.bind( new Skeleton( bones, undefined, useVertexTexture ), this.matrixWorld );
71

M
Mr.doob 已提交
72
}
73

R
Rich Harris 已提交
74
SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {
75

R
Rich Harris 已提交
76
	constructor: SkinnedMesh,
77

78 79
	isSkinnedMesh: true,

M
Mr.doob 已提交
80
	bind: function( skeleton, bindMatrix ) {
81

M
Mr.doob 已提交
82
		this.skeleton = skeleton;
83

M
Mr.doob 已提交
84
		if ( bindMatrix === undefined ) {
M
Mr.doob 已提交
85

M
Mr.doob 已提交
86
			this.updateMatrixWorld( true );
87

M
Mr.doob 已提交
88
			this.skeleton.calculateInverses();
89

M
Mr.doob 已提交
90
			bindMatrix = this.matrixWorld;
91

M
Mr.doob 已提交
92
		}
93

M
Mr.doob 已提交
94 95
		this.bindMatrix.copy( bindMatrix );
		this.bindMatrixInverse.getInverse( bindMatrix );
96

M
Mr.doob 已提交
97
	},
98

M
Mr.doob 已提交
99
	pose: function () {
100

M
Mr.doob 已提交
101
		this.skeleton.pose();
102

M
Mr.doob 已提交
103
	},
104

M
Mr.doob 已提交
105
	normalizeSkinWeights: function () {
106

107
		if ( this.geometry && this.geometry.isGeometry ) {
108

M
Mr.doob 已提交
109
			for ( var i = 0; i < this.geometry.skinWeights.length; i ++ ) {
110

M
Mr.doob 已提交
111
				var sw = this.geometry.skinWeights[ i ];
112

M
Mr.doob 已提交
113
				var scale = 1.0 / sw.lengthManhattan();
114

M
Mr.doob 已提交
115
				if ( scale !== Infinity ) {
116

M
Mr.doob 已提交
117
					sw.multiplyScalar( scale );
118

M
Mr.doob 已提交
119 120 121 122 123
				} else {

					sw.set( 1, 0, 0, 0 ); // do something reasonable

				}
124

125
			}
126

127
		} else if ( this.geometry && this.geometry.isBufferGeometry ) {
128

R
Rich Harris 已提交
129
			var vec = new Vector4();
130

M
Mr.doob 已提交
131
			var skinWeight = this.geometry.attributes.skinWeight;
132

M
Mr.doob 已提交
133
			for ( var i = 0; i < skinWeight.count; i ++ ) {
134

M
Mr.doob 已提交
135 136 137 138
				vec.x = skinWeight.getX( i );
				vec.y = skinWeight.getY( i );
				vec.z = skinWeight.getZ( i );
				vec.w = skinWeight.getW( i );
139

M
Mr.doob 已提交
140
				var scale = 1.0 / vec.lengthManhattan();
141

M
Mr.doob 已提交
142
				if ( scale !== Infinity ) {
143

M
Mr.doob 已提交
144
					vec.multiplyScalar( scale );
145

M
Mr.doob 已提交
146
				} else {
147

M
Mr.doob 已提交
148
					vec.set( 1, 0, 0, 0 ); // do something reasonable
149

M
Mr.doob 已提交
150
				}
151

M
Mr.doob 已提交
152
				skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w );
153

M
Mr.doob 已提交
154
			}
155 156

		}
157

M
Mr.doob 已提交
158
	},
159

M
Mr.doob 已提交
160
	updateMatrixWorld: function( force ) {
161

R
Rich Harris 已提交
162
		Mesh.prototype.updateMatrixWorld.call( this, true );
163

M
Mr.doob 已提交
164
		if ( this.bindMode === "attached" ) {
165

M
Mr.doob 已提交
166
			this.bindMatrixInverse.getInverse( this.matrixWorld );
167

M
Mr.doob 已提交
168
		} else if ( this.bindMode === "detached" ) {
169

M
Mr.doob 已提交
170
			this.bindMatrixInverse.getInverse( this.bindMatrix );
171

M
Mr.doob 已提交
172
		} else {
173

M
Mr.doob 已提交
174
			console.warn( 'THREE.SkinnedMesh unrecognized bindMode: ' + this.bindMode );
175

M
Mr.doob 已提交
176
		}
177

M
Mr.doob 已提交
178
	},
179

M
Mr.doob 已提交
180
	clone: function() {
181

182
		return new this.constructor( this.geometry, this.material, this.skeleton.useVertexTexture ).copy( this );
183

M
Mr.doob 已提交
184
	}
M
Mr.doob 已提交
185

M
Mr.doob 已提交
186
} );
R
Rich Harris 已提交
187 188


189
export { SkinnedMesh };