Modêlos SMD - Estudo
Ir à página Anterior  1, 2, 3, 4  Próximo
 
   3D Game Builder - Índice » Modelagem
Modêlos SMD - Estudo
Autor Mensagem
Lemos
Usuário
Usuário


Registrado: 14/04/09
Mensagens: 802
Localização: Rio de Janeiro - RJ

Comparação entre smd blender e smd Milkshape.
Edirlei

Eu resolvi fazer um teste aqui para tentar entender o que acontece com a exportação no blender. Baixei o milkshape e importei exatamente o mesmo modêlo que usei no blender.
Primeira coisa interessante que eu notei: o milkshape conseguiu importar o modêlo smd criado pelo blender texturizado e perfeito!
Segunda: a animação feita pelo blender foi aceita pelo milkshape!!! Shocked O modêlo ficou animado lá! Mas não foi uma animação perfeita, parecia que a malha sofreu uma torção, como se alguém torcesse o corpo do modêlo, igual a esses filmes de exorcista em que a vítima possuída gira a cabeça toda para trás (KKKKKKKKKKKK!)!

Bom, havia dado um erro na exportação do blender, então imaginei que o milk shape corrigisse isso. Não corrigiu, apesar de eu conseguir fazer a importação bem, a exportação gerou erro no 3DGamebuilder...

Importei com o milkshape o arquivo 3ds da modelagem original feita no wings3d. Animei no milkshape, mas não consegui fazer uma deformação como fiz no blender, apenas fiz o modêlo ser mexido no espaço pelo esqueleto, tipo, para cima e para baixo. Teria que ter tempo para aprender o milkshape... Mas o fato é que esse modêlo foi exportado perfeitamente e reconhecido pelo 3D Game Builder...

Então peguei os dois arquivos smd do blender (modêlo e animação) e os dois do Milkshape (modêlo e animação) e abri eles com o bloco de notas para comparar. Aprimeira coisa que descobri foi um erro de extensão do arquivo blender. Enquanto o milkshape colocou automaticamente a extensão .jpg em todas as linhas, o blender não fêz... Uma outra coisa foi o nome dos ossos do esqueleto, havia um ponto suspeito no nome, era bone e bone.1, enquanto que no do milk era join1 e join2. Então, voltei ao blender e alterei o nome para bone1 e bone2, suprimindo o ponto. Depois, coloquei manualmente a extensão .jpg no nome do material. Tinha hora que dava um erro dizendo que esse arquivo não havia sido encontrado, então acho que isso resolveu.
Exportei de novo e analizei o arquivo. O nome do bone mudou, a extensão .jpg apareceu em todas as linhas, igual ao milkshape, mas continua dando erro, agora outros erros. Acho que antes o erro era line5074 agora é linha 0001 ou algo assim.
Será que se eu lhe enviasse os arquivos smd do blender e smd do milkshape, você abrindo eles com o bloco de notas, conseguiria enxergar algo que eu não vi? Porque para mim não existe erro, ambos são perfeitos!
Eu acho que assim como a falta do .jpg no nome do material (que é o mesmo nome da textura) afetou todas as linhas do arquivo, de repente tem algum erro assim que me passou despercebido. De repente é algum ajuste, algum nome impróprio.
Eu gostaria muito de poder fazer a exportação diretamente do blender sem erro, seria tudo de bom, para mim e para toda a comunidade que trabalha com o blender.
Abraço.



_________________
Lemos
http://alemdanimacao.zip.net/
Qui Dez 03, 2009 4:52 pm Exibir perfil de usuários
Lemos
Usuário
Usuário


Registrado: 14/04/09
Mensagens: 802
Localização: Rio de Janeiro - RJ

Re: Comparação entre smd blender e smd Milkshape.
Mais uma experiência: ao invéz de fazer uma deformação de malha complexa, apenas associei o modêlo a 1 único bone animado. Aí exportei com o blender. Na hora de cadastrar no 3DGbuilder, deu pau! Neutral Bom, aí, eu importei esse mesmo smd problemático com o milkshape e também a animação. O Milkshape reconheceu tudo perfeitamente! Aí exportei animação e arquivo com o mesmo nome, apenas com a plalavra Milk no nome para diferenciar. Aí funcionou! Shocked ShockedShocked
Mas agora vem a grande dúvida: abri os pares de arquivos com o bloco de notas e comparei, tipo Sal.smd do blender e Sal.smd do milk e estão iguais!!!! Não vejo diferença!
O que mudou quando o arquivo passou pelo milk shape? Pque ele não mudou absolutamente nada!
Edirlei, seguem os arquivos deste teste:

http://www.4shared.com/file/164831689/57794801/Sal_sem_skin.html

Abraço!

_________________
Lemos
http://alemdanimacao.zip.net/
Qui Dez 03, 2009 6:39 pm Exibir perfil de usuários
Edirlei
Administrador
Administrador


Registrado: 15/03/08
Mensagens: 760

Oi Lemos,

Encontrei o problema, os arquivos exportados pelo Blender possuem um campo a mais que é facilmente identificado se você abrir os dois arquivos do modelo em um editor de texto.

Em todas as linhas da malha de triângulos existe o valor "1 1 1.000000" no final. Deletei todas as ocorrências do "1 1 1.000000" no arquivo e o modelo foi carregado normalmente.

É só você deletar estes valores do arquivo exportado do Blender, pode utilizar o recurso o "Replace All" ou "Substituir" de qualquer editor de texto.

Não conheço muito do Blender, mas acho que o código fonte dos Plugins pode ser editado, então outra solução seria encontrar no Plugin o local onde esse valor a mais é adicionado no arquivo.


Qui Dez 03, 2009 9:43 pm Exibir perfil de usuários
Lemos
Usuário
Usuário


Registrado: 14/04/09
Mensagens: 802
Localização: Rio de Janeiro - RJ

Obrigado Edirlei! Amanhã vou trabalhar com afinco nisso! Very Happy Eu tenho A GUi do Phyton, que permite editar o script, vou analizar as duas possibilidades e posto aqui!

Abraço!

_________________
Lemos
http://alemdanimacao.zip.net/
Qui Dez 03, 2009 10:30 pm Exibir perfil de usuários
alemoes
Usuário
Usuário


Registrado: 21/08/08
Mensagens: 166
Localização: Clarkston, Washington

lol fim de semana vou estar com meu mouse de novo e tempo de sobra para fucar no novo 3DGB e também dar uma estudada nos arquivos SMD.

So uma duvida rapida, e possivel pegar do half life 1 ou 2 os arquivos SMD e passar para o 3DGB sem problemas?


Qui Dez 03, 2009 11:36 pm Exibir perfil de usuários
Lemos
Usuário
Usuário


Registrado: 14/04/09
Mensagens: 802
Localização: Rio de Janeiro - RJ

Edirlei escreveu:
Oi Lemos,

Encontrei o problema, os arquivos exportados pelo Blender possuem um campo a mais que é facilmente identificado se você abrir os dois arquivos do modelo em um editor de texto.

Em todas as linhas da malha de triângulos existe o valor "1 1 1.000000" no final. Deletei todas as ocorrências do "1 1 1.000000" no arquivo e o modelo foi carregado normalmente.

É só você deletar estes valores do arquivo exportado do Blender, pode utilizar o recurso o "Replace All" ou "Substituir" de qualquer editor de texto.

Não conheço muito do Blender, mas acho que o código fonte dos Plugins pode ser editado, então outra solução seria encontrar no Plugin o local onde esse valor a mais é adicionado no arquivo.


Edirlei

Eu não sei como não vi isso, realmente funciona, o própri bloco de notas tem um comando de substituir. Fiz o teste e deu certo, mas a coisa não é tão simples assim, infelizmente. Peguei o arquivo do pato, que usei como teste para criar um modêlo MD2 do tutorial de criação de MD2 com blender, e fiz a exportação. Como esperado, não foi aceito pelo 3dgb... Crying or Very sad Abri pelo bloco de notas e notei que não apenas havia a ocorrência 1 1 1.000000, mas também 1 2 1.000000, 2 1 1.000000, 1 1.000000. Cacei e eliminei todas elas mas ainda assim não funcionou Shocked ...
Importei o smd com o milk e também a animação. A torçaão no modêlo tornou a ocorrer, existe uma incompatibilidade entre o sistema de bones entre o blender e o milk... A animação ficou tosca. Exportei pelo milk e como já era de se esperar as ocorrências desapareceram. Mas havia mais coisas: todas as linhas da exportação do blender começam com 0 e no milk viraram 1 ou 2. Não dá para substituir isso pque esses valores estão sozinhos, se eu excluir o 0, todos os zeros desaparecem...
E para piorar, o pato exportado pelo blender e importado pelo milk, e exportado novamente, mesmo sem os campos anômalos deu erro...
Tentei estudar o pluggin de exportação e só consegui suspeitar de uma linha, que eu deletei e tentei de novo, mas parece que não alterou em nada os códigos. Voltei ao pluggin original...
Existem outros pluggins de smd por aí, mas parece que esse é o único que funciona.
Vou dar um tempo de smd com o blender. Vou tentar estudar o milkshape e ver se me adapto com ele até ter outra idéia, mas vai ser duro não animar com o blender... O sistema de bones do milkshape é tosco perto do sistema do blender. Vai ser uma grande pena.
Um outro recurso que vi na sua lista de pluggins é o do gmax, mas o pessoal não estava comentando bem ele, duvido que funcione, pelo que entendi do site parece que ocorrem erros quando um vértice é controlado por mais de um bone e no gmax isso é comum , pque ele não associa bones aos vértices, ele trabalha por meio de envelopes, você associa a malha ao esqueleto, trabalha o campo de ação dos bones e pronto. Seria bom se funcionasse, o gmax é muito bom para animar.
A opção de usar o 3dmax seria legal se tivesse algum pluggin para a versão 8, mas acho que não tem, você disse que esse funciona, certo?
Vou ver o que eu faço aqui. Conforme for mantenho o meu projeto com ator md2 mesmo... Sad Sad Sad Sad
Abraço

