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;
     7.1 --- a/src/mesh.h	Wed Oct 09 16:40:59 2013 +0300
     7.2 +++ b/src/mesh.h	Sun Oct 13 10:14:19 2013 +0300
     7.3 @@ -13,6 +13,9 @@
     7.4  
     7.5  struct Int4 {
     7.6  	int x, y, z, w;
     7.7 +
     7.8 +	Int4();
     7.9 +	Int4(int x, int y, int z, int w);
    7.10  };
    7.11  
    7.12  class Mesh : public Object {