Optimized ASCII model format to use indexed UVs. Updated OBJ slim converter and Loader accordingly.

This saves ~22% from size of textured ASCII models.

TODO: make the same for binary model format.
This commit is contained in:
alteredq
2010-11-08 18:10:43 +01:00
parent b14f09be61
commit 188f36be5d
12 changed files with 271 additions and 141 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -241,11 +241,11 @@
bwebgl.addEventListener("click", toggleWebGL, false);
var loader = new THREE.Loader();
loader.loadAsciiOld( "obj/male02/male02.js", function() { createScene( new Male02( "obj/male02" ), 90, 50, FLOOR, 105 ) } );
loader.loadAsciiOld( "obj/female02/female02.js", function() { createScene( new Female02( "obj/female02" ), -80, 50, FLOOR, 0 ) } );
//loader.loadAsciiOld( "obj/male02/male02.js", function() { createScene( new Male02( "obj/male02" ), 90, 50, FLOOR, 105 ) } );
//loader.loadAsciiOld( "obj/female02/female02.js", function() { createScene( new Female02( "obj/female02" ), -80, 50, FLOOR, 0 ) } );
//loader.loadAscii( "obj/male02/Male02_slim.js", function( geometry ) { createScene( geometry, 90, 50, FLOOR, 105 ) }, "obj/male02" );
//loader.loadAscii( "obj/female02/Female02_slim.js", function( geometry ) { createScene( geometry, -80, 50, FLOOR, 0 ) }, "obj/female02" );
loader.loadAscii( "obj/male02/Male02_slim.js", function( geometry ) { createScene( geometry, 90, 50, FLOOR, 105 ) }, "obj/male02" );
loader.loadAscii( "obj/female02/Female02_slim.js", function( geometry ) { createScene( geometry, -80, 50, FLOOR, 0 ) }, "obj/female02" );
//loader.loadBinary( "obj/male02/Male02_bin.js", function( geometry ) { createScene( geometry, 90, 50, FLOOR, 105 ) }, "obj/male02" );
//loader.loadBinary( "obj/female02/Female02_bin.js", function( geometry ) { createScene( geometry, -80, 50, FLOOR, 0 ) }, "obj/female02" );
+144 -76
View File
@@ -579,7 +579,6 @@ THREE.Loader.prototype = {
init_materials();
init_vertices();
init_uvs();
init_faces();
this.computeCentroids();
@@ -600,108 +599,177 @@ THREE.Loader.prototype = {
}
function init_uvs() {
var i, l, ua, ub, uc, ud, va, vb, vc, vd;
for( i = 0, l = data.uvs_tri.length; i < l; i++ ) {
ua = data.uvs_tri[ i*6 ];
va = data.uvs_tri[ i*6 + 1 ];
ub = data.uvs_tri[ i*6 + 2 ];
vb = data.uvs_tri[ i*6 + 3 ];
uc = data.uvs_tri[ i*6 + 4 ];
vc = data.uvs_tri[ i*6 + 5 ];
uv( ua, va, ub, vb, uc, vc );
}
for( i = 0, l = data.uvs_quad.length; i < l; i++ ) {
ua = data.uvs_quad[ i*8 ];
va = data.uvs_quad[ i*8 + 1 ];
ub = data.uvs_quad[ i*8 + 2 ];
vb = data.uvs_quad[ i*8 + 3 ];
uc = data.uvs_quad[ i*8 + 4 ];
vc = data.uvs_quad[ i*8 + 5 ];
ud = data.uvs_quad[ i*8 + 6 ];
vd = data.uvs_quad[ i*8 + 7 ];
uv( ua, va, ub, vb, uc, vc, ud, vd );
}
}
function init_faces() {
var i, l, a, b, c, d, m, na, nb, nc, nd;
var i, l;
for( i = 0, l = data.triangles.length/4; i < l; i++ ) {
function add_tri( src, i, stride ) {
var a, b, c, m;
a = data.triangles[ i*4 ];
b = data.triangles[ i*4 + 1 ];
c = data.triangles[ i*4 + 2 ];
a = src[ i*stride ];
b = src[ i*stride + 1 ];
c = src[ i*stride + 2 ];
m = data.triangles[ i*4 + 3 ];
m = src[ i*stride + 3 ];
f3( a, b, c, m );
}
for( i = 0, l = data.triangles_n.length/7; i < l; i++ ) {
function add_tri_n( src, i, stride ) {
a = data.triangles_n[ i*7 ];
b = data.triangles_n[ i*7 + 1 ];
c = data.triangles_n[ i*7 + 2 ];
var a, b, c, m, na, nb, nc;
m = data.triangles_n[ i*7 + 3 ];
a = src[ i*stride ];
b = src[ i*stride + 1 ];
c = src[ i*stride + 2 ];
na = data.triangles_n[ i*7 + 4 ];
nb = data.triangles_n[ i*7 + 5 ];
nc = data.triangles_n[ i*7 + 6 ];
m = src[ i*stride + 3 ];
na = src[ i*stride + 4 ];
nb = src[ i*stride + 5 ];
nc = src[ i*stride + 6 ];
f3n( a, b, c, m, na, nb, nc );
}
for( i = 0, l = data.quads.length/5; i < l; i++ ) {
function add_quad( src, i, stride ) {
a = data.quads[ i*5 ];
b = data.quads[ i*5 + 1 ];
c = data.quads[ i*5 + 2 ];
d = data.quads[ i*5 + 3 ];
var a, b, c, d, m;
m = data.quads[ i*5 + 4 ];
a = src[ i*stride ];
b = src[ i*stride + 1 ];
c = src[ i*stride + 2 ];
d = src[ i*stride + 3 ];
m = src[ i*stride + 4 ];
f4( a, b, c, d, m );
}
for( i = 0, l = data.quads_n.length/9; i < l; i++ ) {
function add_quad_n( src, i, stride ) {
a = data.quads_n[ i*9 ];
b = data.quads_n[ i*9 + 1 ];
c = data.quads_n[ i*9 + 2 ];
d = data.quads_n[ i*9 + 3 ];
var a, b, c, d, m, na, nb, nc, nd;
m = data.quads_n[ i*9 + 4 ];
a = src[ i*stride ];
b = src[ i*stride + 1 ];
c = src[ i*stride + 2 ];
d = src[ i*stride + 3 ];
na = data.quads_n[ i*9 + 5 ];
nb = data.quads_n[ i*9 + 6 ];
nc = data.quads_n[ i*9 + 7 ];
nd = data.quads_n[ i*9 + 8 ];
m = src[ i*stride + 4 ];
na = src[ i*stride + 5 ];
nb = src[ i*stride + 6 ];
nc = src[ i*stride + 7 ];
nd = src[ i*stride + 8 ];
f4n( a, b, c, d, m, na, nb, nc, nd );
}
function add_uv3( src, i, stride, offset ) {
var uva, uvb, uvc, u1, u2, u3, v1, v2, v3;
uva = src[ i*stride + offset ];
uvb = src[ i*stride + offset + 1 ];
uvc = src[ i*stride + offset + 2 ];
u1 = data.uvs[ uva*2 ];
v1 = data.uvs[ uva*2 + 1 ];
u2 = data.uvs[ uvb*2 ];
v2 = data.uvs[ uvb*2 + 1 ];
u3 = data.uvs[ uvc*2 ];
v3 = data.uvs[ uvc*2 + 1 ];
uv( u1, v1, u2, v2, u3, v3 );
}
function add_uv4( src, i, stride, offset ) {
var uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4;
uva = src[ i*stride + offset ];
uvb = src[ i*stride + offset + 1 ];
uvc = src[ i*stride + offset + 2 ];
uvd = src[ i*stride + offset + 3 ];
u1 = data.uvs[ uva*2 ];
v1 = data.uvs[ uva*2 + 1 ];
u2 = data.uvs[ uvb*2 ];
v2 = data.uvs[ uvb*2 + 1 ];
u3 = data.uvs[ uvc*2 ];
v3 = data.uvs[ uvc*2 + 1 ];
u4 = data.uvs[ uvd*2 ];
v4 = data.uvs[ uvd*2 + 1 ];
uv( u1, v1, u2, v2, u3, v3, u4, v4 );
}
for( i = 0, l = data.triangles.length/4; i < l; i++ ) {
add_tri( data.triangles, i, 4 );
}
for( i = 0, l = data.triangles_uv.length/7; i < l; i++ ) {
add_tri( data.triangles_uv, i, 7 );
add_uv3( data.triangles_uv, i, 7, 4 );
}
for( i = 0, l = data.triangles_n.length/7; i < l; i++ ) {
add_tri_n( data.triangles_n, i, 7 );
}
for( i = 0, l = data.triangles_n_uv.length/10; i < l; i++ ) {
add_tri_n( data.triangles_n_uv, i, 10 );
add_uv3( data.triangles_n_uv, i, 10, 7 );
}
for( i = 0, l = data.quads.length/5; i < l; i++ ) {
add_quad( data.quads, i, 5 );
}
for( i = 0, l = data.quads_uv.length/9; i < l; i++ ) {
add_quad( data.quads_uv, i, 9 );
add_uv4( data.quads_uv, i, 9, 5 );
}
for( i = 0, l = data.quads_n.length/9; i < l; i++ ) {
add_quad_n( data.quads_n, i, 9 );
}
for( i = 0, l = data.quads_n_uv.length/13; i < l; i++ ) {
add_quad_n( data.quads_n_uv, i, 13 );
add_uv4( data.quads_n_uv, i, 13, 9 );
}
}
function v( x, y, z ) {
@@ -709,14 +777,14 @@ THREE.Loader.prototype = {
scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
}
function f3( a, b, c, mi ) {
var material = scope.materials[ mi ];
scope.faces.push( new THREE.Face3( a, b, c, null, material ) );
}
function f4( a, b, c, d, mi ) {
var material = scope.materials[ mi ];
@@ -769,7 +837,7 @@ THREE.Loader.prototype = {
material ) );
}
function uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {
var uv = [];
+94 -47
View File
@@ -156,14 +156,17 @@ var model = {
'vertices': [%(vertices)s],
'uvs_tri': [%(uvs_tri)s],
'uvs_quad': [%(uvs_quad)s],
'uvs': [%(uvs)s],
'triangles': [%(triangles)s],
'triangles_n': [%(triangles_n)s],
'triangles_uv': [%(triangles_uv)s],
'triangles_n_uv': [%(triangles_n_uv)s],
'quads': [%(quads)s],
'quads_n': [%(quads_n)s],
'quads_uv': [%(quads_uv)s],
'quads_n_uv': [%(quads_n_uv)s],
'end': (new Date).getTime()
}
@@ -197,13 +200,20 @@ TEMPLATE_VERTEX = "%f,%f,%f"
TEMPLATE_UV_TRI = "%f,%f,%f,%f,%f,%f"
TEMPLATE_UV_QUAD = "%f,%f,%f,%f,%f,%f,%f,%f"
TEMPLATE_TRI = "%d,%d,%d,%d"
TEMPLATE_QUAD = "%d,%d,%d,%d,%d"
TEMPLATE_TRI = "%d,%d,%d,%d"
TEMPLATE_QUAD = "%d,%d,%d,%d,%d"
TEMPLATE_TRI_N = "%d,%d,%d,%d,%d,%d,%d"
TEMPLATE_QUAD_N = "%d,%d,%d,%d,%d,%d,%d,%d,%d"
TEMPLATE_TRI_UV = "%d,%d,%d,%d,%d,%d,%d"
TEMPLATE_QUAD_UV = "%d,%d,%d,%d,%d,%d,%d,%d,%d"
TEMPLATE_TRI_N = "%d,%d,%d,%d,%d,%d,%d"
TEMPLATE_QUAD_N = "%d,%d,%d,%d,%d,%d,%d,%d,%d"
TEMPLATE_TRI_N_UV = "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d"
TEMPLATE_QUAD_N_UV = "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d"
TEMPLATE_N = "%f,%f,%f"
TEMPLATE_UV = "%f,%f"
# #####################################################
# Utils
@@ -548,40 +558,68 @@ def parse_obj(fname):
def generate_vertex(v):
return TEMPLATE_VERTEX % (v[0], v[1], v[2])
def generate_uv_tri(f, uvs):
ui = f['uv']
return TEMPLATE_UV_TRI % (uvs[ui[0]-1][0], 1.0 - uvs[ui[0]-1][1],
uvs[ui[1]-1][0], 1.0 - uvs[ui[1]-1][1],
uvs[ui[2]-1][0], 1.0 - uvs[ui[2]-1][1])
def generate_uv_quad(f, uvs):
ui = f['uv']
return TEMPLATE_UV_QUAD % (uvs[ui[0]-1][0], 1.0 - uvs[ui[0]-1][1],
uvs[ui[1]-1][0], 1.0 - uvs[ui[1]-1][1],
uvs[ui[2]-1][0], 1.0 - uvs[ui[2]-1][1],
uvs[ui[3]-1][0], 1.0 - uvs[ui[3]-1][1])
def generate_triangle(f):
vi = f['vertex']
return TEMPLATE_TRI % (vi[0]-1, vi[1]-1, vi[2]-1, f['material'])
v = f['vertex']
return TEMPLATE_TRI % (v[0]-1, v[1]-1, v[2]-1,
f['material'])
def generate_triangle_uv(f):
v = f['vertex']
uv = f['uv']
return TEMPLATE_TRI_UV % (v[0]-1, v[1]-1, v[2]-1,
f['material'],
uv[0]-1, uv[1]-1, uv[2]-1)
def generate_triangle_n(f):
vi = f['vertex']
ni = f['normal']
return TEMPLATE_TRI_N % (vi[0]-1, vi[1]-1, vi[2]-1, f['material'], ni[0]-1, ni[1]-1, ni[2]-1)
v = f['vertex']
n = f['normal']
return TEMPLATE_TRI_N % (v[0]-1, v[1]-1, v[2]-1,
f['material'],
n[0]-1, n[1]-1, n[2]-1)
def generate_triangle_n_uv(f):
v = f['vertex']
n = f['normal']
uv = f['uv']
return TEMPLATE_TRI_N_UV % (v[0]-1, v[1]-1, v[2]-1,
f['material'],
n[0]-1, n[1]-1, n[2]-1,
uv[0]-1, uv[1]-1, uv[2]-1)
def generate_quad(f):
vi = f['vertex']
return TEMPLATE_QUAD % (vi[0]-1, vi[1]-1, vi[2]-1, vi[3]-1, f['material'])
return TEMPLATE_QUAD % (vi[0]-1, vi[1]-1, vi[2]-1, vi[3]-1,
f['material'])
def generate_quad_uv(f):
v = f['vertex']
uv = f['uv']
return TEMPLATE_QUAD_UV % (v[0]-1, v[1]-1, v[2]-1, v[3]-1,
f['material'],
uv[0]-1, uv[1]-1, uv[2]-1, uv[3]-1)
def generate_quad_n(f):
vi = f['vertex']
ni = f['normal']
return TEMPLATE_QUAD_N % (vi[0]-1, vi[1]-1, vi[2]-1, vi[3]-1, f['material'], ni[0]-1, ni[1]-1, ni[2]-1, ni[3]-1)
v = f['vertex']
n = f['normal']
return TEMPLATE_QUAD_N % (v[0]-1, v[1]-1, v[2]-1, v[3]-1,
f['material'],
n[0]-1, n[1]-1, n[2]-1, n[3]-1)
def generate_quad_n_uv(f):
v = f['vertex']
n = f['normal']
uv = f['uv']
return TEMPLATE_QUAD_N_UV % (v[0]-1, v[1]-1, v[2]-1, v[3]-1,
f['material'],
n[0]-1, n[1]-1, n[2]-1, n[3]-1,
uv[0]-1, uv[1]-1, uv[2]-1, uv[3]-1)
def generate_normal(n):
return TEMPLATE_N % (n[0], n[1], n[2])
def generate_uv(uv):
return TEMPLATE_UV % (uv[0], 1.0 - uv[1])
# #####################################################
# Materials
# #####################################################
@@ -675,16 +713,28 @@ def generate_materials_string(materials, mtllib):
# Faces
# #####################################################
def is_triangle_flat(f):
return len(f['vertex'])==3 and not (f["normal"] and SHADING == "smooth")
return len(f['vertex'])==3 and not (f["normal"] and SHADING == "smooth") and not f['uv']
def is_triangle_flat_uv(f):
return len(f['vertex'])==3 and not (f["normal"] and SHADING == "smooth") and len(f['uv'])==3
def is_triangle_smooth(f):
return len(f['vertex'])==3 and f["normal"] and SHADING == "smooth"
return len(f['vertex'])==3 and f["normal"] and SHADING == "smooth" and not f['uv']
def is_triangle_smooth_uv(f):
return len(f['vertex'])==3 and f["normal"] and SHADING == "smooth" and len(f['uv'])==3
def is_quad_flat(f):
return len(f['vertex'])==4 and not (f["normal"] and SHADING == "smooth")
return len(f['vertex'])==4 and not (f["normal"] and SHADING == "smooth") and not f['uv']
def is_quad_flat_uv(f):
return len(f['vertex'])==4 and not (f["normal"] and SHADING == "smooth") and len(f['uv'])==4
def is_quad_smooth(f):
return len(f['vertex'])==4 and f["normal"] and SHADING == "smooth"
return len(f['vertex'])==4 and f["normal"] and SHADING == "smooth" and not f['uv']
def is_quad_smooth_uv(f):
return len(f['vertex'])==4 and f["normal"] and SHADING == "smooth" and len(f['uv'])==4
# #####################################################
# API - ASCII converter
@@ -708,27 +758,24 @@ def convert_ascii(infile, outfile):
bottom(vertices)
elif ALIGN == "top":
top(vertices)
uv_string_tri = ""
uv_string_quad = ""
if len(uvs)>0:
uv_string_tri = ",".join([generate_uv_tri(f, uvs) for f in faces if len(f['uv']) == 3])
uv_string_quad = ",".join([generate_uv_quad(f, uvs) for f in faces if len(f['uv']) == 4])
normals_string = ""
if SHADING == "smooth":
normals_string = ",".join(generate_normal(n) for n in normals)
text = TEMPLATE_FILE_ASCII % {
"name" : get_name(outfile),
"vertices" : ",".join([generate_vertex(v) for v in vertices]),
"triangles" : ",".join([generate_triangle(f) for f in faces if is_triangle_flat(f)]),
"triangles_n": ",".join([generate_triangle_n(f) for f in faces if is_triangle_smooth(f)]),
"quads" : ",".join([generate_quad(f) for f in faces if is_quad_flat(f)]),
"quads_n" : ",".join([generate_quad_n(f) for f in faces if is_quad_smooth(f)]),
"uvs_tri" : uv_string_tri,
"uvs_quad" : uv_string_quad,
"normals" : normals_string,
"name" : get_name(outfile),
"vertices" : ",".join([generate_vertex(v) for v in vertices]),
"triangles" : ",".join([generate_triangle(f) for f in faces if is_triangle_flat(f)]),
"triangles_n" : ",".join([generate_triangle_n(f) for f in faces if is_triangle_smooth(f)]),
"triangles_uv" : ",".join([generate_triangle_uv(f) for f in faces if is_triangle_flat_uv(f)]),
"triangles_n_uv": ",".join([generate_triangle_n_uv(f) for f in faces if is_triangle_smooth_uv(f)]),
"quads" : ",".join([generate_quad(f) for f in faces if is_quad_flat(f)]),
"quads_n" : ",".join([generate_quad_n(f) for f in faces if is_quad_smooth(f)]),
"quads_uv" : ",".join([generate_quad_uv(f) for f in faces if is_quad_flat_uv(f)]),
"quads_n_uv" : ",".join([generate_quad_n_uv(f) for f in faces if is_quad_smooth_uv(f)]),
"uvs" : ",".join([generate_uv(uv) for uv in uvs]),
"normals" : normals_string,
"materials" : generate_materials_string(materials, mtllib),