Morph targets

About Truespace Archives

These pages are a copy of the official truespace forums prior to their removal somewhere around 2011.

They are retained here for archive purposes only.

Morph targets // Scriptorium

1  |  

Post by Jack Edwards // Apr 8, 2007, 8:26pm

Jack Edwards
Total Posts: 4062
pic
It just occured to me that the solution created by ProfessorKhaos in this thread:

http://forums1.caligari.com/truespace/showthread.php?t=2533


Would lend itself very well to generating a Morph target system. Instead of copying UVs why not average local vertex positions by an arbitrary ratio set by slider? It needn't be limited to just two meshes either. The math scales easily to fit as many "template meshes" as needed. (Pos1 + Pos2 + ....)/(#pos).


Add the ability to define the active area (vertex indexes) to be morphed and it could conceivably even be used in parallel with bones based animation. Of course instancing or linking the skeletons would probably be the safest approach. Then just set a visibility toggle on the morph target meshes.


If I've got time I think I'll set up a simple version of this. I'm pretty much stuck at where I'm at on other project anyway.


-Jack.

Post by Jack Edwards // Apr 8, 2007, 9:10pm

Jack Edwards
Total Posts: 4062
pic
Whupps, goofed my math. Since it doesn't take into account the slider percentage.


Hmm... two ways to solve this:


1.) Average each with the base mesh separately based on slider amount then average the results of each of those operation. This would give bias to the base mesh.


2.) Treat all meshes equally and sum all slider percentages then divide each by that sum to find the ratio of influence that would be multiplied by that meshe's vertex values.


I think #1 would be the more intuitive interface... but I suppose it wouldn't be that hard to allow for either via checkbox.


-Jack.

Post by Jack Edwards // Apr 9, 2007, 12:00am

Jack Edwards
Total Posts: 4062
pic
:D :D :D

5255

Here's the code:

// OnComputeOutputs
// Called to compute values of all output connectors
function OnComputeOutputs(params)
{
BaseMesh = params.conValue('BaseMesh');
MorphMesh1 = params.conValue('MorphMesh1');
nMorphVal1 = params.ConValue('nMorphVal1');

// TODO: put your computation here

// get some info from input meshes

BaseMeshNumTris = BaseMesh.GetNumTriangles();
MorphMesh1NumTris = MorphMesh1.GetNumTriangles();

// check to make sure there are input meshes present

if ((!BaseMeshNumTris) || (!MorphMesh1NumTris)) {
// params.ConValue('Mesh') = BaseMesh;
// System.Alert("Input meshes not present.");
return;
}

// we have input meshes, get other pertinent data for comparison

BaseMeshNumVertices = BaseMesh.GetNumVertices();
MorphMesh1NumVertices = MorphMesh1.GetNumVertices();

BaseMeshTriList = BaseMesh.GetTrianglesStreamByName('Triangle Vertices Stream Data');
MorphMesh1TriList = MorphMesh1.GetTrianglesStreamByName('Triangle Vertices Stream Data');

// are there equal number of vertices and triangles in each mesh?

if ((BaseMeshNumVertices != MorphMesh1NumVertices) || (BaseMeshNumTris != MorphMesh1NumTris))
{
params.ConValue('Mesh') = BaseMesh;
// System.Alert("Failed vertex test. Meshes not same geometry.");
return;
}

// are triangle vertex indices identical in both meshes?

bad_tri_flag = 0;

for (tri_index = 0; tri_index < BaseMeshNumTris; tri_index++) {
if (BaseMeshTriList.i(tri_index) != MorphMesh1TriList.i(tri_index)) bad_tri_flag = 1;
if (BaseMeshTriList.j(tri_index) != MorphMesh1TriList.j(tri_index)) bad_tri_flag = 1;
if (BaseMeshTriList.k(tri_index) != MorphMesh1TriList.k(tri_index)) bad_tri_flag = 1;
}

if (bad_tri_flag == 1) {
params.ConValue('Mesh') = BaseMesh;
// System.Alert("Failed triangle test. Meshes not same geometry.");
return;
}

// ok, mesh is close enough to allow vertex averaging

// vertex streams
BaseMeshVerts = BaseMesh.GetVerticesStreamByName('Vertex Stream Data');
MorphMesh1Verts = MorphMesh1.GetVerticesStreamByName('Vertex Stream Data');
MeshVerts = Mesh.GetVerticesStreamByName('Vertex Stream Data');


// process verts

Mesh = BaseMesh;

nBaseVal = 1 - nMorphVal1;

for (vert_index = 0; vert_index < BaseMeshNumVertices; vert_index++) {
MeshVerts.x(vert_index) = (BaseMeshVerts.x(vert_index) * nBaseVal) + (MorphMesh1Verts.x(vert_index) * nMorphVal1);
MeshVerts.y(vert_index) = (BaseMeshVerts.y(vert_index) * nBaseVal) + (MorphMesh1Verts.y(vert_index) * nMorphVal1);
MeshVerts.z(vert_index) = (BaseMeshVerts.z(vert_index) * nBaseVal) + (MorphMesh1Verts.z(vert_index) * nMorphVal1);
}

// Reattach output mesh updated vertex list

Mesh.AttachVerticesStream(MeshVerts);

// output should have morphed geometry applied.

params.conValue("Mesh") = Mesh
}


Let me know if you guys see some ways we can make the code as safe as possible and I'll get to work making a distributable version.

BTW, many thanks go to ProfessorKhaos without whose code I couldn't have figured out how to make this work and wouldn't have gotten the idea.

-Jack.

Post by Jack Edwards // Apr 9, 2007, 12:49am

Jack Edwards
Total Posts: 4062
pic
Here's the working object. You should be able to link up any two same geometry objects and morph between them. (Copies work well.)


-Jack.
Awportals.com is a privately held community resource website dedicated to Active Worlds.
Copyright (c) Mark Randall 2006 - 2024. All Rights Reserved.
Awportals.com   ·   ProLibraries Live   ·   Twitter   ·   LinkedIn