Allow creation of custom SkinnedSubGeometry

Software: Away3D 4.x

Avatar
Huck, Jr. Member
Posted: 14 January 2012 07:56 PM   Total Posts: 45

Hi,

This should be simple to implement. Pretty much all 3D engines allow users to create not only custom meshes (vertex, normal, uv and indices) but also the bone binding info (joint weights and indices). These custom meshes can then be animated programmatically by applying user transformations on the bones, using for example inverse kinematics.

Away3D currently seems to prevent modification of bone binding data by applying the “arcane” modifier on SkinnedSubGeometry.updateJointIndexData and SkinnedSubGeometry.updateJointWeightsData.

It would be a nice feature to add if you could change this to expose these methods publicly so we can use them if we need to. Would also be nice to expose the ability to apply user transformations on the skeleton bones, to allow users to animate with inverse kinematics and other procedural approach.

would be greatly appreciated smile

thanks for the great work!

   

Avatar
Huck, Jr. Member
Posted: 14 January 2012 09:13 PM   Total Posts: 45   [ # 1 ]

note in case it can help, flare3D v2 has 2 nice examples that allow to do this:

Test14_CustomMesh3D.as shows how a custom mesh can be created (notice how bone weights and indices can be set by the user) and Test20_ControlBones.as shows how to control bones manually.

would be REALLY nice if away3d could implement this features.

thanks guys!! smile

 

   

Avatar
Huck, Jr. Member
Posted: 14 January 2012 10:23 PM   Total Posts: 45   [ # 2 ]

please note that in the meanwhile i found this post here:

[forum prevents me from posting the link, so here is a hacked form]
forum thread: 771

As mentioned in one of the posts, i tried to build a custom animator class and with some fiddling around managed to get some basic custom animation going.

Although the animation system is powerful, i also see it as very complex for the newcommer, perhaps it might be good to create a “custom animator” class for users to use.

I will try to improve mine and then i will post the code here, perhaps the devs can incorporate it into the final away3d 4 code.

im sure a userAnimator class will be most needed and most welcome in away3d. if devs want to build their own, fine with me, as long as away3d 4 gets one.

regards,

 

   

Avatar
Huck, Jr. Member
Posted: 14 January 2012 11:00 PM   Total Posts: 45   [ # 3 ]

oh well, turns out it was really easy to do, once we know how. Im really starting to like away3d. the skeleton animation system is really powerful indeed smile

so, for the sake of new users, here is how to perform custom animations.

first, in your class that will create the mesh data, add the following lines to allow for the “hidden” functions to work:

import away3d.arcane;
use namespace 
arcane

now, create your vertex, normals, uv and index data as usual, and then add the bone weights and index data. here is a small abstract example using my 23 classes i add as attachments:

mesh = new Mesh();
 
   
mesh.name "mymesh";
   
   var 
vercount:Number 32;
   var 
boneCount:Number =3;
   
   var 
subGeom SkinnedSubGeometry = new SkinnedSubGeometry(boneCount);
   

   
   var 
vertices Vector.<Number> = new Vector.<Number>(vercount 3true);
   var 
normals Vector.<Number> = new Vector.<Number>(vercount 3true);
   
   
   var 
ix:Number 0;
   
   var 
dataVector.<Vector3f> = new Vector.<Vector3f>(vercount);
   
data[ix++= new Vector3f(1.000000, -1.000000, -1.000000);
   
data[ix++= new Vector3f(1.000000, -1.0000001.000000);
   
data[ix++= new Vector3f(-1.000000, -1.0000001.000000);
   
data[ix++= new Vector3f(-1.000000, -1.000000, -1.000000);

   
   var 
index:Number 0;
   var 
vert:Vector3f;
   for (var 
i:int 0<vercounti++ )
   
{
    vert 
data[i];
    var 
v1:Number index 3;

    
vertices[v1] vert.x;
    
vertices[v1+1] vert.y;
    
vertices[v1+2] vert.z;
    
    
index++;
   
}
   
   data
.splice(0data.length);
   
data = new Vector.<Vector3f>(vercount);
   
ix 0;
   
data[ix++= new Vector3f(0.000000, -1.0000000.000000);
   
data[ix++= new Vector3f(0.000000, -1.0000000.000000);
   
data[ix++= new Vector3f(0.000000, -1.0000000.000000);
   
data[ix++= new Vector3f(0.000000, -1.0000000.000000);


   
index 0;
   for (
0<vercounti++ )
   
{
    vert 
data[i];
    
v1 index 3;

    
normals[v1] vert.x;
    
normals[v1+1] vert.y;
    
normals[v1+2] vert.z;
    
    
index++;
   
}
   
   
var indexes:Vector.<uint> = new Vector.<uint>();
   
   var 
indexesA:Array = [ 01202 ];
   
    for 
each (var elem:uint in indexesA
    
indexes.push(elem);

    
   
// bone weights
   
var jointIndices Vector.<Number> = new Vector.<Number>(vercount boneCounttrue);
   var 
jointWeights Vector.<Number> = new Vector.<Number>(vercount boneCounttrue);

   
// set bone strength
   
jointWeights[boneCount*0] 1.0;
   
jointWeights[boneCount*1] 1.0;
   
jointWeights[boneCount*2] 1.0;
   
jointWeights[boneCount*3] 1.0;
   
   
// and which vertex connects to which bone (note, away3d seems to require that the indices be multipled by 3, dont know why)
   
jointIndices[boneCount*0] 1*3;
   
jointIndices[boneCount*1] 1*3;
   
jointIndices[boneCount*2] 1*3;
   
jointIndices[boneCount*3] 1*3;
   
   
subGeom.updateVertexData(vertices);
   
subGeom.updateVertexNormalData(normals);
   
//subGeom.updateUVData(uvs);
   
subGeom.updateIndexData(indexes);
   
   
// and now the arcane bone data
   
subGeom.updateJointIndexData(jointIndices);
   
subGeom.updateJointWeightsData(jointWeights);
   
   
// add our submesh
   
mesh.geometry.addSubGeometry(subGeom);

   
// create our 3 bone skeleton
   
var skeleton:Skeleton = new Skeleton();
   
   
//1
   
var joint:SkeletonJoint = new SkeletonJoint();
   
   
joint.name "root";
   
//joint.parentIndex = -1; // root is always -1, set by default
   
var pos:Matrix3D = new Matrix3D();
   
pos.position = new Vector3D(0,00);
   
pos.invert();
   
joint.inverseBindPose pos.rawData;
   
skeleton.joints[0] joint;
   
   
//2
   
joint = new SkeletonJoint();
   
   
joint.name "child";
   
joint.parentIndex 0;
   
pos = new Matrix3D();
   
pos.position = new Vector3D(020);
   
pos.invert();
   
joint.inverseBindPose pos.rawData;
   
skeleton.joints[1] joint;
   
   
//3
   
joint = new SkeletonJoint();
   
   
joint.name "child2";
   
joint.parentIndex 1;
   
pos = new Matrix3D();
   
pos.position = new Vector3D(040);
   
pos.invert();
   
joint.inverseBindPose pos.rawData;
   
skeleton.joints[2] joint;
   
   
// attach our animation to our mesh
   
mesh.geometry.animation = new SkeletonAnimation(skeletonboneCount);
   
   
// important note!!  due to some bug in away3D, the materials MUST be atatched to the mesh AFTER all the vertex data and animations
   
var ctr:ObjectContainer3D = new ObjectContainer3D();
   var 
green ColorMaterial = new ColorMaterial(0x00FF00);
   
green.lights [light];
   
   
mesh.material green;
   
   
ctr.addChild(mesh);
   
   
ctr.scale(80);
   
this.scene.addChild(ctr);
   
   
// good, now we attach our user animator that i provded as a zip file (hopefully the devs will incorporate them or some derivative of in the final away3d code)
   
controller = new UserAnimator(SkeletonAnimationState(mesh.animationState));
   
   
// adn when you are ready to start the animation, play :)   (note: here you need to add methods to hook in and add your transformations to each bone)
   
controller.play(); 

there you go, i hope this helps.


admins and devs, please add some form of user admin in away3d 4. will really help smile

 

File Attachments
UserAnimator.zip  (File Size: 2KB - Downloads: 377)
   

carl.looper, Newbie
Posted: 26 May 2012 04:03 AM   Total Posts: 8   [ # 4 ]
Huck - 14 January 2012 11:00 PM

oh well, turns out it was really easy to do, once we know how. Im really starting to like away3d. the skeleton animation system is really powerful indeed smile

Looks like a good example.

I’m currently testing it. I’ve made the following assumed corrections

var vercount:Number 32// original
var vercount:Number 4// fixed

var indexesA:Array = [ 01202 ]// original
var indexesA:Array = [ 012023 ]// fixed 

Created a Vector3f class for where one was required

public class Vector3f 
{
 
public var x:Number;
 public var 
y:Number;
 public var 
z:Number;
  
 public function 
Vector3f(x:Number=0y:Number=0z:Number=0
 
{
  this
.x;
  
this.y;
  
this.z;
 

In UserSkeletonTreeNode I’m assuming this is the fix, otherwise it throws a runtime error

endPoses[1].orientation.fromAxisAngle(Vector3D.X_AXISangle); //original
endPoses[i].orientation.fromAxisAngle(Vector3D.X_AXISangle); // fixed? 

To get the example to work (and it now does work) I had to ensure the controller was referenced through a global variable. I assume this might have something to do with the controller otherwise going out of scope in my particular implementation

var controller:UserAnimator = new UserAnimator(SkeletonAnimationState(mesh.animationState));
   
_userAnimator controller// added 

thanks heaps for the great example.

Carl

 

 

   
   

X

Away3D Forum

Member Login

Username

Password

Remember_me



X