- Joined
- Aug 27, 2006
- Messages
- 223
- Reaction score
- 183
Completed Functionality:
Incomplete Functionality:
Installation:
Usage:
License:
Source:
Collaboration:
- Meshes
- Sticky and Per-face UV Coordinates
- Vertex Groups/Weights
- Armature
- Materials
- Textures (Stored in your temporary directory)
- Animations
Incomplete Functionality:
- Define unknowns
Installation:
- Download and install Blender 2.49b from
You must be registered to see links
- Download and install Python 2.7.x from
You must be registered to see links(Windows Users)
- Copy and paste embedded source code and save as ebm_import.py in your
You must be registered to see links.
Usage:
- Click File > Import > CABAL (*.ebm)
- Select *.ebm file
- Click Ok
License:
You must be registered to see links
Source:
Copy and save as: ebm_import.py
Code:
#!BPY
# Copyright (c) 2007-2012 AJ
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# -----------------------------------------------------------------------------
#
# Version 0.0.1
# * Initial release
#
# Version 0.0.2
# * Fixed setting face mode to double sided
# * Fixed mirroring the UV coordinates
# * Fixed reading vertex influences
# * Added setting material mode to texture face with alpha
#
# Version 0.0.3
# * Fixed importing textures in Microsoft Windows
#
# Version 0.0.4
# * Fixed armature edit bone matrix
# * Added animation importing
"""
Name: 'CABAL (.ebm)...'
Blender: 246
Group: 'Import'
Tooltip: 'Import CABAL game (*.ebm) files'
"""
__author__ = 'AJ'
__email__ = ''
__url__ = ('blender', 'elysiun', 'Project homepage, http://www.ragezone.com/')
__version__ = '0.0.4'
__bpydoc__ = """ \
This script imports CABAL game (*.ebm) files.
"""
import Blender
import struct
import tempfile
import math
import re
EBM_BONE_NAMES = []
LEFT_TO_RIGHT = Blender.Mathutils.Matrix([-1.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 1.0])
class MagicError(ValueError):
pass
def ebm_read_material(file_object):
diffuse = struct.unpack('<4f', file_object.read(16))
ambient = struct.unpack('<4f', file_object.read(16))
specular = struct.unpack('<4f', file_object.read(16))
emissive = struct.unpack('<4f', file_object.read(16))
power = struct.unpack('<f', file_object.read(4))[0]
material = Blender.Material.New()
material.setRGBCol(diffuse[0:3])
material.setAlpha(diffuse[3])
material.setMirCol(ambient[0:3])
material.setAmb(ambient[3])
material.setSpecCol(specular[0:3])
material.setSpec(power)
material.setEmit(emissive[3])
return material
def ebm_read_texture(file_object):
name_length = struct.unpack('<H', file_object.read(2))[0]
name = file_object.read(name_length)
texture_data_size = struct.unpack('<I', file_object.read(4))[0]
texture_data = file_object.read(texture_data_size)
file_object.read(26) # ?, 00 00 00 00 00 00 00 00 00 FF FF FF FF 00 00 00 00 00 00 00 00 00 04 00 00 00 DXT3
# Clean the file name
rec = re.compile('[^\w\.]*')
name = rec.sub('', name)
# Create a temporary texture file
texture_file = open(Blender.sys.join(tempfile.gettempdir(), name), 'wb')
texture_file.write(texture_data)
texture_file.close()
texture = None
try:
texture = Blender.Texture.Get(name)
except:
texture = Blender.Texture.New(name)
texture.setType('Image')
image = None
try:
image = Blender.Image.Get(name)
except:
try:
image = Blender.Image.Load(Blender.sys.join(tempfile.gettempdir(), name))
except:
raise
finally:
if image is not None:
texture.setImage(image)
return texture
def ebm_read_mesh(file_object, materials):
name_length = struct.unpack('<H', file_object.read(2))[0]
name = file_object.read(name_length)
world_matrix = Blender.Mathutils.Matrix(struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)))
local_matrix = Blender.Mathutils.Matrix(struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)))
unknown_0 = struct.unpack('<I', file_object.read(4))[0] # 0xFFFFFF
material_index = struct.unpack('<B', file_object.read(1))[0]
vertex_count = struct.unpack('<H', file_object.read(2))[0]
face_count = struct.unpack('<H', file_object.read(2))[0]
if vertex_count == 0 or face_count == 0:
return None
mesh_object = Blender.Object.New('Mesh', name)
mesh = mesh_object.getData(mesh = True)
if mesh is None:
mesh = Blender.Mesh.New(name)
mesh_object.link(mesh)
mesh.vertexUV = True
material = materials[material_index]
mesh.materials = [material]
textures = material.getTextures()
image = None
if len(textures) > 0:
texture = textures[0].tex
image = texture.getImage()
for x in xrange(vertex_count):
position = Blender.Mathutils.Vector(struct.unpack('<3f', file_object.read(12)))
normal = Blender.Mathutils.Vector(struct.unpack('<3f', file_object.read(12)))
uv = Blender.Mathutils.Vector(struct.unpack('<2f', file_object.read(8)))
mesh.verts.extend(position)
vertex = mesh.verts[-1]
vertex.no = normal
vertex.uvco = uv
vertex.uvco[1] = 1.0 - vertex.uvco[1]
for x in xrange(face_count):
mesh.faces.extend([mesh.verts[y] for y in struct.unpack('<3H', file_object.read(6))])
face = mesh.faces[-1]
face.uv = [vertex.uvco for vertex in face.verts]
if image is not None:
face.mode = Blender.Mesh.FaceModes.TEX + Blender.Mesh.FaceModes.TWOSIDE
face.image = image
mesh.faceUV = True
mesh_object.setMatrix(LEFT_TO_RIGHT) # mesh_object.setMatrix(world_matrix)
return mesh_object
def ebm_read_influence(file_object, mesh, armatures):
armature_object = armatures[-1]
mesh_object = mesh
armature_object.makeParent([mesh_object])
armature_modifier = mesh_object.modifiers.append(Blender.Modifier.Types.ARMATURE)
armature_modifier[Blender.Modifier.Settings.OBJECT] = armature_object
armature = armature_object.getData()
mesh = mesh_object.getData(mesh = True)
for x in xrange(0, len(EBM_BONE_NAMES)):
vertex_influences_count = struct.unpack('<I', file_object.read(4))[0]
group_id = EBM_BONE_NAMES[x]
mesh.addVertGroup(group_id)
if vertex_influences_count != 0:
vertex_influences = []
for y in xrange(vertex_influences_count):
vertex_index = struct.unpack('<I', file_object.read(4))[0]
vertex_influences.append(vertex_index)
for y in xrange(vertex_influences_count):
vertex_weight = struct.unpack('<f', file_object.read(4))[0]
mesh.assignVertsToGroup(group_id, \
[vertex_influences[y]], \
vertex_weight, \
Blender.Mesh.AssignModes.ADD)
# else: # problems on bike_10, comment out
# mesh.assignVertsToGroup(group_id, \
# [vertex.index for vertex in mesh.verts], \
# 1.0, \
# Blender.Mesh.AssignModes.ADD)
def ebm_read_bone(file_object, bones):
global EBM_BONE_NAMES
name_length = struct.unpack('<H', file_object.read(2))[0]
name = file_object.read(name_length)
parent_bone_index = struct.unpack('<I', file_object.read(4))[0]
armature_space_matrix = Blender.Mathutils.Matrix(struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)))
parent_armature_space_matrix = Blender.Mathutils.Matrix(struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)), \
struct.unpack('<4f', file_object.read(16)))
armature_space_matrix.invert()
edit_bone = Blender.Armature.Editbone()
edit_bone.name = name
edit_bone.matrix = armature_space_matrix
if parent_bone_index != 0xFFFFFFFF:
edit_bone.parent = bones[parent_bone_index]
bones.append(edit_bone)
EBM_BONE_NAMES.append(name)
return edit_bone
def ebm_read_animation(file_object, magic, armatures):
name_length = struct.unpack('<H', file_object.read(2))[0]
name = file_object.read(name_length)
armature_object = armatures[-1]#EBM_ARMATURES[-1]
armature = armature_object.getData()
action = Blender.Armature.NLA.NewAction(name)
action.setActive(armature_object)
# ipo = Blender.Ipo.New('Object', name)
armature_pose = armature_object.getPose()
armature_pose_bones = armature_pose.bones
bone_count = struct.unpack('<H', file_object.read(2))[0]
for x in xrange(bone_count):
bone_name_length = struct.unpack('<H', file_object.read(2))[0]
bone_name = file_object.read(bone_name_length)
translation_count = struct.unpack('<I', file_object.read(4))[0]
key_frames = {}
for y in xrange(translation_count):
key_frame_second = struct.unpack('<f', file_object.read(4))[0]
x, y, z = struct.unpack('<3f', file_object.read(12))
key_frame_index = int(math.floor(key_frame_second * 100))
if key_frame_index < 1:
key_frame_index = 1
translation = Blender.Mathutils.Vector(x, y, z)
key_frames[key_frame_index] = Blender.Mathutils.TranslationMatrix(translation)
rotation_count = struct.unpack('<I', file_object.read(4))[0]
for y in xrange(rotation_count):
key_frame_second = struct.unpack('<f', file_object.read(4))[0]
x, y, z, w = struct.unpack('<4f', file_object.read(16))
key_frame_index = int(math.floor(key_frame_second * 100))
if key_frame_index < 1:
key_frame_index = 1
xx = x * x
xy = x * y
xz = x * z
xw = x * w
yy = y * y
yz = y * z
yw = y * w
zz = z * z
zw = z * w
rotation_matrix = Blender.Mathutils.Matrix([1.0 - 2.0 * (yy + zz), 2.0 * (xy - zw), 2.0 * (xz + yw), 0.0], \
[2.0 * (xy + zw), 1.0 - 2.0 * (xx + zz), 2.0 * (yz - xw), 0.0], \
[2.0 * (xz - yw), 2.0 * (yz + xw), 1.0 - 2.0 * (xx + yy), 0.0], \
[0.0, 0.0, 0.0, 1.0])
if key_frame_index in key_frames:
key_frames[key_frame_index] = rotation_matrix * key_frames[key_frame_index]
else:
bone = armature.bones[bone_name]
rest_bone_matrix = bone.matrix['ARMATURESPACE'].copy()
if bone.parent is not None:
parent_bone = bone.parent
parent_rest_bone_matrix = parent_bone.matrix['ARMATURESPACE'].copy()
parent_rest_bone_matrix.invert()
rest_bone_matrix *= parent_rest_bone_matrix
translation = rest_bone_matrix.translationPart()
translation_matrix = Blender.Mathutils.TranslationMatrix(translation)
key_frames[key_frame_index] = rotation_matrix * translation_matrix
if bone_name in armature.bones.keys():
for key_frame_index, key_frame_transformation in key_frames.iteritems():
local_matrix = key_frame_transformation.copy()
bone = armature.bones[bone_name]
rest_bone_matrix = bone.matrix['ARMATURESPACE'].copy()
if bone.parent is not None and magic != 0x3EF03:
parent_bone = bone.parent
parent_rest_bone_matrix = parent_bone.matrix['ARMATURESPACE'].copy()
parent_rest_bone_matrix.invert()
local_matrix *= (rest_bone_matrix * parent_rest_bone_matrix).invert()
else:
rest_bone_matrix.invert()
local_matrix *= rest_bone_matrix
armature_pose_bones[bone_name].localMatrix = local_matrix
armature_pose_bones[bone_name].insertKey(armature_object, key_frame_index, [Blender.Object.Pose.ROT, Blender.Object.Pose.LOC])
# else:
# mesh_object = Blender.Object.Get(bone_name)
#
# mesh_object.setIpo(ipo)
#
# for key_frame_index, key_frame_transformation in key_frames.iteritems():
# Blender.Set("curframe", key_frame_index)
#
# mesh_object.setMatrix(key_frame_transformation)
#
# mesh_object.insertIpoKey(Blender.Object.LOCROT)
#
# Blender.Set("curframe", 1)
armature_pose.update()
def ebm_read_material_chunk(file_object, materials):
material_count = struct.unpack('<H', file_object.read(2))[0]
for x in xrange(material_count):
material = ebm_read_material(file_object)
texture = ebm_read_texture(file_object)
if texture is not None:
material.setTexture(0, texture, Blender.Texture.TexCo.UV)
material.setMode(Blender.Material.Modes.TEXFACE + Blender.Material.Modes.TEXFACE_ALPHA)
materials.append(material)
def ebm_read_influence_chunk(file_object, mesh, armatures):
influence_count = struct.unpack('<H', file_object.read(2))[0]
for x in xrange(influence_count):
ebm_read_influence(file_object, mesh, armatures)
def ebm_read_mesh_chunk(file_object, materials, meshes, armatures):
mesh_count = struct.unpack('<H', file_object.read(2))[0]
for x in xrange(mesh_count):
mesh_object = ebm_read_mesh(file_object, materials)
if mesh_object is not None:
chunk_id = struct.unpack('<I', file_object.read(4))[0]
if chunk_id == 0x41470205:
ebm_read_influence_chunk(file_object, mesh_object, armatures)
else: # WTF? fix...
file_object.seek(-5, os.SEEK_CUR)
meshes.append(mesh_object)
def ebm_read_armature_chunk(file_object):
bone_count = struct.unpack('<H', file_object.read(2))[0]
armature_object = Blender.Object.New('Armature')
armature_object.drawMode = Blender.Object.DrawModes.XRAY
armature = armature_object.getData()
if armature is None:
base_name = Blender.sys.basename(file_object.name)
armature_name = Blender.sys.splitext(base_name)[0]
armature = Blender.Armature.New(armature_name)
armature_object.link(armature)
armature.drawType = Blender.Armature.STICK
armature.envelopes = False
armature.vertexGroups = True
armature.makeEditable()
bones = []
for x in xrange(bone_count):
edit_bone = ebm_read_bone(file_object, bones)
armature.bones[edit_bone.name] = edit_bone
armature_object.setMatrix(LEFT_TO_RIGHT)
armature.update()
return armature_object
def ebm_read_animation_chunk(file_object, magic, armatures):
animation_count = struct.unpack('<H', file_object.read(2))[0]
for x in xrange(animation_count):
ebm_read_animation(file_object, magic, armatures)
def ebm_import(file_path):
file_object = None
materials = []
meshes = []
armatures = []
try:
Blender.Window.WaitCursor(1)
file_object = open(file_path, 'rb')
magic = struct.unpack('<I', file_object.read(4))[0]
if magic != 0x3ED03 and \
magic != 0x3EE03 and \
magic != 0x3EF03:
raise MagicError, "Bad magic number, %08x" % magic
print hex(magic)
unknown_0 = struct.unpack('<H', file_object.read(2))[0] # 0x100 (256)
unknown_1 = struct.unpack('<I', file_object.read(4))[0] # ?
bounding_box_min = Blender.Mathutils.Vector(struct.unpack('<3f', file_object.read(12)))
bounding_box_max = Blender.Mathutils.Vector(struct.unpack('<3f', file_object.read(12)))
unknown_2 = struct.unpack('<I', file_object.read(4))[0] # 0x64 (100)
while True:
data = file_object.read(4)
if len(data) == 0: # Clean break
break
chunk_id = struct.unpack('<I', data)[0]
if chunk_id == 0x41470201:
ebm_read_material_chunk(file_object, materials)
continue
if chunk_id == 0x41470202:
ebm_read_mesh_chunk(file_object, materials, meshes, armatures)
continue
if chunk_id == 0x41470203:
armature_object = ebm_read_armature_chunk(file_object)
armatures.append(armature_object)
continue
if chunk_id == 0x41470204:
ebm_read_animation_chunk(file_object, magic, armatures)
continue
except IOError:
raise
else:
scene = Blender.Scene.GetCurrent()
for mesh_object in meshes:
scene.objects.link(mesh_object)
for armature_object in armatures:
scene.objects.link(armature_object)
finally:
if file_object is not None:
file_object.close()
Blender.Window.WaitCursor(0)
def main():
def ebm_file_selector(file_path):
if file_path and \
not Blender.sys.exists(file_path):
Blender.Draw.PupMenu("Warning%%t|The file %s does not exist." % file_path)
else:
ebm_import(file_path)
Blender.Window.FileSelector(ebm_file_selector, 'Ok', Blender.sys.makename(ext='.ebm'))
if __name__ == "__main__":
main()
Collaboration:
Check out the list of other importers and exporters RZ Project Listing
Last edited: