Page 4 of 34

Re: Extracting simple models

Posted: Mon Mar 30, 2015 6:06 am
by zdsmdbh
shakotay2 wrote: Then you could read some MaxScript online help to understand functions like
BoneSys.CreateBone and skinOps.ReplaceVertexWeights for example.
I know how BoneSys.CreateBone or skinOps.ReplaceVertexWeights work,what I don't understand are something like these(part of zaramot's script)

Code: Select all

maxweight = 0
if(W1_array[a].Weight1 != 0) then
   maxweight = maxweight + W1_array[a].Weight1
if(W1_array[a].Weight2 != 0) then
   maxweight = maxweight + W1_array[a].Weight2
if(W1_array[a].Weight3 != 0) then
   maxweight = maxweight + W1_array[a].Weight3
if(W1_array[a].Weight4 != 0) then
   maxweight = maxweight + W1_array[a].Weight4
I don't understand why he need this maxweight,I thought I just need to read the weights from file,and skinOps.ReplaceVertexWeights directly,then mesh got correct weights

.x format file use 4x4 matrix,but seems 3ds Max use 4x3 matrix,something like this

Code: Select all

print $leg_left_ankle.transform
(matrix3 [-0.610972,0.791652,0] [-0.791652,-0.610972,0] [0,0,1] [17.6693,2e-006,1e-006])
So,how to convert 4x4 matrix to 4x3 matrix?

I found these from zaramot's script(hope he won't blame me for this,LOL)

Code: Select all

c11 = ReadFloat f; c12 = ReadFloat f; c13 = ReadFloat f; c14 = ReadFloat f	
c21 = ReadFloat f; c22 = ReadFloat f; c23 = ReadFloat f; c24 = ReadFloat f	
c31 = ReadFloat f; c32 = ReadFloat f; c33 = ReadFloat f; c34 = ReadFloat f
c41 = ReadFloat f; c42 = ReadFloat f; c43 = ReadFloat f; c44 = ReadFloat f
			
tfm = matrix3 [c11,c12,c13] [c21,c22,c23] [c31,c32,c33] [c41,c42,c43]
tfm=(scaleMatrix [-1,-1,1])*tfm
	
newBone = bonesys.createbone	\
				  tfm.row4	\
				  (tfm.row4 + 0.01 * (normalize tfm.row1)) \
				  (normalize tfm.row3)
			newBone.name = BoneName
			newBone.width  = 0.01
			newBone.height = 0.01
			newBone.transform = tfm
			newBone.setBoneEnable false 0
			newBone.wirecolor = white
			newbone.showlinks = true
			newBone.pos.controller      = TCB_position ()
			newBone.rotation.controller = TCB_rotation ()	
It read a 4x4 matrix data,then ignore c14,c24,c34,c44 to generate a 4x3 matrix,and then just use BoneSys.CreateBone to create bone
But if I copy this part to my script,bone seems weird
Image

I also got another question.
Seems there are 2 types of matrix in x.format files?
Here's matrix from Frame

Code: Select all

