Model exporter for blender. Simple model loader for PSP.
authorslack <slack@codemaniacs.com>
Sun, 5 Oct 2008 01:55:53 +0000 (03:55 +0200)
committerslack <slack@codemaniacs.com>
Sun, 5 Oct 2008 01:55:53 +0000 (03:55 +0200)
Makefile
game.cc
gfx.cc
model.cc [new file with mode: 0644]
model.h [new file with mode: 0644]
tools/blender_exporter.py [new file with mode: 0644]

index 3c3c8fbb7347414160c085d5a8d33d088e5140b1..109a3d30fff83fe6be0f99c3209cab94bbd43a24 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 TARGET = laz0r
-OBJS = main.o game.o gfx.o
+OBJS = main.o game.o gfx.o model.o
 
 PSP_FW_VERSION=401
 BUILD_PRX=1
@@ -13,5 +13,9 @@ LIBS = -lpspgum -lpspgu -lpsprtc -lstdc++ -lm
 LIBDIR =
 LDFLAGS =
 
+EXTRA_TARGETS=EBOOT.PBP
+PSP_EBOOT_TITLE=laz0r
+
+
 PSPSDK=$(shell psp-config --pspsdk-path)
 include $(PSPSDK)/lib/build.mak
diff --git a/game.cc b/game.cc
index fad9d39c0b0ce150cbd68138c7a0c84413db3d44..9b24946003a59c70b42cf6443cb93215d169959a 100644 (file)
--- a/game.cc
+++ b/game.cc
@@ -1,10 +1,13 @@
 #include "game.h"
 #include "gfx.h"
+#include "model.h"
 
 #include <pspgu.h>
 #include <pspgum.h>
 #include <psptypes.h>
 #include <pspdisplay.h>
+#include <pspkernel.h>
+
 
 float triangle[]={1,-1,0,-1,-1,0,0,1,0};
 
