3D format conversion

Talk about development tools here

Moderator: BigEvilCorporation

Post Reply
kubilus1
Very interested
Posts: 237
Joined: Thu Aug 16, 2012 2:25 am
Contact:

3D format conversion

Post by kubilus1 » Fri Aug 22, 2014 5:01 pm

I wrote a tool that takes wavefront .obj files and converts them into something digestable by SGDK.

http://code.google.com/p/gendev/source/ ... bj2mesh.py

# python obj2mesh.py -f afile.obj > meshs.h

This works with a slightly modified cube_flat sample program from SGDK with the following patch:

Code: Select all

Index: main.c
===================================================================
--- main.c      (revision 194)
+++ main.c      (working copy)
@@ -2,7 +2,7 @@

 #include "meshs.h"

-#define MAX_POINTS  256
+#define MAX_POINTS 512


 Vect3D_f16 pts_3D[MAX_POINTS];
@@ -47,7 +47,7 @@

     JOY_setEventHandler(handleJoyEvent);

-    BMP_init(TRUE, PAL0, FALSE);
+    BMP_init(TRUE, PAL1, FALSE);

     camdist = FIX16(15);

@@ -99,9 +99,9 @@
 void updatePointsPos()
 {
     // transform 3D point
-    M3D_transform(&transformation, cube_coord, pts_3D, 8);
+    M3D_transform(&transformation, cube_coord, pts_3D, verts);
     // project 3D point (f16) to 2D point (s16)
-    M3D_project_s16(pts_3D, pts_2D, 8);
+    M3D_project_s16(pts_3D, pts_2D, verts);
 }

 void drawPoints(u8 col)
@@ -108,7 +108,7 @@
 {
     if (flatDrawing)
     {
-        Vect2D_s16 v[4];
+        Vect2D_s16 v[3];
         const Vect3D_f16 *norm;
         const u16 *poly_ind;
         u16 i;
@@ -116,7 +116,8 @@
         norm = cube_face_norm;
         poly_ind = cube_poly_ind;
 
-        i = 6;
+        // # of polygon faces
+        i = faces;
 
         while (i--)
         {
@@ -124,9 +125,10 @@
             fix16 dp;
             u8 col = 2;

+            // Cycle through number of indices in polygon face
             *pt_dst++ = pts_2D[*poly_ind++];
             *pt_dst++ = pts_2D[*poly_ind++];
-            *pt_dst++ = pts_2D[*poly_ind++];
+            //*pt_dst++ = pts_2D[*poly_ind++];
             *pt_dst = pts_2D[*poly_ind++];

             dp = fix16Mul(transformation.lightInv.x, norm->x) +
@@ -136,8 +138,8 @@

             if (dp > 0) col += (dp >> (FIX16_FRAC_BITS - 2));

-            if (!BMP_isPolygonCulled(v, 4))
-                BMP_drawPolygon(v, 4, col);
+            if (!BMP_isPolygonCulled(v, 3))
+                BMP_drawPolygon(v, 3, col);
         }
     }
     else
@@ -148,9 +150,10 @@

         l.col = col;
         line_ind = cube_line_ind;
+
+        // Number of lines
+        i = edges;

-        i = 12;
-
         while (i--)
         {
             l.pt1 = pts_2D[*line_ind++];
Since the wavefront format (and most other 3d formats) specify polygons as a series of triangles, I had to change that.

Here's the current result:

https://dl.dropboxusercontent.com/u/101 ... huttle.bin

Made quickly from https://www.3dtin.com

Some things I've noticed:

*Not sure if the culling is working properly. Is this due to me changing the quads to triangles?

*The script reduces duplicate points, but is still less efficient due to the increased number of lines from triangles. Is there a better 3d drawing tool/format to use?

* The Y axis appears to be reversed between the formats.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Fri Aug 22, 2014 6:17 pm

Nice tool ! I would be even better if we could port it to C code so i could include it directly in the rescomp tool :D
I'm not really surprised about the inverted Y axis as i do revert it in SGDK (i want coordinate 0 to be at bottom as in "real life"). For the culling, well it should work (it does work on the cube example), you polygon has to be clockwise defined. As you said, using triangle is definitely not optimal as it requires to calculate more edges... but i don't know if you can specify to keep originals polygons in the OBJ format (SGDK support polygon up to 8 points).

kubilus1
Very interested
Posts: 237
Joined: Thu Aug 16, 2012 2:25 am
Contact:

Post by kubilus1 » Fri Aug 22, 2014 7:51 pm

Ahh, but python works cross platform and is oh so nice to program in!

AFAICT, the format requires triangles, but I'm not an expert in it by any means.

I believe that the format defines coordinates in counter-clockwise fashion. Could that be why the polygon is kind of see-through when I make it solid?

haroldoop
Very interested
Posts: 160
Joined: Sun Apr 29, 2007 10:04 pm
Location: Belo Horizonte, MG, Brazil

Post by haroldoop » Fri Aug 22, 2014 11:07 pm

That's pretty cool. :)

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Sat Aug 23, 2014 10:22 pm

kubilus1 wrote:Ahh, but python works cross platform and is oh so nice to program in!
Yeah i know, at least on windows you need to install python.
AFAICT, the format requires triangles, but I'm not an expert in it by any means.

I believe that the format defines coordinates in counter-clockwise fashion. Could that be why the polygon is kind of see-through when I make it solid?
If they are defined in wrong clockwise order, it should display the interior of object instead, which does not appear to be the case here so i'm not sure.

kubilus1
Very interested
Posts: 237
Joined: Thu Aug 16, 2012 2:25 am
Contact:

Post by kubilus1 » Tue Sep 02, 2014 10:27 pm

I've updated the obj2mesh.py tool (same link) to support more from the Wavefront format. This should now handle files created by more tools (tested with Wings3d) and support polygons with more than three points.

Currently I am not limiting the number of vertices, which I should since the engine is limited to eight.

Here's a replacement main.c file and an example bin:
https://dl.dropboxusercontent.com/u/101302896/3d.zip

I've changed the main.c from the cube_flat example enough that it is probably best just to show the entire file. This should now be able to take a converted obj file and display it.

Some issues still:

* Limit to 8 vertices per polygon - I figure I will just split them in half.
* objects that are behind objects should be hidden/not drawn.

For the second point, does anyone have any advice on this? I know the brute force way is to use the painter's algorithm, but I would still need to know the current z-order of the polygons, which could be taxing on the system.

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Wed Sep 03, 2014 8:21 am

What is used in SNES Starfox engine (and i replicated in the demo) is the BSP tree structure to store convexe 3D objects, this way you use the BSP tree to navigate in the object faces and draw them in the good order. This way you only need to sort each convexe object on mean Z instead of sorting each face.

kubilus1
Very interested
Posts: 237
Joined: Thu Aug 16, 2012 2:25 am
Contact:

Post by kubilus1 » Sat Oct 25, 2014 4:20 pm

I've made some improvements to the obj2mesh conversion program and the code to run files created with this.

Obj2mesh now supports multiple polygons in the single file and calculates the center of the polygons. Polygons are now represented as a list of polygons that can be accessed for rendering, OR individually by name.

http://code.google.com/p/gendev/source/ ... 2Fobj2mesh

I've created an example using this:

http://code.google.com/p/gendev/source/ ... 3d_example

The binary: http://gendev.googlecode.com/svn/trunk/ ... le/out.bin

This allows a fairly simple way of displaying all polygons by calling the 'render' function. Polygons should properly be placed in the correct order now.

I simply use the taxi-cab method for distance, and use a modification of Stef's quicksort, for order, but instead work on a list of pointers instead of objects directly.

I'm sure there's room for improvement still!

kubilus1
Very interested
Posts: 237
Joined: Thu Aug 16, 2012 2:25 am
Contact:

Post by kubilus1 » Sun Nov 16, 2014 5:11 pm

Another update! Now obj2mesh supports the .mtl files! This allows for colors to be setup in Wings3d or other tools and automatically be loaded.

This uses the diffuse color property (Kd)

I've also updated the lighting so that colors are not wasted. Currently I set aside three colors, black, dark grey, light grey that are used for shading. This leaves 12 useable colors in the palette.

The example is in the same location and shows a multi-colored space ship in a star field.

(I've also renamed things in a slightly more sensible manner.)

kubilus1
Very interested
Posts: 237
Joined: Thu Aug 16, 2012 2:25 am
Contact:

Post by kubilus1 » Sat Dec 13, 2014 4:42 pm

Updated obj2mech to support multiple input files. The user can now do something like:

Code: Select all

python obj2mesh.py -f obj1.obj -f obj2.obj > meshs.h
.mtl files are automatically looked for with the same path/name as the .obj file.

Post Reply