_________________
Lemos
http://alemdanimacao.zip.net/
Sex Dez 04, 2009 12:18 pm Exibir perfil de usuários
Lemos
Usuário
Usuário


Registrado: 14/04/09
Mensagens: 802
Localização: Rio de Janeiro - RJ

Uma luz no fim do túnel...
Parece que uma luz surgiu no fim do túnel, porém não é a solução definitiva, tá faltando ainda alguma coisa. depois de quebrar muito a cabeça, descobri onde errei com o pato. O número de campos reconhecidos pelo 3DGame Builder é 8, mas o engraçadinho do blender cria 9 e até 10 por enquanto. Para que a edição seja perfeita, é necessário passear por tiodo o código e localizar primeiro essas linhas de 10 cmapos e mandar o bloco de notas deletar os campos 9 e 10 ao mesmo tempo, depois que acabarem as linhas de 10 campos caçamos as de 9, aí deletamos o 9º campo, mas dependendo da complexidade do modêlo, esse campo 9 pode ter vário valores, tipo 121 000000, 141 000000, 211 000000, e por aí vai. Todos tem que ser deletados.
Uma vez com 8 campos, a importação do modêlo estático acontece.
Antes de tudo, claro, no nome do material temos que botar o nome da textura com a extensão, tipo, se a sua textura (e com no máximo 8 caracteres!) for "Tex_01", imagem jpg, no nome do material tem que ser: Tex_01.jpg
Se isso não for feito, esse nome vai aparecer errado dentro do código e eo material não será encontrado.
Bom, exportei o pato e abri com o 3dgamebuilder, quando vi a cara dele, texturizado, fiquei rindo sozinho! aí foi a hora da água fria: na hora de cadastrar a animação, ela foi aceita mas nada aconteceu!!! Shocked
Então lembrei que já havia conseguido animar, mas movendo para cima e para baixo. Então fiz um outro modêlo, um cilindro, e coloquei 4 bones, que contorciam ele para um lado e para o outro, sendo que o último de baixo (a base, o bone pai) girava o conjuto todo e também o deslocava de um lado para o outro.
Exportei o modêlo estático e a animação. Abri o estático, limpei os campos 9 e 10. Importei com 3dgb e entrou de 1ª. Aí, quando cadastrei a animação, a desgraça total: a animação estava lá sim, mas só foi reconhecido o movimento de vai-vem do bone-pai e o giro para lá e para cá, onde os outros 3 bones deformavam a malha, nada aconteceu, a malha ficou rígida e tosca!
Abri o milk shape. Até agora não consegui fazer a malha deformar nele, consegui criar gurpos e associar aos bones, nmas quando mexo os bones, eles despedaçam a malha! Cada um move o seu pedaço e não o conjunto! Shocked
Bom, ao importar maha e animação para dentro dele, a animação se comportou exatamente como no 3dGame builder, dura, só o movimento e o giro do bone pai.
Estou desconfiado que os campos 9 e 10 estão carregando as informações dos bones, uuma outra forma de codificação. Quando deletamos elas, a animação se perde.
Quem quiser ver os arquivos, estão em anexo:

http://www.4shared.com/file/165501056/2bac35d5/Sal4Bones.html

A luta continua! Rolling Eyes

_________________
Lemos
http://alemdanimacao.zip.net/
Sex Dez 04, 2009 6:08 pm Exibir perfil de usuários
Lemos
Usuário
Usuário


Registrado: 14/04/09
Mensagens: 802
Localização: Rio de Janeiro - RJ

Código do pluggin em Phyton
Para qem quiser analizar, posto aqui o script do pluggin do blender. Descobri que a segunda coluna do 10º campo contem a referência aos bones. Quando o milkshape exporta, essa referência passa a ser o primeiro número de cada linha abaixo do nome do material. São 2 formas diferentes de codificar.
Abraço.


[color=green]
#!BPY