Frame root_ground {
 

 FrameTransformMatrix {
  -0.000000,1.000000,0.000000,0.000000,-0.000000,-0.000000,1.000000,0.000000,1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,1.000000;;
 }

 Frame root_hips {
  

  FrameTransformMatrix {
   -0.000000,-0.000000,1.000000,0.000000,-0.000000,1.000000,0.000000,0.000000,-1.000000,0.000000,-0.000000,0.000000,46.984253,-0.000011,0.000005,1.000000;;
  }
And here's matrix from SkinWeights

Code: Select all

template SkinWeights {
 <6f0d123b-bad2-4167-a0d0-80224f25fabb>
 STRING transformNodeName;
 DWORD nWeights;
 array DWORD vertexIndices[nWeights];
 array FLOAT weights[nWeights];
 Matrix4x4 matrixOffset
}

.........................
   1.000000,
   1.000000,
   1.000000,
   1.000000,
   1.000000,
   1.000000,
   1.000000,
   1.000000,
   1.000000,
   1.000000,
   1.000000,
   1.000000,
   1.000000,
   1.000000,
   1.000000;
   -1.000000,0.000031,-0.000031,0.000000,-0.000031,-0.000000,1.000000,0.000000,0.000031,1.000000,-0.000000,0.000000,-34.073386,0.181064,-62.320659,1.000000;;
  }
If Frame matrix are used to create bone,what this SkinWeights matrix are used for?
I also tried to import these SkinWeights matrix to Max as bone,but it still looks weird

Here's my new script,it can read bone data,weights data and bones' hierarchy now

Code: Select all

if (heapSize < 200000) then
        heapSize = 2000000 -- allow ~ 40 MB instead of just 7.5 MB. Prevents "Runtime Error: Out of scripter memory"

fname = getOpenFileName \
caption:"Select a X format file" \
types:"DirectX(.x)|*.x" \
historyCategory:"DirectXObjectPresets"
f = openfile fname

Vert_array = #()
Face_array = #()
Normal_array = #()
UV_array = #()
vertexIndice_array = #()
weights_array = #()
bone_stack = #()

RDL= readline f
BoneName = ""

--Read texture name
while (RDL != " TextureFilename {") do (RDL = readline f)
texture_name = readvalue f

while (RDL != "Frame Object001 {") do 
(
	RDL = readline f
	--Read bone name
	if (findString RDL "Frame" != undefined and findString RDL "TransformMatrix" == undefined) do
	(
		start = (findString RDL "Frame")+6
		len = RDL.count-start-1
		BoneName = substring RDL start len
		append bone_stack BoneName
	)
	--Read bone data and create bone
	if (findString RDL "FrameTransformMatrix" != undefined) do
    (
		c11 = readvalue f; c12 = readvalue f; c13 = readvalue f; c14 = readvalue f	
		c21 = readvalue f; c22 = readvalue f; c23 = readvalue f; c24 = readvalue f	
		c31 = readvalue f; c32 = readvalue f; c33 = readvalue f; c34 = readvalue f
		c41 = readvalue f; c42 = readvalue f; c43 = readvalue f; c44 = readvalue f

		tfm = matrix3 [c11,c12,c13] [c21,c22,c23] [c31,c32,c33] [c41,c42,c43]
		tfm=(scaleMatrix [-1,-1,1])*tfm
			
		newBone = bonesys.createbone	\
						  tfm.row4	\
						  (tfm.row4 + 0.01 * (normalize tfm.row1)) \
						  (normalize tfm.row3)
					newBone.name = BoneName
					newBone.width  = 0.01
					newBone.height = 0.01
					newBone.transform = tfm
					newBone.setBoneEnable false 0
					newBone.wirecolor = white
					newbone.showlinks = true
					newBone.pos.controller      = TCB_position ()
					newBone.rotation.controller = TCB_rotation ()
		readline f
		readline f
	)
	--Create bones' hierarchy
	if (findString RDL "}" != undefined and (bone_stack.count > 1)) do
	(
		(getnodebyname (bone_stack[bone_stack.count])).parent = getnodebyname (bone_stack[bone_stack.count-1])
		deleteItem bone_stack bone_stack.count
	)
)			

while (RDL != " Mesh  {") do (RDL = readline f)
mesh_count = readvalue f
for i=1 to mesh_count do
(
	x = readvalue f
	y = readvalue f
	z = readvalue f
	append Vert_array [x,z,y]
	readline f
)

face_count = readvalue f
for i=1 to face_count do
(
	readvalue f
	p1 = readvalue f
	p2 = readvalue f
	p3 = readvalue f
	append Face_array [p1+1,p2+1,p3+1]
	readline f
)

while (RDL != "  MeshNormals  {") do (RDL = readline f)
normal_count = readvalue f
for i=1 to normal_count do
(
	nx = readvalue f
	ny = readvalue f
	nz = readvalue f
	append Normal_array [nx,ny,nz]
	readline f
)

while (RDL != "  MeshTextureCoords  {") do (RDL = readline f)
UV_count = readvalue f
for i=1 to UV_count do
(
	u = readvalue f
	v = readvalue f
	append UV_array [u,1-v,0]
	readline f
)

--Read weights
while (eof f == false) do
(
	RDL = readline f
	if (RDL == "  SkinWeights {") do
	(
		BoneName = readvalue f
		weights_number = readvalue f
		for i=1 to weights_number do
		(
			vertexIndice = readvalue f
			append vertexIndice_array vertexIndice
		)
		for i=1 to weights_number do
		(
			weights = readvalue f
			append weights_array weights
		)
		c11 = readvalue f; c12 = readvalue f; c13 = readvalue f; c14 = readvalue f	
		c21 = readvalue f; c22 = readvalue f; c23 = readvalue f; c24 = readvalue f	
		c31 = readvalue f; c32 = readvalue f; c33 = readvalue f; c34 = readvalue f
		c41 = readvalue f; c42 = readvalue f; c43 = readvalue f; c44 = readvalue f
	)
)

--Build mesh
msh = mesh vertices:Vert_array faces:Face_array
msh.numTVerts = UV_array.count
buildTVFaces msh
for j = 1 to UV_array.count   do setTVert  msh j UV_array[j]
for j = 1 to face_array.count do setTVFace msh j face_array[j]

close f

--Assign material
texture_path = sysInfo.currentdir
if texture_path[texture_path.count] != "\\" do texture_path += "\\"
texture_path += texture_name

new_mat = StandardMaterial()
new_mat.diffuseMap = Bitmaptex()
new_mat.diffuseMap.filename = texture_path
new_mat.showInViewport = True
msh.Material = new_mat

Re: Extracting simple models

Posted: Mon Mar 30, 2015 11:14 am
by shakotay2
zdsmdbh wrote:I know how BoneSys.CreateBone or skinOps.ReplaceVertexWeights work,
I couldn't know this, sry. :)
Nice progress again. Congratz!
I don't understand why he need this maxweight
Don't know his script, so can't tell.
Sum of weights should be <= 1.0 that's what I know. If sumOfWeights is zero you don't need to append weights for that vertex.
So,how to convert 4x4 matrix to 4x3 matrix?
to ignore the last column is one methode.
(There is another method MrAdults told for Noesis but I forgot it cause of rare use.)
But if I copy this part to my script,bone seems weird
Did you check the hierarchy in 3dsmax for correctness? (Would be my first step.)
(seems before that I've to understand how you implemented the bone parenting)

edit: well, hierarchy seems to be ok.
You might check the bones and compare to a working skeleton (Aria, or someone else):

Code: Select all

3 pelvis 0.00023 -0.376314 0.926492
          9.3e-005 0.926492 0.376313
          -1.0 0.0 0.000248
          0.0 0.0 0.0

4 leg_left_thigh 0.926492 0.376314 0.000248
          -0.376314 0.926492 -1e-006
          -0.00023 -9.3e-005 1.0
          7.00017 1.97639 -4.01395

5 leg_left_knee 1.0 0.0 0.0
          0.0 1.0 0.0
          0.0 0.0 1.0
          17.6693 2e-006 1e-006

6 leg_left_ankle 0.610972 -0.791652 0.0
          0.791652 0.610972 0.0
          0.0 0.0 1.0
          17.6693 2e-006 1e-006

7 leg_left_toes 1.0 0.0 0.0
          0.0 1.0 0.0
          0.0 0.0 1.0
          5.14267 0.0 0.0

----------------------------------

9 leg_right_thigh 0.926492 0.376314 0.000248
          -0.376314 0.926492 -1e-006
          -0.00023 -9.3e-005 1.0
          6.99832 1.97564 4.01754

10 leg_right_knee 1.0 0.0 0.0
          0.0 1.0 0.0
          0.0 0.0 1.0
          17.6693 0.0 0.0

11 leg_right_ankle 0.610972 -0.791652 -2e-006
          0.791653 0.610972 -3e-006
          3e-006 0.0 1.0
          17.6693 4e-006 1e-006

12 leg_right_toes 1.0 0.0 0.0
          0.0 1.0 0.0
          0.0 0.0 1.0
          5.14266 -1e-006 -2e-006
If you look at leg_left_knee for example: y and z pos are near to zero, x identical to leg_right_knee.
While left/right tighs are symmetrical.
But maybe it's relative positions.
I also got another question.
Seems there are 2 types of matrix in x.format files?

Code: Select all

[...]
And here's matrix from SkinWeights
[code]template SkinWeights {
 <6f0d123b-bad2-4167-a0d0-80224f25fabb>
 STRING transformNodeName;
 DWORD nWeights;
 array DWORD vertexIndices[nWeights];
 array FLOAT weights[nWeights];
 Matrix4x4 matrixOffset
}
If Frame matrix are used to create bone,what this SkinWeights matrix are used for?
I wasn't aware that there's a matrix for SkinWeights. So I don't know what it's good for.

Here's my new script,it can read bone data,weights data and bones' hierarchy now
Thanks! :) I'll see whether I can use it to get a proper skeleton.

(but seems you know more than me... :D )

Re: Extracting simple models

Posted: Mon Mar 30, 2015 1:39 pm
by howfie
zaramot's maxweight variable is just the sum of the weight values. if it is not zero, he appends the bone ID/weight pairs. it's not really something that needs to be done but there's nothing wrong with doing it. it's just his way of ignoring unweighted vertices. if a mesh's input layout has blendweights and blendindices though, it's pretty rare to see this sum to be 0.

Re: Extracting simple models

Posted: Mon Mar 30, 2015 2:20 pm
by shakotay2
hi, howfie :)

@zdsmdbh: seems I have to read here:
http://cboard.cprogramming.com/game-pro ... ormat.html
and about "Homogeneous Coordinates".

Maybe the link is of interest for you, too?
VirtualAce wrote:" I would recommend looking in the SDK concerning the .x file format. Each type of matrix has a code which tells you what type of matrix it is and what type of transformation will be used."
well, seems I forget too may things I used to know:
"Each bone transform needs to be combined with it's parent all the way up the hierarchy chain."

Re: Extracting simple models

Posted: Mon Mar 30, 2015 5:39 pm
by zdsmdbh
shakotay2 wrote: "Each bone transform needs to be combined with it's parent all the way up the hierarchy chain."
What that mean?
Image

Code: Select all

$leg_left_toes.transform *= $leg_left_ankle.transform
$leg_left_ankle.transform *= $leg_left_knee.transform
$leg_left_knee.transform *= $leg_left_thigh.transform

Code: Select all

for b in geometry where classOf b == BoneGeometry do
(
	if b.parent != undefined do
	(
		b.transform *= b.parent.transform
	)
)

Code: Select all

$leg_left_toes.transform *= $leg_left_ankle.transform
$leg_left_toes.transform *= $leg_left_knee.transform
$leg_left_toes.transform *= $leg_left_thigh.transform