@@ -12,6 +15,13 @@ int game_main(int argc, char **argv)
 {
        GFX.init();
 
+       //Model cube("colors-noUV.lob");
+       Model cube("models/colors-noUV.lob");
+       //sceKernelDcacheWritebackRange(cube.vertices, cube.num_vertices * sizeof(Vertex));
+       //sceKernelDcacheWritebackRange(cube.indices, cube.num_faces * sizeof(unsigned short));
+       //sceKernelDcacheWritebackRange(&cube, sizeof(cube));
+       sceKernelDcacheWritebackInvalidateAll(); 
+
        GFX.perspective(75.0f, 16.0f/9.0f, 0.5f, 1000.0f);
 
        ScePspFVector3 eye={0,0,-10};
@@ -20,21 +30,32 @@ int game_main(int argc, char **argv)
        GFX.look_at(&eye, &center, &up);
 
        sceGumMatrixMode(GU_MODEL);
+       int i=0;
        while(1)
        {
+               i++;
                sceGuStart(GU_DIRECT, GFX.display_list);
                sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT);
 
                sceGumLoadIdentity();
+               sceGumRotateX(0.001f*i);
+               sceGumRotateY(0.001f*i);
+               sceGumRotateZ(0.001f*i);
                sceGuColor(GU_COLOR(1.0f,1.0f,1.0f,0.0f));
-               sceGumDrawArray(GU_TRIANGLES, GU_VERTEX_32BITF | GU_TRANSFORM_3D, 3, 0, triangle);
+               sceGumDrawArray(GU_TRIANGLES, 
+                               /*GU_TEXTURE_32BITF |*/ GU_COLOR_8888 | GU_NORMAL_32BITF |
+                               GU_VERTEX_32BITF | GU_TRANSFORM_3D | GU_INDEX_16BIT, cube.num_faces*3,
+                               cube.indices, cube.vertices);
        
+               
                ScePspFVector3 move={2,0,0};
+               sceGumLoadIdentity();
+               sceGumRotateZ(0.001f*i);
                sceGumTranslate(&move);
                
                sceGuColor(GU_COLOR(1.0f,0.0f,0.0f,0.0f));
                sceGumDrawArray(GU_TRIANGLES, GU_VERTEX_32BITF | GU_TRANSFORM_3D, 3, 0, triangle);
-
+               
                sceGuFinish();
                sceGuSync(0,0);
 
diff --git a/gfx.cc b/gfx.cc
index af05fa73bcd075434f7ed798c794ff4ef79c3aab..12ff231018bc866933a2a35814f5d98c5e5d0829 100644 (file)
--- a/gfx.cc
+++ b/gfx.cc
@@ -39,8 +39,8 @@ void Gfx::init()
        sceGuEnable( GU_DEPTH_TEST );
        sceGuShadeModel( GU_SMOOTH );
        sceGuFrontFace( GU_CW );
-       //sceGuEnable( GU_CULL_FACE );
-       //sceGuEnable( GU_CLIP_PLANES );
+       sceGuEnable( GU_CULL_FACE );
+       sceGuEnable( GU_CLIP_PLANES );
        
        // set clear color/depth
        sceGuClearColor( GU_COLOR( 0.0f, 0.0f, 0.0f, 1.0f ) ); 
diff --git a/model.cc b/model.cc
new file mode 100644 (file)
index 0000000..a329e87
--- /dev/null
+++ b/model.cc
@@ -0,0 +1,42 @@
+#include "model.h"
+#include <cstdio>
+#include <cstring>
+
+struct ModelHeader
+{
+       char sig[8]; // "laz0rOBJ"
+       int num_vertices;
+       int num_faces;
+};
+
+Model::Model(const char *filename)
+{
+       printf("Reading model %s\n", filename);
+       FILE *f=fopen(filename, "r");
+       ModelHeader h;
+       fread(&h, sizeof(ModelHeader), 1, f);
+       if (strncmp(h.sig, "laz0rOBJ", 8))
+       {
+               printf("Error, not a model file.\n");
+               num_vertices=0;
+               num_faces=0;
+               return;
+       }
+
+       num_vertices = h.num_vertices;
+       num_faces    = h.num_faces;
+       vertices     = new Vertex[num_vertices];
+       indices      = new unsigned short[num_faces*3];
+
+       fread(vertices, sizeof(Vertex), num_vertices, f);
+       fread(indices, sizeof(unsigned short), 3*num_faces, f);
+       fclose(f);
+}
+
+Model::~Model()
+{
+       delete[] vertices;
+       delete[] indices;
+}
+
+
diff --git a/model.h b/model.h
new file mode 100644 (file)
index 0000000..d3ad20b
--- /dev/null
+++ b/model.h
@@ -0,0 +1,26 @@
+#if !defined(MODEL_H)
+#define MODEL_H
+
+#include <psptypes.h>
+
+struct Vertex
+{
+       //float u,v;
+       u32 color;
+       float nx,ny,nz;
+       float x,y,z;
+};
+
+struct Model
+{
+       int num_vertices;
+       int num_faces;
+       Vertex *vertices;
+       unsigned short *indices;
+
+       Model(const char *filename);
+       ~Model();
+};
+
+#endif
+
diff --git a/tools/blender_exporter.py b/tools/blender_exporter.py
new file mode 100644 (file)
index 0000000..b1955c9
--- /dev/null
@@ -0,0 +1,113 @@
+#!BPY
+
+"""
+Name: 'laz0r-exporter'
+Blender: 245
+Group: 'Export'
+Tooltip: 'Exports meshes to a simple format with PSP-formatted vertex arrays
+and index list'
+"""
+
+import Blender
+import bpy
+import struct
+
+def write(filename):
+       vertex_list = [] # index --> {co=(x,y,z), no=(nx,ny,nz), uv=(u,v)}
+       vertex_map = {} # (x,y,z) --> [index, index, ...]
+       index_list = [] # indices of each vertex for every face, in order
+       
+       scene = bpy.data.scenes.active
+       obj = scene.objects.active
+
+       if obj.type != "Mesh":
+               return
+       
+       mesh = obj.getData(mesh=1)
+
+       # add every vertex
+       for vert in mesh.verts:
+               vx,vy,vz = vert.co
+               nx,ny,nz = vert.no
+               v = {"co":(vx,vy,vz), "no":(nx,ny,nz)}
+               vertex_list.append(v)
+               if v["co"] in vertex_map:
+                       vertex_map[v["co"]].append(len(vertex_list)-1)
+               else:
+                       vertex_map[v["co"]] = [len(vertex_list)-1]
+
+       # iterate through faces, filling uv attribute in vertices
+       # and duplicating them if needed
+       for face in mesh.faces:
+               for vert_i,vert in enumerate(face.verts):
+                       vx,vy,vz = vert.co
+                       nx,ny,nz = vert.no
+                       co = (vx,vy,vz)
+                       no = (nx,ny,nz)
+
+                       if mesh.faceUV:
+                               u,v=face.uv[vert_i]
+                       else:
+                               u,v=0,0
+
+                       if mesh.vertexColors:
+                               r = face.col[vert_i].r
+                               g = face.col[vert_i].g
+                               b = face.col[vert_i].b
+                               a = face.col[vert_i].a
+                       else:
+                               r,g,b,a=255,255,255,255
+
+
+                       # find matching vertex
+                       for i in vertex_map[co]:
+                               match = True
+                               if vertex_list[i]["no"] != no:
+                                       match = False
+                               if "uv" in vertex_list[i]:
+                                       if vertex_list[i]["uv"] != (u,v):
+                                               match = False
+                               if "col" in vertex_list[i]:
+                                       if vertex_list[i]["col"] != (r,g,b,a):
+                                               match = False
+
+                               if match:
+                                       break
+
+                       if match:
+                               matching_vertex = vertex_list[i]
+                               matching_vertex["uv"] = (u,v)
+                               matching_vertex["col"] = (r,g,b,a)
+                               matching_index = i
+                       else:
+                               matching_vertex = { "co":co, "no":no, "uv":(u,v), "col":(r,g,b,a) }
+                               vertex_list.append(matching_vertex)
+                               matching_index = len(vertex_list)-1
+                               vertex_map[co].append(matching_index)
+
+                       index_list.append(matching_index)
+                       #print matching_index
+               #print "end face"
+
+       # write header
+       f = file(filename, "w")
+       f.write("laz0rOBJ")
+       f.write(struct.pack("<II", len(vertex_list), len(mesh.faces)))
+       print "%u verts, %u faces"%(len(vertex_list), len(mesh.faces))
+       for vert in vertex_list:
+               u,v = vert["uv"]
+               r,g,b,a = vert["col"]
+               nx,ny,nz = vert["no"]
+               x,y,z = vert["co"]
+               #f.write(struct.pack("< ff BBBB fff fff", u,v, r,g,b,a, nx, ny, nz, x,y,z)) # 36 bytes each
+               f.write(struct.pack("< BBBB fff fff", r,g,b,a, nx, ny, nz, x,y,z)) # 36 bytes each
+       
+       for i in index_list:
+               f.write(struct.pack("<H", i))
+       
+       f.close()
+
+
+Blender.Window.FileSelector(write, "Export")
+
+