#
# Copyright (C) 2009, Doug Tyrrell ( dvondrake.com )
# Copyright (C) 2005, Pluss Roland ( roland@rptd.dnsalias.net )
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#


# Major credits to Pluss Roland for the original script.
# All I did was reformat it, make it work, and recode a few things my way.
# Most of the code in here is still 99% him. I take very little credit.


""" Registration info for Blender menus:
Name: 'Half-Life 2 (.smd)...'
Blender: 235
Group: 'Export'
Submenu: 'Static Mesh' static_sel
Submenu: 'Physics Mesh' phys_sel
Submenu: 'Animated Mesh' anim_sel
Tip: 'Export to Half-Life 2 (.smd) format.'
"""

__author__ = "Doug Tyrrell/Pluss Roland"
__version__ = "1.3 5/03/09"

__bpydoc__ = """\
Exports models, UVs and animations from Blender to SMD files.
"""


import Blender
from Blender.Mathutils import *
import struct, os, cStringIO, time, re
import math
from math import *


# constants
PI = 3.14159265
HALF_PI = PI / 2.0
ONE_PI = PI / 180.0

# transformation matrices
# hl2 coordinate system layout:
# model faces along x axis ( is -y axis in blender )
# model right is along -y axis ( is -x axis in blender )
# model up is along z axis ( is z axis in blender )

tuv = 1.0 # Change this if you feel the need to.
transformPosition = Matrix( [0,1,0,0], [-1,0,0,0], [0,0,1,0], [0,0,0,0] )
scalePosition = Matrix( [tuv,0,0,0], [0,tuv,0,0], [0,0,tuv,0], [0,0,0,1] )
transformBone = Matrix( [1,0,0,0], [0,-1,0,0], [0,0,1,0], [0,0,0,0] )
transformScalePosition = transformPosition * scalePosition
transformScaleBone = transformBone * scalePosition


class BoneType:
def __init__( self, index, bone ):
self.bone = bone
self.index = index
self.parent = None
self.name = bone.name
self.pos = Vector( [ 0, 0, 0 ] )
self.rot = Vector( [ 0, 0, 0 ] )
self.restMat = Matrix( [ 1, 0, 0, 0 ], [ 0, 1, 0, 0 ], [ 0, 0, 1, 0 ], [ 0, 0, 0, 1 ] )

class WeightType:
def __init__( self, bone, weight ):
self.bone = bone
self.weight = weight
def __repr__(self):
return '[' + str( self.bone ) + '=' + str( self.weight ) + ']'
def __str__(self):
return self.__repr__()

class VertexType:
def __init__( self, index, vertex ):
self.vertex = vertex
self.edges = []
self.faces = []
self.index = index
self.weights = []
def findEdge(self, edges, v2):
for edge in self.edges:
if edges[edge].vertices[1] == v2:
return edge
return -1
def getHardEdgeCount(self, edges):
count = 0
for edge in self.edges:
if edges[edge].hard:
count = count + 1
return count

class EdgeType:
def __init__(self, v1, v2, index):
self.vertices = [ v1, v2 ]
self.faces = [ -1, -1 ]
self.index = index
self.hard = False

class FaceType:
def __init__(self, verts, index):
self.vertices = [ verts[0].index, verts[1].index, verts[2].index ]
self.normals = [ -1, -1, -1 ]
self.edges = [ -1, -1, -1 ]
self.index = index
if len( verts ) == 4:
self.vertices.append( verts[3].index )
self.normals.append( -1 )
self.edges.append( -1 )
def findCorner(self, vertex):
for index in range( len(self.vertices) ):
if self.vertices[index] == vertex:
return index
return -1
def setNormalFor(self, vertex, normal):
for index in range( len(self.vertices) ):
if self.vertices[index] == vertex:
self.normals[index] = normal


class BaseExport:
def __init__( self ):
self.armature = None
self.mesh = None
self.file = None
self.object = None
self.center = None
self.bones = []
self.vertices = []
self.faces = []
self.edges = []
self.matrixMesh = Matrix()
self.matrixArmature = Matrix()

def addBone( self, bone, parent ):
boneIndex = len( self.bones )
newBone = BoneType( boneIndex, bone )
newBone.parent = parent
self.bones.append( newBone )

if bone.children:
for child in bone.children:
self.addBone( child, newBone )

def initBones( self ):
print 'Initializing bones...'
for bone in self.armature.bones.values():
if not bone.hasParent():
self.addBone( bone, None )

print '...Found %i bones.' % len( self.bones )

def addArmature( self, object ):
if not self.armature:
self.objArmature = object
self.armature = self.objArmature.getData()
print 'Found armature: %s' % self.objArmature.name
self.matrixArmature = self.objArmature.getMatrix().rotationPart()
self.matrixArmature.resize4x4()
self.initBones()
else:
print 'Found duplicate armature: %s, ignoring...' % object.getData().name