$leg_left_ankle.transform *= $leg_left_knee.transform
$leg_left_ankle.transform *= $leg_left_thigh.transform

$leg_left_knee.transform *= $leg_left_thigh.transform

Code: Select all

for b in geometry where classOf b == BoneGeometry do
(
	prt = b.parent
	while (prt != undefined) do
	(
		b.transform *= prt.transform
		prt = prt.parent
	)
)
Guess what I am doing are wrong
Image

Re: Extracting simple models

Posted: Mon Mar 30, 2015 8:45 pm
by shakotay2
zdsmdbh wrote:

Code: Select all

for b in geometry where classOf b == BoneGeometry do
(
	prt = b.parent
	while (prt != undefined) do
	(
		b.transform *= prt.transform
		prt = prt.parent
	)
)
well, I really would like to know how you know how to code that! :D

From the log it looks to me as if this were the right way:
$Bone:leg_left_thigh @ [7.000163,-4.013950,45.007866] $Bone:pelvis @ [-0.000007,0.000004,46.984253]
$Bone:leg_left_thigh @ [-45.006649,4.986253,53.337406] $Bone:root_hips @ [0.000005,46.984253,-0.000011]
$Bone:leg_left_thigh @ [-45.006653,-6.353142,4.986240] $Bone:root_ground @ [0.000000,0.000000,0.000000]

$Bone:leg_left_knee @ [16.382095,-46.980209,-6.649185] $Bone:leg_left_thigh @ [4.986240,-45.006653,-6.353142]
$Bone:leg_left_knee @ [32.938225,-82.361061,-24.874954] $Bone:pelvis @ [-0.000007,0.000004,46.984253]
$Bone:leg_left_knee @ [24.874878,-0.482716,135.686249] $Bone:root_hips @ [0.000005,46.984253,-0.000011]
$Bone:leg_left_knee @ [24.874861,-88.701973,-0.482727] $Bone:root_ground @ [0.000000,0.000000,0.000000]

Code: Select all

 1. root_ground
     2. root_hips
	 3. pelvis
	     4. leg_left_thigh
		 5. leg_left_knee
		     6. leg_left_ankle
			 7. leg_left_toes
	     	 8. leg_left_knee_adj
I don't have a clue what is missing. The leg_left_knee matrix is multiplied with leg_left_thigh, then pelvis, then root_hips and at last with root_ground;
as it should be.

Reduced it to 15 bones or so:
GuanYinPing_bones.JPG
(tried "inverse" transform then but at no avail.)

Re: Extracting simple models

Posted: Tue Mar 31, 2015 1:37 pm
by zdsmdbh
Here's original model,maybe it helps(.max 2012 and .fbx)
http://www.mediafire.com/download/tn503 ... fbx%29.rar
shakotay2 wrote:well, I really would like to know how you know how to code that! :D
Just saw some posts in forum.
Seyren wrote:If the result looks weird try adding this:

Code: Select all

newBone.transform *= newBone.parent.transform

Code: Select all

for b in geometry where classOf b == BoneGeometry do         --If object is a bone
(
	prt = b.parent
	while (prt != undefined) do                                               --if object have parent ,multiply object.transform by parent.transform
	(                                                                         --if object have grandpa,multiply object.transform by grandpa.transform
		b.transform *= prt.transform                                           --if object have great grandpa.............
		prt = prt.parent                                                       --and so on,until great great great …………grandpa have no parent
	)
)

Re: Extracting simple models

Posted: Wed Apr 01, 2015 12:23 pm
by shakotay2
zdsmdbh wrote:Here's original model,maybe it helps(.max 2012 and .fbx)
Thanks!
I've made a comparison between
GuanYinPing, transforms from FBX scene

leg left thigh
(matrix3 [0,0,-0.393701] [-0.393701,0,0] [0,0.393701,0] [1.581,-0.316203,15.6519])
left leg knee
(matrix3 [0,0,-0.393701] [-0.393701,0,0] [0,0.393701,0] [1.581,-0.316203,8.69552])
left leg ankle
(matrix3 [0,-0.311674,-0.24054] [-0.393701,0,0] [0,0.24054,-0.311674] [1.581,-0.316202,1.73911])
left leg toes
(matrix3 [0,-0.311674,-0.24054] [-0.393701,0,0] [0,0.24054,-0.311674] [1.581,-1.91904,0.50209])

the transforms in the GuanYinPing.x file

Code: Select all

(matrix3 [0.926492,0.376314,0.000247926] [-0.376314,0.926492,0] [-0.00022994,0,1] [7.00017,1.97639,-4.01395])

(matrix3 [1,0,0] 			 [0,1,0] 		[0,0,1] 	                                          [17.6693,0,0])

(matrix3 [0.610972,-0.791652,0] 	 [0.791652,0.610972,0]  [0,0,1] 	                      [17.6693,0,0])

(matrix3 [1,0,0] 			 [0,1,0] 		[0,0,1] 	                                          [5.14267,0,0])
and multiplied with the parenting matrices:

(matrix3 [0.858388,0.376527,-0.348422] [-0.348882,0.926405,0.141611] [0.3761,-1.78814e-007,0.926578] [4.98624,-45.0067,-6.35314])

(matrix3 [0.736817,0.671645,0.0774161] [0.0251844,-0.141692,0.98959] [0.675621,-0.727197,-0.121317] [-0.482723,24.8749,-88.702])

(matrix3 [0.0855027,-0.757195,0.647568] [0.983194,-0.0410912,-0.177864] [0.161287,0.651893,0.740958] [-85.0968,22.71,47.0646])

(matrix3 [0.0295085,0.726544,-0.686482] [-0.05361,0.686942,0.724727] [0.998121,0.0154186,0.0592207] [-33.5888,-23.4079,-88.1313])

So this is the correct position of left knee and toes:
[1.581,-0.316203,8.69552] and [1.581,-1.91904,0.50209] where the "low leg to foot ratio": 8.2/1.6= 5.125 is above 3.0 what I would have expected but maybe she has small feet and long legs?

While [-0.482723,24.8749,-88.702] and [-33.5888,-23.4079,-88.1313] show me that there's a greater problem than a missing scaling factor.
Just saw some posts in forum.
well, Seyren. :)
Sadly he's not too often in this forum...

edit: well, I've made great progress with the parenting. I made an x file from Adria (she's only 46 bones), changed your script
a little bit and bang:
Adria_x_bones_.JPG
Looks pretty normal. But I've spoiled the bones hierarchy somehow in a very strange way...

(I'll send you the zipped max file, the script and the x file.)

well, a small fault only: replace some '6' in the BP_IDs array by '7'
That's the changes:
7, 7, 38, 39, 40,
7, 42, 43, 44, 2)

Now I'll go for the skinning.

Re: Extracting simple models

Posted: Thu Apr 02, 2015 10:00 am
by zdsmdbh
Thanks to shakotay2.
Now I got bones.
Image
But still got some problems to set weights,any ideas?

Code: Select all

if (heapSize < 200000) then
        heapSize = 2000000 -- allow ~ 40 MB instead of just 7.5 MB. Prevents "Runtime Error: Out of scripter memory"

fname = getOpenFileName \
caption:"Select a X format file" \
types:"DirectX(.x)|*.x" \
historyCategory:"DirectXObjectPresets"
f = openfile fname

struct BoneStruct
(
	bone_name,matrix,parent
)
BS = BoneStruct bone_name:#() matrix:#() parent:#()

Vert_array = #()
Face_array = #()
Normal_array = #()
UV_array = #()
vertexIndice_array = #()
weights_array = #()
bone_stack = #()

RDL= readline f
texture_name = ""
BoneName = ""

--Read texture name
while (RDL != " TextureFilename {" and (findString RDL "Frame" == undefined or findString RDL "template" != undefined or findString RDL "Matrix" != undefined)) do (RDL = readline f)
if RDL == " TextureFilename {" do
(
	texture_name = readvalue f
	readline f
	readline f
	readline f
)

--Collect Bones Info
brackets_count = 0
do
(
	RDL = readline f
	if (findString RDL "{" != undefined) do (brackets_count += 1)
	if (findString RDL "}" != undefined) do (brackets_count -= 1)
	--Collect bone name
	if (findString RDL "Frame" != undefined and findString RDL "TransformMatrix" == undefined and RDL != "    Frame Adriaout {") do
	(
		start = (findString RDL "Frame")+6
		len = RDL.count-start-1
		BoneName = substring RDL start len
		append BS.bone_name BoneName
		append bone_stack BoneName
	)
	--Read bone data and collect bones matrix
	if (findString RDL "FrameTransformMatrix" != undefined) do
    (
		
		c11 = readvalue f; c12 = readvalue f; c13 = readvalue f; c14 = readvalue f	
		c21 = readvalue f; c22 = readvalue f; c23 = readvalue f; c24 = readvalue f	
		c31 = readvalue f; c32 = readvalue f; c33 = readvalue f; c34 = readvalue f
		c41 = readvalue f; c42 = readvalue f; c43 = readvalue f; c44 = readvalue f

		tfm = matrix3 [c11,c12,c13] [c21,c22,c23] [c31,c32,c33] [c41,c42,c43]
		append BS.matrix tfm

		readline f
		readline f
		brackets_count -= 1
	)
	--Collect bones' hierarchy
	if (findString RDL "}" != undefined and (bone_stack.count > 1)) do
	(
		BS.parent[findItem BS.bone_name bone_stack[bone_stack.count]] = bone_stack[bone_stack.count-1]
		deleteItem bone_stack bone_stack.count
	)
)while(brackets_count > 0)	

--Create Bones
for i=1 to BS.bone_name.count do
(
    newBone = bonesys.createbone   \
                    BS.matrix[i].row4   \
                    (BS.matrix[i].row4 + 0.01 * (normalize BS.matrix[i].row1)) \
                    (normalize BS.matrix[i].row3)
			   newBone.name = BS.bone_name[i]
               newBone.width  = 0.01
               newBone.height = 0.01
               newBone.transform = BS.matrix[i]
               newBone.setBoneEnable false 0
               newBone.wirecolor = white
               newbone.showlinks = true
               newBone.pos.controller      = TCB_position ()
               newBone.rotation.controller = TCB_rotation ()

	if (BS.parent[i] != undefined) do
	(
		newBone.parent = getnodebyname BS.parent[i]
		newBone.transform *= (getnodebyname BS.parent[i]).transform
	)
)

--Flip bones
rootRT = dummy name:"Main_Root" boxsize:[.1,.1,.1]
for b in objects where (classOf b == BoneGeometry and b.parent==undefined) do b.parent = rootRT
rootRT.transform = (matrix3 [-1,0,0] [0,0,1] [0,1,0] [0,0,0])
delete rootRT

--Read mesh name
while (findString RDL "Frame" == undefined) do (RDL = readline f)
start = (findString RDL "Frame")+6
len = RDL.count-start-1
MeshName = substring RDL start len

while (RDL != " Mesh  {") do (RDL = readline f)
mesh_count = readvalue f
for i=1 to mesh_count do
(
	x = readvalue f
	y = readvalue f
	z = readvalue f
	append Vert_array [x,z,y]
	readline f
)

face_count = readvalue f
for i=1 to face_count do
(
	readvalue f
	p1 = readvalue f
	p2 = readvalue f
	p3 = readvalue f
	append Face_array [p1+1,p2+1,p3+1]
	readline f
)

while (RDL != "  MeshNormals  {") do (RDL = readline f)
normal_count = readvalue f
for i=1 to normal_count do
(
	nx = readvalue f
	ny = readvalue f
	nz = readvalue f
	append Normal_array [nx,ny,nz]
	readline f
)

while (RDL != "  MeshTextureCoords  {") do (RDL = readline f)
UV_count = readvalue f
for i=1 to UV_count do
(
	u = readvalue f
	v = readvalue f
	append UV_array [u,1-v,0]
	readline f
)

--Build mesh
msh = mesh vertices:Vert_array faces:Face_array
msh.numTVerts = UV_array.count
buildTVFaces msh
for j = 1 to UV_array.count   do setTVert  msh j UV_array[j]
for j = 1 to face_array.count do setTVFace msh j face_array[j]
	
msh.name = MeshName

max modify mode
select msh
skinMod = skin ()
addModifier msh skinMod
modPanel.setCurrentObject skinMod

--Read weights
while (eof f == false) do
(
	RDL = readline f
	if (RDL == "  SkinWeights {") do
	(
		BoneName = readvalue f
		skinOps.addBone skinMod (getnodebyname BoneName) 1
		weights_number = readvalue f
		for i=1 to weights_number do
		(
			vertexIndice = readvalue f
			append vertexIndice_array vertexIndice
		)
		for i=1 to weights_number do
		(
			weights = readvalue f
			append weights_array weights
		)
		c11 = readvalue f; c12 = readvalue f; c13 = readvalue f; c14 = readvalue f	
		c21 = readvalue f; c22 = readvalue f; c23 = readvalue f; c24 = readvalue f	
		c31 = readvalue f; c32 = readvalue f; c33 = readvalue f; c34 = readvalue f
		c41 = readvalue f; c42 = readvalue f; c43 = readvalue f; c44 = readvalue f
	)
)

close f

--Assign material
texture_path = sysInfo.currentdir
if texture_path[texture_path.count] != "\\" do texture_path += "\\"
texture_path += texture_name

new_mat = StandardMaterial()
new_mat.diffuseMap = Bitmaptex()
new_mat.diffuseMap.filename = texture_path
new_mat.showInViewport = True
msh.Material = new_mat

Re: Extracting simple models

Posted: Thu Apr 02, 2015 11:49 am
by shakotay2
zdsmdbh wrote:Thanks to shakotay2.
Now I got bones.
:)
But still got some problems to set weights,any ideas?
I applied the weights per bone. Then cleared vertexIndices_array and weights_array for the next bone.
But maxscript doesn't "understand" me (and vice versa :D ):
GuanYinPing_skin.JPG
Some rotations work, though.
Normally one would loop through vertices - maybe that's the fault.
At this moment max' weights table's coming into my mind -
maybe it reveals something of interest...
hmm, why the weights are 1.0 all??
upps, skinOps.getNumberVertices skinMod is zero, skinOps.ReplaceVertexWeights is never executed...

edit: there's only one thing I know for sure:
you're running mad with skinOps if you don't check these for none-zero:
format "vCnt skinMod %\n" (skinOps.getNumberVertices skinMod)
bones_count = skinops.getnumberbones skinMod

Re: Extracting simple models

Posted: Fri Apr 03, 2015 6:43 am
by zdsmdbh
OK,got weights
Image
3ds Max 2013 and above have some ridiculous problem about get Bone ID,so I have to write a GetBoneIDbyName function,which make my script more complex and slow

