  | 
		  | 
	 
	 
	
	
		  | 
		
	
	
	
		| Autor | 
		Mensagem | 
	 
	
		
			Lemos 
			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!!!    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 | 
		  | 
	 
	
		  | 
	 
	
		
			Lemos 
			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!     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!      
 
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 | 
		  | 
	 
	
		  | 
	 
	
		
			Edirlei 
			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 | 
		  | 
	 
	
		  | 
	 
	
		
			Lemos 
			Usuário 
			 
  
  
			
			
				Registrado: 14/04/09 Mensagens: 802 Localização: Rio de Janeiro - RJ | 
			 
			  
		 | 
		
			
				 | 
				 | 
			 
			
				Obrigado Edirlei! Amanhã vou trabalhar com afinco nisso!    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 | 
		  | 
	 
	
		  | 
	 
	
		
			alemoes 
			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 | 
		  | 
	 
	
		  | 
	 
	
		
			Lemos 
			Usuário 
			 
  
  
			
			
				Registrado: 14/04/09 Mensagens: 802 Localização: Rio de Janeiro - RJ | 
			 
			  
		 | 
		
			
				 | 
				 | 
			 
			
					  | 	 	  | 	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...    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    ...
 
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...         
 
Abraço
  _________________ Lemos
 
http://alemdanimacao.zip.net/
 
  | 
			 
		  | 
	 
	
		| Sex Dez 04, 2009 12:18 pm | 
		  | 
	 
	
		  | 
	 
	
		
			Lemos 
			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!!!   
 
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!  
 
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!   
  _________________ Lemos
 
http://alemdanimacao.zip.net/
 
  | 
			 
		  | 
	 
	
		| Sex Dez 04, 2009 6:08 pm | 
		  | 
	 
	
		  | 
	 
	
		
			Lemos 
			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 | 
		  | 
	 
	
		  | 
	 
	
		 | 
	 
 
		 | 
		  | 
	 
	 
	
	
		  | 
		  | 
	 
	 
	 |