def switchAction( self, action ):
if self.objArmature:
action.setActive( self.objArmature )

def switchTime( self, time ):
if self.armature:
self.objArmature.evaluatePose( time )

def niceValue( self, value ):
if fabs( value ) < 1e-6:
return 0
else:
return round( value, 6 )

def writeBones( self ):
self.file.write( 'nodes\n' )
if len( self.bones ) > 0:
#self.file.write( '0 "%s" -1\n' % ( self.armature.name ) )
for bone in self.bones:
if bone.parent:
self.file.write( '%i "%s" %i\n' % ( bone.index, bone.name, bone.parent.index ) )
else:
self.file.write( '%i "%s" %i\n' % ( bone.index, bone.name, -1 ) )
else:
self.file.write("0 \"joint0\" -1\n")
self.file.write( 'end\n' )
self.file.write( 'skeleton\n' )
self.file.write( 'time 0\n' )
#self.file.write( '%i %f %f %f %f %f %f\n' % ( 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ) )
if len( self.bones ) > 0:
for bone in self.bones:
realBone = bone.bone
bone.restMat = convertMatrix( realBone.matrix[ 'ARMATURESPACE' ] * self.matrixArmature )
if realBone.hasParent():
parentMat = convertMatrix( realBone.parent.matrix[ 'ARMATURESPACE' ] * self.matrixArmature )
parentMat.invert()
bone.restMat = bone.restMat * parentMat
bone.pos = vector_by_matrix( bone.restMat * transformScaleBone, Vector( [ 0, 0, 0 ] ) )
bone.rot = matrixToEuler( bone.restMat )
# write bone informations
self.file.write( '%i %f %f %f %f %f %f\n' % ( bone.index,
self.niceValue( bone.pos.x ), self.niceValue( bone.pos.y ), self.niceValue( bone.pos.z ),
self.niceValue( bone.rot.x * ONE_PI ), self.niceValue( bone.rot.y * ONE_PI ), self.niceValue( bone.rot.z * ONE_PI ) ) )
else:
self.file.write( '0 0 0 0 0 0 0\n' )

def writeNodes( self ):
self.file.write( 'nodes\n' )
#self.file.write( '0 "%s" -1\n' % ( self.armature.name ) )
if len( self.bones ) > 0:
for bone in self.bones:
if bone.parent:
self.file.write( '%i "%s" %i\n' % ( bone.index, bone.name, bone.parent.index ) )
else:
self.file.write( '%i "%s" %i\n' % ( bone.index, bone.name, -1 ) )
else:
self.file.write( '0 "%s" -1\n' % ( self.objMesh.data.name ) )
self.file.write( 'end\n' )

def addVertices( self ):
if self.mesh:
# add vertices
for vert in self.mesh.verts:
self.vertices.append( VertexType( vert.index, vert ) )
# add weights
groups = self.mesh.getVertGroupNames()
for group in groups:
for bone in self.bones:
if group == bone.bone.name:
weights = self.mesh.getVertsFromGroup( group, 1 )
for weight in weights:
if weight[ 1 ] > 0.001:
self.vertices[ weight[ 0 ] ].weights.append( WeightType( bone, weight[ 1 ] ) )
break

def addEdges( self ):
if self.mesh:
if not self.mesh.edges:
self.mesh.addEdgesData()
for index in range( len( self.mesh.edges ) ):
edge = self.mesh.edges[ index ]
newEdge = EdgeType( edge.v1.index, edge.v2.index, index )
newEdge.crease = edge.crease / 255
if edge.crease > 128:
newEdge.hard = True
self.edges.append( newEdge )
self.vertices[ edge.v1.index ].edges.append( index )
self.vertices[ edge.v2.index ].edges.append( index )

def addFaces( self ):
if self.mesh:
for index in range( len( self.mesh.faces ) ):
face = self.mesh.faces[ index ]
newFace = FaceType( face.v, index )
self.faces.append( newFace )
# gather vertices and indices
vi = [ face.v[ 0 ].index, face.v[ 1 ].index, face.v[ 2 ].index ]
vo = [ self.vertices[ vi[ 0 ] ], self.vertices[ vi[ 1 ] ], self.vertices[ vi[ 2 ] ] ]
if len( face.v ) == 4:
vi.append( face.v[ 3 ].index )
vo.append( self.vertices[ vi[ 3 ] ] )
# corners
count = len( face.v )
for c in range( count ):
self.initProcessFaceCorner( vi, vo, c, (c + 1) % count, index )

