Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/blender2.64 #10

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
327 changes: 327 additions & 0 deletions Blender Export/objc_blend_2.64/io_export_objective_c_header.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
bl_info = {
"name": "Export Objective-C Header (.h)",
"author": "Jeff LaMarche",
"version": (1, 0),
"blender": (2, 5, 7),
"api": 35622,
"location": "File > Export",
"description": "Export Model to Objective-C Header file",
"warning": "",
"wiki_url": "",
"tracker_url": "",
"category": "Import-Export"}

'''
Usage Notes:


'''

import bpy
from bpy.props import *
import mathutils, math, struct
import os
from os import remove
import time
import bpy_extras
from bpy_extras.io_utils import ExportHelper
import time
import shutil
import bpy
import mathutils

def triangulateNMesh(object):
bneedtri = False
scene = bpy.context.scene
bpy.ops.object.mode_set(mode='OBJECT')
for i in scene.objects: i.select = False #deselect all objects
object.select = True
scene.objects.active = object #set the mesh object to current
print("Checking mesh if needs to convert quad to Tri...")
object.data.update(calc_tessface=True)
for face in object.data.tessfaces:
if (len(face.vertices) > 3):
bneedtri = True
break

bpy.ops.object.mode_set(mode='OBJECT')
if bneedtri == True:
print("Converting quad to tri mesh...")
me_da = object.data.copy() #copy data
me_ob = object.copy() #copy object
#note two copy two types else it will use the current data or mesh
me_ob.data = me_da
bpy.context.scene.objects.link(me_ob)#link the object to the scene #current object location
for i in scene.objects: i.select = False #deselect all objects
me_ob.select = True
scene.objects.active = me_ob #set the mesh object to current
bpy.ops.object.mode_set(mode='EDIT') #Operators
bpy.ops.mesh.select_all(action='SELECT')#select all the face/vertex/edge
bpy.ops.mesh.quads_convert_to_tris() #Operators
bpy.context.scene.update()
bpy.ops.object.mode_set(mode='OBJECT') # set it in object
print("Triangulate Mesh Done!")
print("Remove Merge tmp Mesh [ " ,object.name, " ] from scene!" )
bpy.ops.object.mode_set(mode='OBJECT') # set it in object
bpy.context.scene.objects.unlink(object)
else:
print("No need to convert tri mesh.")
me_ob = object
return me_ob


def writeString(file, string):
file.write(bytes(string, 'UTF-8'))

def do_export(context, props, filepath):
mat_x90 = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
ob = context.active_object
me_ob = triangulateNMesh(ob)
current_scene = context.scene
apply_modifiers = props.apply_modifiers

mesh = me_ob.to_mesh(current_scene, apply_modifiers, 'PREVIEW')

basename = mesh.name.capitalize()

if props.world_space:
mesh.transform(ob.matrix_world)

if props.rot_x90:
mesh.transform(mat_x90)

file = open(filepath, "wb")
theHeader = '//If not using MC3D, change 1 to 0 to add needed types\n#if 1\n\t#import "MC3DTypes.h"\n#else\n\
struct texCoord\n\
{\n\
GLfloat u;\n\
GLfloat v;\n\
};\n\
typedef struct texCoord texCoord;\n\
typedef texCoord* texCoordPtr;\n\
\n\
typedef struct vec2 vec2;\n\
typedef vec2* vec2Ptr;\n\
\n\
struct vec3\n\
{\n\
GLfloat x;\n\
GLfloat y;\n\
GLfloat z;\n\
};\n\
\n\
typedef struct vec3 vec3;\n\
typedef vec3* vec3Ptr;\n\
\n\
struct vec4\n\
{\n\
GLfloat x;\n\
GLfloat y;\n\
GLfloat z;\n\
GLfloat w;\n\
};\n\
\n\
typedef struct vec4 vec4;\n\
typedef vec4* vec4Ptr;\n\
\n\
#endif\n\
\n'
writeString(file, theHeader)

if len(mesh.uv_textures) > 0:
writeString(file, 'struct vertexDataTextured\n\
{\n\
vec3 vertex;\n\
vec3 normal;\n\
texCoord texCoord;\n\
}\n\
typedef struct vertexDataTextured vertexDataTextured;\n\
typedef vertexDataTextured* vertexDataTexturedPtr;\n\n\n')
writeString(file, 'static const vertexDataTextured %sVertexData[] = {\n' % basename)
#for face in uv: #loop through the faces
#uv_layer = mesh.uv_layers.active
#for face in mesh.tessfaces:
# faceUV = uv_layer.data[face.index]
# i=0
# for index in face.vertices:
# if len(face.vertices) == 3:
# vert = mesh.vertices[index]
# writeString(file, '\t{/*v:*/{%f, %f, %f}, ' % (vert.co.x, vert.co.y, vert.co.z) )
# writeString(file, '/*n:*/{%f, %f, %f}, ' % (vert.normal.x, vert.normal.y, vert.normal.z))
# writeString(file, '/*t:*/{%f, %f}' % ( faceUV.uv[i][0], faceUV.uv[i][1] ) )
# writeString(file, '},\n')
# i+=1
# Print all the vertices using mesh.loops
uv_layer = mesh.uv_layers.active.data
for poly in mesh.polygons:
#writeString(file, "// Polygon index: %d, length: %d\n" % (poly.index, poly.loop_total))
# range is used here to show how the polygons reference loops,
# for convenience 'poly.loop_indices' can be used instead.
for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total):
i=mesh.loops[loop_index].vertex_index
vert=mesh.vertices[i]
writeString(file, '\t{/*v:*/{%f, %f, %f}, ' % (vert.co.x, vert.co.y, vert.co.z) )
writeString(file, '/*n:*/{%f, %f, %f}, ' % (vert.normal.x, vert.normal.z, -vert.normal.y) )
writeString(file, '/*t:*/{%f, %f}' % ( uv_layer[loop_index].uv[0], uv_layer[loop_index].uv[1] ) )
writeString(file, '},\n')
writeString(file, '};\n\n')
elif len(mesh.vertex_colors) > 0:
writeString(file, 'struct vertexDataColored\n\
{\n\
vec3 vertex;\n\
vec3 normal;\n\
vec4 color;\n\
}\n\
typedef struct vertexDataColored vertexDataColored;\n\
typedef vertexDataColored* vertexDataColoredPtr;\n\n\n')
writeString(file, 'static const vertexDataColored %sVertexData[] = {\n' % basename)
color_layer = mesh.vertex_colors.active
for face in mesh.tessfaces:
if len(face.vertices) == 3:
faceC = color_layer.data[face.index]
i=0
for index in face.vertices:
vert = mesh.vertices[index]
writeString(file, '\t{/*v:*/{%f, %f, %f}, ' % (vert.co.y, vert.co.z, vert.co.x) )
writeString(file, '/*n:*/{%f, %f, %f}, ' % (vert.normal.x, vert.normal.z, -vert.normal.y))
writeString(file, '/*c:*/{%f, %f, %f, %f}' % ( faceC.color1[i], faceC.color2[i], faceC.color3[i], faceC.color4[i]) )
writeString(file, '},\n')
i+=1
writeString(file, '};\n\n')
else:
writeString(file, 'struct vertexData\n\
{\n\
vec3 vertex;\n\
vec3 normal;\n\
}\n\
typedef struct vertexData vertexData;\n\
typedef vertexData* vertexDataPtr;\n\n\n')
writeString(file, 'static const vertexData %sVertexData[] = {\n' % basename)
for face in mesh.tessfaces:
if len(face.vertices) == 3:
for index in face.vertices:
vert = mesh.vertices[index]
writeString(file, '\t{/*v:*/{%f, %f, %f}, ' % (vert.co.x, vert.co.y, vert.co.z) )
writeString(file, '/*n:*/{%f, %f, %f} ' % (vert.normal.x, vert.normal.y, vert.normal.z))
writeString(file, '},\n')
writeString(file, '};\n\n')

writeString(file, '// Example OpenGL ES 1.1 Drawing Code:\n')
writeString(file, '// glEnableClientState(GL_VERTEX_ARRAY);\n')
if len(mesh.uv_textures) > 0:
writeString(file, '// glEnableClientState(GL_TEXTURE_COORD_ARRAY);\n')
elif len(mesh.vertex_colors) > 0:
writeString(file, '// glEnableClientState(GL_COLOR_ARRAY);\n')
writeString(file, '// glEnable(GL_COLOR_MATERIAL)\n')
writeString(file, '// glEnableClientState(GL_NORMAL_ARRAY);\n')
writeString(file, '// glVertexPointer(3, GL_FLOAT, sizeof(')
if len(mesh.uv_textures) > 0:
writeString(file, 'TexturedVertexData3D')
elif len(mesh.vertex_colors) > 0:
writeString(file, 'ColoredVertexData3D')
else:
writeString(file, 'VertexData3D')
writeString(file, '), &%sVertexData[0].vertex);\n' % basename)
writeString(file, '// glNormalPointer(GL_FLOAT, sizeof(')
if len(mesh.uv_textures) > 0:
writeString(file, 'TexturedVertexData3D')
elif len(mesh.vertex_colors) > 0:
writeString(file, 'ColoredVertexData3D')
else:
writeString(file, 'VertexData3D')
writeString(file, '), &%sVertexData[0].normal);\n' % basename)
if len(mesh.uv_textures) > 0:
writeString(file, '// glTexCoordPointer(2, GL_FLOAT, sizeof(TexturedVertexData3D), &%sVertexData[0].texCoord);\n' % basename)
elif len(mesh.vertex_colors) > 0:
writeString(file, '// glColorPointer(4, GL_FLOAT, sizeof(ColoredVertexData3D), &%sVertexData[0].color);\n' % basename)
writeString(file, '// glDrawArrays(GL_TRIANGLES, 0, k%sNumberOfVertices);\n' % basename)
writeString(file, '// glDisableClientState(GL_VERTEX_ARRAY);\n')
if len(mesh.uv_textures) > 0:
writeString(file, '// glDisableClientState(GL_TEXTURE_COORD_ARRAY);\n')
elif len(mesh.vertex_colors) > 0:
writeString(file, '// glDisableClientState(GL_NORMAL_ARRAY);\n')
writeString(file, '// glDisable(GL_COLOR_MATERIAL);\n')
writeString(file, '// glDisableClientState(GL_NORMAL_ARRAY);\n\n\n')


file.flush()
file.close()

return True


###### EXPORT OPERATOR #######
class Export_objc(bpy.types.Operator, ExportHelper):
'''Exports the active Object as an Objective-C Header File.'''
bl_idname = "export_object.objc"
bl_label = "Export Objective-C Header (.h)"

filename_ext = ".h"

apply_modifiers = BoolProperty(name="Apply Modifiers",
description="Applies the Modifiers",
default=True)

rot_x90 = BoolProperty(name="Convert to Y-up",
description="Rotate 90 degrees around X to convert to y-up",
default=True)

world_space = BoolProperty(name="Export into Worldspace",
description="Transform the Vertexcoordinates into Worldspace",
default=False)


@classmethod
def poll(cls, context):
return context.active_object.type in ['MESH', 'CURVE', 'SURFACE', 'FONT']

def execute(self, context):
start_time = time.time()
print('\n_____START_____')
props = self.properties
filepath = self.filepath
filepath = bpy.path.ensure_ext(filepath, self.filename_ext)

exported = do_export(context, props, filepath)

if exported:
print('finished export in %s seconds' %((time.time() - start_time)))
print(filepath)

return {'FINISHED'}

def invoke(self, context, event):
wm = context.window_manager

if True:
# File selector
wm.fileselect_add(self) # will run self.execute()
return {'RUNNING_MODAL'}
elif True:
# search the enum
wm.invoke_search_popup(self)
return {'RUNNING_MODAL'}
elif False:
# Redo popup
return wm.invoke_props_popup(self, event) #
elif False:
return self.execute(context)


### REGISTER ###

def menu_func(self, context):
self.layout.operator(Export_objc.bl_idname, text="Objective-C Header (.h)")

def register():
bpy.utils.register_module(__name__)

bpy.types.INFO_MT_file_export.append(menu_func)

def unregister():
bpy.utils.unregister_module(__name__)

bpy.types.INFO_MT_file_export.remove(menu_func)

if __name__ == "__main__":
register()