goat3d
changeset 40:a5c5cec3cb88
- added mesh attribute and face append functions
- added Int4 constructor
- continued the blender exporter
- fixed a bug in clean_filename which made it produce unterminated strings
- renamed clean_filename to goat3d_clean_filename and made it extern
- added call to goat3d_clean_filename in the mesh XML export code to cleanup ctm filenames
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 13 Oct 2013 10:14:19 +0300 |
parents | 0e48907847ad |
children | da3f335e0069 |
files | exporters/blendgoat/src/export_goat.py src/goat3d.cc src/goat3d.h src/goat3d_impl.h src/goat3d_writexml.cc src/mesh.cc src/mesh.h |
diffstat | 7 files changed, 186 insertions(+), 24 deletions(-) [+] |
line diff
1.1 --- a/exporters/blendgoat/src/export_goat.py Wed Oct 09 16:40:59 2013 +0300 1.2 +++ b/exporters/blendgoat/src/export_goat.py Sun Oct 13 10:14:19 2013 +0300 1.3 @@ -1,9 +1,28 @@ 1.4 # Goat3D Blender >2.63 exporter 1.5 -import bpy; 1.6 +import bpy 1.7 import ctypes 1.8 from ctypes import * 1.9 from ctypes.util import find_library 1.10 1.11 +GOAT3D_MAT_ATTR_DIFFUSE = "diffuse".encode('utf-8') 1.12 +GOAT3D_MAT_ATTR_SPECULAR = "specular".encode('utf-8') 1.13 +GOAT3D_MAT_ATTR_SHININESS = "shininess".encode('utf-8') 1.14 +GOAT3D_MAT_ATTR_NORMAL = "normal".encode('utf-8') 1.15 +GOAT3D_MAT_ATTR_BUMP = "bump".encode('utf-8') 1.16 +GOAT3D_MAT_ATTR_REFLECTION = "reflection".encode('utf-8') 1.17 +GOAT3D_MAT_ATTR_TRANSMISSION = "transmission".encode('utf-8') 1.18 +GOAT3D_MAT_ATTR_IOR = "ior".encode('utf-8') 1.19 +GOAT3D_MAT_ATTR_ALPHA = "alpha".encode('utf-8') 1.20 + 1.21 +# these must match the goat3d_vertex_attr enumeration values in goat3d.h 1.22 +GOAT3D_MESH_ATTR_VERTEX = 0 1.23 +GOAT3D_MESH_ATTR_NORMAL = 1 1.24 +GOAT3D_MESH_ATTR_TANGENT = 2 1.25 +GOAT3D_MESH_ATTR_TEXCOORD = 3 1.26 +GOAT3D_MESH_ATTR_SKIN_WEIGHT = 4 1.27 +GOAT3D_MESH_ATTR_SKIN_MATRIX = 5 1.28 +GOAT3D_MESH_ATTR_COLOR = 6 1.29 + 1.30 1.31 def export(oper, ctx, fname): 1.32 print("Exporting goat3d file: " + fname) 1.33 @@ -21,7 +40,6 @@ 1.34 lib.goat3d_set_name(goat, fname.encode('utf-8')) 1.35 1.36 export_env(ctx, goat, lib) 1.37 - export_materials(ctx, goat, lib) 1.38 export_meshes(ctx, goat, lib) 1.39 export_nodes(ctx, goat, lib) 1.40 1.41 @@ -32,8 +50,60 @@ 1.42 def export_env(ctx, goat, lib): 1.43 return False 1.44 1.45 -def export_materials(ctx, goat, lib): 1.46 - return False 1.47 +def export_material(bmtl, goat, lib): 1.48 + name = bmtl.name.encode("utf-8") 1.49 + 1.50 + mtl = lib.goat3d_create_mtl() 1.51 + lib.goat3d_set_mtl_name(mtl, name) 1.52 + 1.53 + s = bmtl.diffuse_intensity 1.54 + col = bmtl.diffuse_color 1.55 + lib.goat3d_set_mtl_attrib4f(mtl, GOAT3D_MAT_ATTR_DIFFUSE, c_float(col[0] * s), c_float(col[1] * s), c_float(col[2] * s), 1.0) 1.56 + 1.57 + s = bmtl.specular_intensity 1.58 + col = bmtl.specular_color 1.59 + lib.goat3d_set_mtl_attrib4f(mtl, GOAT3D_MAT_ATTR_SPECULAR, c_float(col[0] * s), c_float(col[1] * s), c_float(col[2] * s), 1.0) 1.60 + lib.goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_SHININESS, c_float(bmtl.specular_hardness)) 1.61 + lib.goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_ALPHA, c_float(bmtl.alpha)) 1.62 + 1.63 + if bmtl.raytrace_mirror.use: 1.64 + lib.goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_REFLECTION, c_float(bmtl.raytrace_mirror.reflect_factor)) 1.65 + if bmtl.use_transparency and bmtl.transparency_method == 'RAYTRACE': 1.66 + lib.goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_IOR, c_float(bmtl.raytrace_transparency.ior)) 1.67 + lib.goat3d_set_mtl_attrib1f(mtl, GOAT3D_MAT_ATTR_TRANSMISSION, 1.0) 1.68 + 1.69 + # grab all the textures and apply them to the correct attributes 1.70 + for texslot in bmtl.texture_slots: 1.71 + if not texslot: 1.72 + continue 1.73 + 1.74 + tex = texslot.texture 1.75 + if tex.type != 'IMAGE': 1.76 + print("ignoring texture " + tex.name + ": not an image!") 1.77 + continue 1.78 + 1.79 + fname = tex.image.filepath.encode('ascii') 1.80 + 1.81 + attr = "" 1.82 + if texslot.use_map_color_diffuse or texslot.use_map_diffuse: 1.83 + attr = GOAT3D_MAT_ATTR_DIFFUSE 1.84 + elif texslot.use_map_color_spec or texslot.use_map_specular: 1.85 + attr = GOAT3D_MAT_ATTR_SPECULAR 1.86 + elif texslot.use_map_color_reflection or texslot.use_map_reflect: 1.87 + attr = GOAT3D_MAT_ATTR_REFLECTION 1.88 + elif texslot.use_map_hardness: 1.89 + attr = GOAT3D_MAT_ATTR_SHININESS 1.90 + elif texslot.use_map_alpha: 1.91 + attr = GOAT3D_MAT_ATTR_ALPHA 1.92 + elif texslot.use_map_normal: 1.93 + attr = GOAT3D_MAT_ATTR_NORMAL 1.94 + 1.95 + if attr != "": 1.96 + lib.goat3d_set_mtl_attrib_map(mtl, attr, fname) 1.97 + 1.98 + lib.goat3d_add_mtl(goat, mtl) 1.99 + return mtl 1.100 + 1.101 1.102 def export_meshes(ctx, goat, lib): 1.103 print("exporting " + str(len(ctx.scene.objects)) + " objects") 1.104 @@ -41,20 +111,31 @@ 1.105 if obj.type != 'MESH': 1.106 continue 1.107 1.108 - mesh = obj.data 1.109 + bmesh = obj.data 1.110 # make sure we get a tesselated mesh 1.111 - mesh.update(calc_tessface = True) 1.112 + bmesh.update(calc_tessface = True) 1.113 1.114 - triangles = [] 1.115 - for idx, face in enumerate(mesh.tessfaces): 1.116 + # create goat3d mesh and set the data 1.117 + mesh = lib.goat3d_create_mesh() 1.118 + lib.goat3d_set_mesh_name(mesh, bmesh.name.encode("utf-8")) 1.119 + 1.120 + # get the material, add it to the scene and apply it to this mesh 1.121 + for bmtl in bmesh.materials: 1.122 + mtl = export_material(bmtl, goat, lib) 1.123 + lib.goat3d_set_mesh_mtl(mesh, mtl) 1.124 + break # we only care about one material 1.125 + 1.126 + for vert in bmesh.vertices: 1.127 + v = vert.co 1.128 + n = vert.normal 1.129 + lib.goat3d_add_mesh_attrib3f(mesh, GOAT3D_MESH_ATTR_VERTEX, v[0], v[1], v[2]) 1.130 + lib.goat3d_add_mesh_attrib3f(mesh, GOAT3D_MESH_ATTR_NORMAL, n[0], n[1], n[2]) 1.131 + 1.132 + for face in bmesh.tessfaces: 1.133 fverts = face.vertices 1.134 - triangles.append(fverts[0]) 1.135 - triangles.append(fverts[1]) 1.136 - triangles.append(fverts[2]) 1.137 + lib.goat3d_add_mesh_face(mesh, fverts[0], fverts[1], fverts[2]) 1.138 1.139 - print("creating native array of " + str(len(triangles)) + " triangles") 1.140 - IndexArrayType = c_int * len(triangles) 1.141 - indices = IndexArrayType(triangles) 1.142 + lib.goat3d_add_mesh(goat, mesh) 1.143 return False 1.144 1.145 1.146 @@ -93,6 +174,9 @@ 1.147 lib.goat3d_set_mtl_name.argtypes = [c_void_p, c_char_p] 1.148 lib.goat3d_set_mtl_name.restype = None 1.149 1.150 + lib.goat3d_set_mtl_attrib1f.argtypes = [c_void_p, c_char_p, c_float] 1.151 + lib.goat3d_set_mtl_attrib1f.restype = None 1.152 + 1.153 lib.goat3d_set_mtl_attrib4f.argtypes = [c_void_p, c_char_p, c_float, c_float, c_float, c_float] 1.154 lib.goat3d_set_mtl_attrib4f.restype = None 1.155 1.156 @@ -111,11 +195,14 @@ 1.157 lib.goat3d_set_mesh_mtl.argtypes = [c_void_p, c_void_p] 1.158 lib.goat3d_set_mesh_mtl.restype = None 1.159 1.160 - lib.goat3d_set_mesh_attribs.argtypes = [c_void_p, c_int, c_void_p, c_int] 1.161 - lib.goat3d_set_mesh_attribs.restype = None 1.162 + lib.goat3d_add_mesh_attrib3f.argtypes = [c_void_p, c_int, c_float, c_float, c_float] 1.163 + lib.goat3d_add_mesh_attrib3f.restype = None 1.164 1.165 - lib.goat3d_set_mesh_faces.argtypes = [c_void_p, c_void_p, c_int] 1.166 - lib.goat3d_set_mesh_faces.restype = None 1.167 + lib.goat3d_add_mesh_attrib4f.argtypes = [c_void_p, c_int, c_float, c_float, c_float, c_float] 1.168 + lib.goat3d_add_mesh_attrib4f.restype = None 1.169 + 1.170 + lib.goat3d_add_mesh_face.argtypes = [c_void_p, c_int, c_int, c_int] 1.171 + lib.goat3d_add_mesh_face.restype = None 1.172 1.173 lib.goat3d_add_node.argtypes = [c_void_p, c_void_p] 1.174 lib.goat3d_add_node.restype = None
2.1 --- a/src/goat3d.cc Wed Oct 09 16:40:59 2013 +0300 2.2 +++ b/src/goat3d.cc Sun Oct 13 10:14:19 2013 +0300 2.3 @@ -29,8 +29,6 @@ 2.4 static long write_file(const void *buf, size_t bytes, void *uptr); 2.5 static long seek_file(long offs, int whence, void *uptr); 2.6 2.7 -static std::string clean_filename(const char *str); 2.8 - 2.9 extern "C" { 2.10 2.11 struct goat3d *goat3d_create(void) 2.12 @@ -228,7 +226,7 @@ 2.13 2.14 void goat3d_set_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib, const char *mapname) 2.15 { 2.16 - (*mtl)[attrib].map = clean_filename(mapname); 2.17 + (*mtl)[attrib].map = goat3d_clean_filename(mapname); 2.18 } 2.19 2.20 const char *goat3d_get_mtl_attrib_map(struct goat3d_material *mtl, const char *attrib) 2.21 @@ -333,6 +331,47 @@ 2.22 } 2.23 } 2.24 2.25 +void goat3d_add_mesh_attrib1f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, 2.26 + float val) 2.27 +{ 2.28 + goat3d_add_mesh_attrib4f(mesh, attrib, val, 0, 0, 1); 2.29 +} 2.30 + 2.31 +void goat3d_add_mesh_attrib3f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, 2.32 + float x, float y, float z) 2.33 +{ 2.34 + goat3d_add_mesh_attrib4f(mesh, attrib, x, y, z, 1); 2.35 +} 2.36 + 2.37 +void goat3d_add_mesh_attrib4f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, 2.38 + float x, float y, float z, float w) 2.39 +{ 2.40 + switch(attrib) { 2.41 + case GOAT3D_MESH_ATTR_VERTEX: 2.42 + mesh->vertices.push_back(Vector3(x, y, z)); 2.43 + break; 2.44 + case GOAT3D_MESH_ATTR_NORMAL: 2.45 + mesh->normals.push_back(Vector3(x, y, z)); 2.46 + break; 2.47 + case GOAT3D_MESH_ATTR_TANGENT: 2.48 + mesh->tangents.push_back(Vector3(x, y, z)); 2.49 + break; 2.50 + case GOAT3D_MESH_ATTR_TEXCOORD: 2.51 + mesh->texcoords.push_back(Vector2(x, y)); 2.52 + break; 2.53 + case GOAT3D_MESH_ATTR_SKIN_WEIGHT: 2.54 + mesh->skin_weights.push_back(Vector4(x, y, z, w)); 2.55 + break; 2.56 + case GOAT3D_MESH_ATTR_SKIN_MATRIX: 2.57 + mesh->skin_matrices.push_back(Int4(x, y, z, w)); 2.58 + break; 2.59 + case GOAT3D_MESH_ATTR_COLOR: 2.60 + mesh->colors.push_back(Vector4(x, y, z, w)); 2.61 + default: 2.62 + break; 2.63 + } 2.64 +} 2.65 + 2.66 void *goat3d_get_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib) 2.67 { 2.68 return goat3d_get_mesh_attrib(mesh, attrib, 0); 2.69 @@ -367,6 +406,15 @@ 2.70 mesh->faces = VECDATA(Face, data, num); 2.71 } 2.72 2.73 +void goat3d_add_mesh_face(struct goat3d_mesh *mesh, int a, int b, int c) 2.74 +{ 2.75 + Face face; 2.76 + face.v[0] = a; 2.77 + face.v[1] = b; 2.78 + face.v[2] = c; 2.79 + mesh->faces.push_back(face); 2.80 +} 2.81 + 2.82 int *goat3d_get_mesh_faces(struct goat3d_mesh *mesh) 2.83 { 2.84 return goat3d_get_mesh_face(mesh, 0); 2.85 @@ -738,7 +786,7 @@ 2.86 return ftell((FILE*)uptr); 2.87 } 2.88 2.89 -static std::string clean_filename(const char *str) 2.90 +std::string goat3d_clean_filename(const char *str) 2.91 { 2.92 const char *last_slash = strrchr(str, '/'); 2.93 if(!last_slash) { 2.94 @@ -755,5 +803,6 @@ 2.95 char c = *str++; 2.96 *dest++ = tolower(c); 2.97 } 2.98 + *dest = 0; 2.99 return buf; 2.100 }
3.1 --- a/src/goat3d.h Wed Oct 09 16:40:59 2013 +0300 3.2 +++ b/src/goat3d.h Sun Oct 13 10:14:19 2013 +0300 3.3 @@ -12,6 +12,7 @@ 3.4 #define GOAT3D_MAT_ATTR_REFLECTION "reflection" 3.5 #define GOAT3D_MAT_ATTR_TRANSMISSION "transmission" 3.6 #define GOAT3D_MAT_ATTR_IOR "ior" 3.7 +#define GOAT3D_MAT_ATTR_ALPHA "alpha" 3.8 3.9 enum goat3d_mesh_attrib { 3.10 GOAT3D_MESH_ATTR_VERTEX, 3.11 @@ -136,7 +137,13 @@ 3.12 * - GOAT3D_MESH_ATTR_SKIN_MATRIX - 4 ints per vertex 3.13 * - GOAT3D_MESH_ATTR_COLOR - 4 floats per vertex 3.14 */ 3.15 -void goat3d_set_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, const void *data, int vnum); 3.16 +void goat3d_set_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, 3.17 + const void *data, int vnum); 3.18 +void goat3d_add_mesh_attrib1f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, float val); 3.19 +void goat3d_add_mesh_attrib3f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, 3.20 + float x, float y, float z); 3.21 +void goat3d_add_mesh_attrib4f(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib, 3.22 + float x, float y, float z, float w); 3.23 /* returns a pointer to the beginning of the requested mesh attribute array */ 3.24 void *goat3d_get_mesh_attribs(struct goat3d_mesh *mesh, enum goat3d_mesh_attrib attrib); 3.25 /* returns a pointer to the requested mesh attribute */ 3.26 @@ -144,6 +151,7 @@ 3.27 3.28 /* sets all the faces in one go. data is an array of 3 int vertex indices per face */ 3.29 void goat3d_set_mesh_faces(struct goat3d_mesh *mesh, const int *data, int fnum); 3.30 +void goat3d_add_mesh_face(struct goat3d_mesh *mesh, int a, int b, int c); 3.31 /* returns a pointer to the beginning of the face index array */ 3.32 int *goat3d_get_mesh_faces(struct goat3d_mesh *mesh); 3.33 /* returns a pointer to a face index */
4.1 --- a/src/goat3d_impl.h Wed Oct 09 16:40:59 2013 +0300 4.2 +++ b/src/goat3d_impl.h Sun Oct 13 10:14:19 2013 +0300 4.3 @@ -21,6 +21,8 @@ 4.4 #define VECDATA(type, data, num) \ 4.5 MOVE(std::vector<type>((type*)(data), (type*)(data) + (num))) 4.6 4.7 +std::string goat3d_clean_filename(const char *str); 4.8 + 4.9 4.10 class Scene { 4.11 private:
5.1 --- a/src/goat3d_writexml.cc Wed Oct 09 16:40:59 2013 +0300 5.2 +++ b/src/goat3d_writexml.cc Sun Oct 13 10:14:19 2013 +0300 5.3 @@ -80,7 +80,7 @@ 5.4 if(mesh->material) { 5.5 xmlout(io, level + 1, "<material string=\"%s\"/>\n", mesh->material->name.c_str()); 5.6 } 5.7 - xmlout(io, level + 1, "<file string=\"%s\"/>\n", mesh_filename); 5.8 + xmlout(io, level + 1, "<file string=\"%s\"/>\n", goat3d_clean_filename(mesh_filename).c_str()); 5.9 xmlout(io, level, "</mesh>\n\n"); 5.10 return true; 5.11 }
6.1 --- a/src/mesh.cc Wed Oct 09 16:40:59 2013 +0300 6.2 +++ b/src/mesh.cc Sun Oct 13 10:14:19 2013 +0300 6.3 @@ -3,6 +3,19 @@ 6.4 #include "openctm.h" 6.5 #include "log.h" 6.6 6.7 +Int4::Int4() 6.8 +{ 6.9 + x = y = z = w = 0; 6.10 +} 6.11 + 6.12 +Int4::Int4(int x, int y, int z, int w) 6.13 +{ 6.14 + this->x = x; 6.15 + this->y = y; 6.16 + this->z = z; 6.17 + this->w = w; 6.18 +} 6.19 + 6.20 Mesh::Mesh() 6.21 { 6.22 material = 0;