def initProcessFaceCorner( self, vi, vo, c1, c2, fi ):
vo[c1].faces.append( fi )
edge = vo[c1].findEdge( self.edges, vi[c2] )
if edge == -1:
edge = vo[c2].findEdge( self.edges, vi[c1] )
theEdge = self.edges[edge]
if theEdge.faces[0] == -1:
theEdge.faces[0] = fi
elif theEdge.faces[1] == -1:
theEdge.faces[1] = fi
else:
self.multiFoldMesh = True
self.faces[fi].edges[c1] = edge

def initCalcCornerNormals(self):
self.normalCount = 0
for vert in self.vertices:
hardEdgeCount = vert.getHardEdgeCount( self.edges )
if hardEdgeCount == 0:
for face in vert.faces:
self.faces[face].setNormalFor( vert.index, self.normalCount )
self.normalCount = self.normalCount + 1
else:
changed = True
while changed:
changed = False
for index in vert.faces:
face = self.faces[index]
c = face.findCorner( vert.index )
if face.normals[c] == -1:
edge = self.edges[ face.edges[c] ]
if edge.faces[0] == face.index:
neighbor = edge.faces[1]
else:
neighbor = edge.faces[0]
if edge.hard or neighbor == -1:
face.normals[c] = self.normalCount
self.normalCount = self.normalCount + 1
changed = True
else:
neighborFace = self.faces[ neighbor ]
neighborCorner = neighborFace.findCorner( vert.index )
if neighborFace.normals[ neighborCorner ] != -1:
face.normals[c] = neighborFace.normals[ neighborCorner ]
changed = True

class StaticExport ( BaseExport ):
def __init__( self, phys ):
BaseExport.__init__( self )

physics = ''
if phys:
physics = ' physics'

print '\nExporting static%s mesh to SMD...' % physics
self.DoPhys = phys

def writeFaces( self ):
print 'Writing Faces...'

matrix = self.matrixObject * transformScalePosition
for face in self.faces:
# texture
mat = "undefined.tga"

if self.mesh.hasFaceUV():
material = self.mesh.materials[ self.mesh.faces[ face.index ].materialIndex ]
mat = material.getName()

# write triangle (for both cases)
if len( face.vertices ) == 3:
self.file.write( '%s\n' % ( mat ) )
self.writeIndexedFace( face, [ 0, 1, 2 ], matrix )
elif len( face.vertices ) == 4:
self.file.write( '%s\n' % ( mat ) )
self.writeIndexedFace( face, [ 0, 1, 2 ], matrix )
self.file.write( '%s\n' % ( mat ) )
self.writeIndexedFace( face, [ 0, 2, 3 ], matrix )

print '...Wrote %i faces.' % len( self.faces )

# helper function to write one single face using the given indices
def writeIndexedFace( self, face, indexList, matrix ):
meshFace = self.mesh.faces[ face.index ]
for t in indexList:
vertex = self.vertices[ face.vertices[ t ] ]
vertPos = vector_by_matrix( matrix, meshFace.v[ t ].co )
vertNormal = axis_by_matrix( matrix, meshFace.v[ t ].no )

vertU = 0
vertV = 0
if self.mesh.hasFaceUV():
vertU = meshFace.uv[ t ][ 0 ]
vertV = meshFace.uv[ t ][ 1 ]
# write to file
self.file.write( '0 %f %f %f %f %f %f %f %f %i' % ( self.niceValue( vertPos.x ), self.niceValue( vertPos.y ), self.niceValue( vertPos.z ),
self.niceValue( vertNormal.x ), self.niceValue( vertNormal.y ), self.niceValue( vertNormal.z ),
self.niceValue( vertU ), self.niceValue( vertV ), len( vertex.weights ) ) )
if len( vertex.weights ) > 0:
for weight in vertex.weights:
self.file.write( ' %i %f' % ( weight.bone.index + 1, self.niceValue( weight.weight ) ) )
else:
self.file.write( ' 0 1' )
self.file.write( '\n' )

def writeChunk( self ):
self.file.write("version 1\n")

self.writeBones()

self.file.write("end\n")
self.file.write("triangles\n")

self.writeFaces()

def getExportFilename( self, filename ):
if self.DoPhys:
return filename[: -( len( filename.split( '.', -1 )[ -1 ] ) + 1 ) ] + '-phy' + '.smd'
else:
return filename[: -len( filename.split( '.', -1 )[ -1 ] ) ] + 'smd'

def Export( self, filename ):
try:
self.file = open(filename, 'w')
except IOError, (errno, strerror):
errmsg = "IOError #%s" % errno
errmsg = errmsg + "%t|" + strerror
Blender.Draw.PupMenu(errmsg)
return None

objects = Blender.Object.GetSelected()

for object in objects:
if object.getType() == 'Armature':
self.addArmature( object )
elif object.getType() == 'Mesh':
#if not self.object:

print 'Object: ' + object.name

self.object = object
self.mesh = object.getData()

self.matrixObject = self.object.getMatrix().rotationPart()
self.matrixObject.resize4x4()

self.center = (0, 0, 0)

if self.mesh.hasFaceUV():
print 'Mesh has UV.'

self.addVertices()
self.addEdges()
self.addFaces()
self.initCalcCornerNormals()

if object.getParent() and object.getParent().getType() == 'Armature':
self.addArmature( object )

#else:
# print 'Found duplicate object: %s, ignoring...' % object.getData().name

if not self.object:
alertUser( 'Nothing selected to export!', 'Error!' )
return None


self.writeChunk()

if not self.armature:
print 'No armature found.'

self.file.write("end\n")
self.file.close()

print "Done. Saved to %s\n" % filename

class AnimExport ( BaseExport ):
def __init__( self ):
BaseExport.__init__( self )
self.moves = []

print '\nExporting animation to SMD...'

def searchForAct( self ):
selfobject = None
objects = Blender.Object.GetSelected()
for object in objects:
if object.getType() == 'Mesh':
if not selfobject:
selfobject = object
if object.getParent() and object.getParent().getType() == 'Armature':
return object.getParent().getAction().getName()
elif object.getType() == 'Armature':
return object.getAction().getName()

def getExportFilename( self, filename ):
actName = self.searchForAct()
return filename[: -( len( filename.split( '.', -1 )[ -1 ] ) + 1 ) ] \
+ '_' + actName.replace( '.', '_' ) \
+ '.smd'

def prepareBones( self ):
print 'Preparing bones...'
for bone in self.bones:
realBone = bone.bone
bone.restMat = convertMatrix( realBone.matrix[ 'ARMATURESPACE' ] )
if realBone.hasParent():
parentMat = convertMatrix( realBone.parent.matrix[ 'ARMATURESPACE' ] )
parentMat.invert()
bone.restMat = bone.restMat * parentMat
matrix = bone.restMat * self.matrixArmature * transformScaleBone
bone.pos = vector_by_matrix( matrix, Vector( [ 0, 0, 0 ] ) )
bone.rot = matrixToEuler( bone.restMat )

# write animation
def writeAnimation( self ):
print 'Writing animations...'

action = self.objArmature.getAction()

# hack matrix
matFixAnim = RotationMatrix( 90.0, 4, 'z' )
# retrieve the poser
pose = self.objArmature.getPose()
# process move
playtime = 0.0
ipos = action.getAllChannelIpos()
# determine playtime
for boneobj in self.bones:
bone = boneobj.bone
if bone.name in ipos:
boneIpo = ipos[bone.name]
ipoCurve = boneIpo.getCurve( 'LocX' )
if ipoCurve:
for knot in ipoCurve.bezierPoints:
if knot.pt[ 0 ] > playtime:
playtime = knot.pt[ 0 ]
ipoCurve = boneIpo.getCurve( 'LocY' )
if ipoCurve:
for knot in ipoCurve.bezierPoints:
if knot.pt[ 0 ] > playtime:
playtime = knot.pt[ 0 ]
ipoCurve = boneIpo.getCurve( 'LocZ' )
if ipoCurve:
for knot in ipoCurve.bezierPoints:
if knot.pt[ 0 ] > playtime:
playtime = knot.pt[ 0 ]
ipoCurve = boneIpo.getCurve( 'QuatX' )
if ipoCurve:
for knot in ipoCurve.bezierPoints:
if knot.pt[ 0 ] > playtime:
playtime = knot.pt[ 0 ]
ipoCurve = boneIpo.getCurve( 'QuatY' )
if ipoCurve:
for knot in ipoCurve.bezierPoints:
if knot.pt[ 0 ] > playtime:
playtime = knot.pt[ 0 ]
ipoCurve = boneIpo.getCurve( 'QuatZ' )
if ipoCurve:
for knot in ipoCurve.bezierPoints:
if knot.pt[ 0 ] > playtime:
playtime = knot.pt[ 0 ]
ipoCurve = boneIpo.getCurve( 'QuatW' )
if ipoCurve:
for knot in ipoCurve.bezierPoints:
if knot.pt[ 0 ] > playtime:
playtime = knot.pt[ 0 ]
playtime = int( round( playtime, 0 ) )
if playtime < 1:
playtime = 1
# write header
self.file.write( 'version 1\n' ) # version one file... don't ask me what else could go here

self.writeNodes()

self.file.write( 'skeleton\n' )
# switch action
self.switchAction( action )
# fetch keyframe values
countI = 0
for time in range( 1, playtime + 1 ):
countI = countI + 1