Sometimes max will give me an "Runtime error:Exceeded the vertex countSkin:Skin"
Sometimes it works fine

I don't know why this happend.
Maybe you know?

Code: Select all

if (heapSize < 200000) then
        heapSize = 2000000 -- allow ~ 40 MB instead of just 7.5 MB. Prevents "Runtime Error: Out of scripter memory"

fname = getOpenFileName \
caption:"Select a X format file" \
types:"DirectX(.x)|*.x" \
historyCategory:"DirectXObjectPresets"
f = openfile fname

fn GetBoneIDbyName BoneName skinMod =
(
    for i=1 to skinOps.GetNumberBones skinMod do
	(
		if (skinOps.GetBoneName skinMod i 1) == BoneName do
		(
			return i
		)
	)
)

struct BoneStruct
(
	bone_name,matrix,parent
)
BS = BoneStruct bone_name:#() matrix:#() parent:#()

Vert_array = #()
Face_array = #()
Normal_array = #()
UV_array = #()
bone_stack = #()
Skin_Bones_Name = #()
Skin_Weights = #()

RDL= readline f
texture_name = ""
BoneName = ""

--Read texture name
while (RDL != " TextureFilename {" and (findString RDL "Frame" == undefined or findString RDL "template" != undefined or findString RDL "Matrix" != undefined)) do (RDL = readline f)
if RDL == " TextureFilename {" do
(
	texture_name = readvalue f
	readline f
	readline f
	readline f
)

--Collect Bones Info
brackets_count = 0
do
(
	RDL = readline f
	if (findString RDL "{" != undefined) do (brackets_count += 1)
	if (findString RDL "}" != undefined) do (brackets_count -= 1)
	--Collect bone name
	if (findString RDL "Frame" != undefined and findString RDL "TransformMatrix" == undefined) do
	(
		start = (findString RDL "Frame")+6
		len = RDL.count-start-1
		BoneName = substring RDL start len
		append BS.bone_name BoneName
		append bone_stack BoneName
	)
	--Read bone data and collect bones matrix
	if (findString RDL "FrameTransformMatrix" != undefined) do
    (
		
		c11 = readvalue f; c12 = readvalue f; c13 = readvalue f; c14 = readvalue f	
		c21 = readvalue f; c22 = readvalue f; c23 = readvalue f; c24 = readvalue f	
		c31 = readvalue f; c32 = readvalue f; c33 = readvalue f; c34 = readvalue f
		c41 = readvalue f; c42 = readvalue f; c43 = readvalue f; c44 = readvalue f

		tfm = matrix3 [c11,c12,c13] [c21,c22,c23] [c31,c32,c33] [c41,c42,c43]
		append BS.matrix tfm

		readline f
		readline f
		brackets_count -= 1
	)
	--Collect bones' hierarchy
	if (findString RDL "}" != undefined and (bone_stack.count > 1)) do
	(
		BS.parent[findItem BS.bone_name bone_stack[bone_stack.count]] = bone_stack[bone_stack.count-1]
		deleteItem bone_stack bone_stack.count
	)
)while(brackets_count > 0)	

--Create Bones
for i=1 to BS.bone_name.count do
(
    newBone = bonesys.createbone   \
                    BS.matrix[i].row4   \
                    (BS.matrix[i].row4 + 0.01 * (normalize BS.matrix[i].row1)) \
                    (normalize BS.matrix[i].row3)
			   newBone.name = BS.bone_name[i]
               newBone.width  = 0.01
               newBone.height = 0.01
               newBone.transform = BS.matrix[i]
               newBone.setBoneEnable false 0
               newBone.wirecolor = white
               newbone.showlinks = true
               newBone.pos.controller      = TCB_position ()
               newBone.rotation.controller = TCB_rotation ()

	if (BS.parent[i] != undefined) do
	(
		newBone.parent = getnodebyname BS.parent[i]
		newBone.transform *= newBone.parent.transform
	)
)

--Flip bones
rootRT = dummy name:"Main_Root" boxsize:[.1,.1,.1]
for b in objects where (classOf b == BoneGeometry and b.parent==undefined) do b.parent = rootRT
rootRT.transform = (matrix3 [1,0,0] [0,0,1] [0,1,0] [0,0,0])
delete rootRT

--Read mesh name
while (findString RDL "Frame" == undefined) do (RDL = readline f)
start = (findString RDL "Frame")+6
len = RDL.count-start-1
MeshName = substring RDL start len

while (RDL != " Mesh  {") do (RDL = readline f)
mesh_count = readvalue f
for i=1 to mesh_count do
(
	x = readvalue f
	y = readvalue f
	z = readvalue f
	append Vert_array [x,z,y]
	readline f
)

face_count = readvalue f
for i=1 to face_count do
(
	readvalue f
	p1 = readvalue f
	p2 = readvalue f
	p3 = readvalue f
	append Face_array [p1+1,p2+1,p3+1]
	readline f
)

while (RDL != "  MeshNormals  {") do (RDL = readline f)
normal_count = readvalue f
for i=1 to normal_count do
(
	nx = readvalue f
	ny = readvalue f
	nz = readvalue f
	append Normal_array [nx,ny,nz]
	readline f
)

while (RDL != "  MeshTextureCoords  {") do (RDL = readline f)
UV_count = readvalue f
for i=1 to UV_count do
(
	u = readvalue f
	v = readvalue f
	append UV_array [u,1-v,0]
	readline f
)

--Build mesh
msh = mesh vertices:Vert_array faces:Face_array
msh.numTVerts = UV_array.count
buildTVFaces msh
for j = 1 to UV_array.count   do setTVert  msh j UV_array[j]
for j = 1 to face_array.count do setTVFace msh j face_array[j]

msh.name = MeshName

max modify mode
select msh
skinMod = skin ()
addModifier msh skinMod
modPanel.setCurrentObject skinMod

--Collect weights data
while (eof f == false) do
(
	RDL = readline f
	if (RDL == "  SkinWeights {") do
	(
		BoneName = readvalue f
		skinOps.addBone skinMod (getnodebyname BoneName) 1
		weights_number = readvalue f
		vertexIndice_array = #()
		weights_array = #()
		for i=1 to weights_number do
		(
			vertexIndice = readvalue f
			append vertexIndice_array (vertexIndice +1)
		)
		for i=1 to weights_number do
		(
			weights = readvalue f
			append weights_array weights
		)
		for i=1 to weights_number do
		(
			if weights_array[i] > 0 do
			(
				if (classof Skin_Bones_Name[vertexIndice_array[i]] != Array) do (Skin_Bones_Name[vertexIndice_array[i]] = #())
				if (classof Skin_Weights[vertexIndice_array[i]] != Array) do (Skin_Weights[vertexIndice_array[i]] = #())
					
				append Skin_Bones_Name[vertexIndice_array[i]] BoneName
				append Skin_Weights[vertexIndice_array[i]] weights_array[i]
			)
		)
		c11 = readvalue f; c12 = readvalue f; c13 = readvalue f; c14 = readvalue f	
		c21 = readvalue f; c22 = readvalue f; c23 = readvalue f; c24 = readvalue f	
		c31 = readvalue f; c32 = readvalue f; c33 = readvalue f; c34 = readvalue f
		c41 = readvalue f; c42 = readvalue f; c43 = readvalue f; c44 = readvalue f
	)
)

--Set weights
for i=1 to Skin_Weights.count do
(
	bones_ID = #()
	for j in Skin_Bones_Name[i] do
	(
		append bones_ID (GetBoneIDbyName j skinMod)
	)
	skinOps.ReplaceVertexWeights skinMod i bones_ID Skin_Weights[i]
)

close f

--Assign material
texture_path = sysInfo.currentdir
if texture_path[texture_path.count] != "\\" do texture_path += "\\"
texture_path += texture_name

new_mat = StandardMaterial()
new_mat.diffuseMap = Bitmaptex()
new_mat.diffuseMap.filename = texture_path
new_mat.showInViewport = True
msh.Material = new_mat

Re: Extracting simple models

Posted: Fri Apr 03, 2015 11:58 am
by shakotay2
zdsmdbh wrote:OK,got weights
great! :)
3ds Max 2013 and above have some ridiculous problem about get Bone ID
From what I know they introduced a "name-sorting-feature" and I don't see an option to switch it off so one might use the add "00x_" trick where x= boneID.
The bones hierachy is shown flat, though. But it seems to exist. (That's either mad or I simply don't understand it... :D )
Max2013.jpg
Sometimes max will give me an "Runtime error:Exceeded the vertex countSkin:Skin"
Sometimes it works fine

I don't know why this happend.
Maybe you know?
You might try
format "vCnt skinMod %\n" (skinOps.getNumberVertices skinMod)
(see my PM)

Re: Extracting simple models

Posted: Fri Apr 03, 2015 2:21 pm
by zdsmdbh
I just test my last maxscript in 2009 32bit, 2009 64bit, 2012 64bit, 2014 64bit, 2015 64bit
It works fine in these version (If I didn't get that "Runtime error:Exceeded the vertex countSkin:Skin")

When it works fine
Image
When I got "Runtime error:Exceeded the vertex countSkin:Skin"
Image
Usually it happened when I close Max completely,and start Max,and run my script,then error

Another problem bother me:
If I delete texture_name = "" in line 36
I won't be able to get texture_name in line 43
Don't know why too.

Re: Extracting simple models

Posted: Fri May 08, 2015 6:42 pm
by Slozhny
Hi Shakotay. Can you help me with highpoly model. I've broke my head with hexeditor (((
try to start from "3ca" but something wrong ((
https://www.dropbox.com/s/oe5ztu9gqslp1 ... e.bin?dl=0
File "Cammy White.bin". It's extracted from webgl model.

Re: Extracting simple models

Posted: Fri May 08, 2015 9:10 pm
by shakotay2
hello, this is what I get:
CammyWhite.JPG
(Please, don't use this thread for webgl requests. Thx.)