self.file.write( 'time %i\n' % ( time - 1 ) )
#self.file.write( '%i %f %f %f %f %f %f\n' % ( 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ) )
self.switchTime( time )
# write bones
for bone in self.bones:
realBone = bone.bone
poseBone = pose.bones[ realBone.name ]


# calculate bone matrix
restMat = convertMatrix( poseBone.poseMatrix * self.matrixArmature ) * matFixAnim
if realBone.hasParent():
poseParent = pose.bones[ bone.parent.bone.name ]
#parentMat = bone.restMat * convertMatrix( poseParent.poseMatrix )
parentMat = convertMatrix( poseParent.poseMatrix * self.matrixArmature ) * matFixAnim
parentMat.invert()
restMat = restMat * parentMat
pos = vector_by_matrix( restMat * transformScaleBone, Vector( [ 0, 0, 0 ] ) )
rot = matrixToEuler( restMat )

self.file.write( '%i %f %f %f %f %f %f\n' % ( bone.index,
self.niceValue( pos.x ), self.niceValue( pos.y ), self.niceValue( pos.z ),
self.niceValue( rot.x * ONE_PI ), self.niceValue( rot.y * ONE_PI ), self.niceValue( rot.z * ONE_PI ) ) )
# finsihed
self.file.write( 'end\n' )
print '...Wrote %i frames.' % countI

def Export( self, filename ):
try:
self.file = open(filename, 'w')
except IOError, (errno, strerror):
errmsg = "IOError #%s" % errno
errmsg = errmsg + "%t|" + strerror
Blender.Draw.PupMenu(errmsg)
return None

objects = Blender.Object.GetSelected()

for object in objects:
if object.getType() == 'Armature':
self.addArmature( object )
elif object.getType() == 'Mesh':
if not self.object:

#print 'Object: ' + object.name

self.object = object
self.mesh = object.getData()

self.center = (0, 0, 0)

if object.getParent() and object.getParent().getType() == 'Armature':
self.addArmature( object )

#else:
# print 'Found duplicate object: %s, ignoring...' % object.getData().name

if not self.object:
alertUser( 'Nothing selected to export!', 'Error!' )
return None

if not self.armature:
alertUser( 'No armature found, what will be be animating?!', 'Error!' )
return None

self.prepareBones()
self.writeAnimation()

self.file.close()
print "Done. Saved to %s\n" % filename

args = __script__['arg']

def convertMatrix( matrix ):
axisX = Vector( [ -matrix[0][1], -matrix[0][0], matrix[0][2], 0 ] )
axisX.normalize()
axisY = Vector( [ -matrix[1][1], -matrix[1][0], matrix[1][2], 0 ] )
axisY.normalize()
axisZ = Vector( [ -matrix[2][1], -matrix[2][0], matrix[2][2], 0 ] )
axisZ.normalize()
pos = Vector( [ -matrix[3][1], -matrix[3][0], matrix[3][2], 1 ] )
return Matrix( axisY, axisX, axisZ, pos )

def matrixToEuler( matrix ):
euler = matrix.toEuler()
return Vector( -euler.x, euler.y, -euler.z )

def vector_by_matrix( m, p ):
return Vector( [ p[0] * m[0][0] + p[1] * m[1][0] + p[2] * m[2][0] + m[3][0],
p[0] * m[0][1] + p[1] * m[1][1] + p[2] * m[2][1] + m[3][1],
p[0] * m[0][2] + p[1] * m[1][2] + p[2] * m[2][2] + m[3][2] ] )

def axis_by_matrix( m, p ):
return Vector( [ p[0] * m[0][0] + p[1] * m[1][0] + p[2] * m[2][0],
p[0] * m[0][1] + p[1] * m[1][1] + p[2] * m[2][1],
p[0] * m[0][2] + p[1] * m[1][2] + p[2] * m[2][2] ] )

def alertUser( message, title ):
Blender.Draw.PupMenu( title + '%t|' + message )
print title + ': ' + message

def file_callback( filename ):
if not filename.endswith( '.smd' ):
filename = filename + '.smd'
exporter.Export( filename )

exporter = None
if args == 'static_sel':
exporter = StaticExport( 0 )
elif args == 'anim_sel':
exporter = AnimExport()
elif args == 'phys_sel':
exporter = StaticExport( 1 )

if exporter:
Blender.Window.FileSelector( file_callback, "Export SMD", exporter.getExportFilename( Blender.Get( 'filename' )))
[/color]

_________________
Lemos
http://alemdanimacao.zip.net/
Dom Dez 06, 2009 3:00 pm Exibir perfil de usuários
   3D Game Builder - Índice » Modelagem Ir à página Anterior  1, 2, 3, 4  Próximo
Página 2 de 4