goat3dgfx

annotate src/curveload.cc @ 20:d9c8cd19c606

fixed the face index loading bug
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 08 Dec 2013 03:00:49 +0200
parents 7bd5ebec3b6f
children
rev   line source
nuclear@0 1 #include <string>
nuclear@0 2 #include <assert.h>
nuclear@0 3 #include "curveload.h"
nuclear@0 4 #include "3dschunks.h"
nuclear@0 5 #include "logger.h"
nuclear@0 6
nuclear@15 7 using namespace goatgfx;
nuclear@15 8
nuclear@2 9 #ifndef _MSC_VER
nuclear@2 10 #include <stdint.h>
nuclear@2 11 #else
nuclear@2 12 typedef __int8 int8_t;
nuclear@2 13 typedef __int16 int16_t;
nuclear@2 14 typedef __int32 int32_t;
nuclear@2 15 typedef unsigned __int8 uint8_t;
nuclear@2 16 typedef unsigned __int16 uint16_t;
nuclear@2 17 typedef unsigned __int32 uint32_t;
nuclear@2 18 #endif
nuclear@2 19
nuclear@0 20 static uint32_t read_counter;
nuclear@0 21
nuclear@0 22 struct ChunkHeader {
nuclear@0 23 ChunkID id;
nuclear@0 24 uint32_t size;
nuclear@0 25 };
nuclear@0 26
nuclear@0 27 #define HEADER_SIZE 6
nuclear@0 28
nuclear@0 29 // local function prototypes
nuclear@0 30 static uint8_t read_byte(FILE *file);
nuclear@0 31 static uint16_t read_int16(FILE *file);
nuclear@0 32 static uint32_t read_int32(FILE *file);
nuclear@0 33 static float read_float(FILE *file);
nuclear@0 34 static Vector3 read_vector(FILE *file, bool flip_yz = false);
nuclear@0 35 static std::string read_string(FILE *file);
nuclear@0 36 static ChunkHeader read_chunk_header(FILE *file);
nuclear@0 37 static void skip_chunk(FILE *file, const ChunkHeader &chunk);
nuclear@0 38 static Curve *read_curve(FILE *file, const ChunkHeader &ch);
nuclear@0 39
nuclear@0 40 static bool eof;
nuclear@0 41
nuclear@0 42 bool load_curves(Scene *scn, const char *fname)
nuclear@0 43 {
nuclear@0 44 FILE *file = fopen(fname, "rb");
nuclear@0 45 if(!file) {
nuclear@0 46 error_log("failed to open curves scene file: %s\n", fname);
nuclear@0 47 return false;
nuclear@0 48 }
nuclear@0 49 eof = false;
nuclear@0 50
nuclear@0 51 ChunkHeader chunk;
nuclear@0 52
nuclear@0 53 chunk = read_chunk_header(file);
nuclear@0 54 if(chunk.id != Chunk_3DSMain) {
nuclear@0 55 fclose(file);
nuclear@0 56 return false;
nuclear@0 57 }
nuclear@0 58
nuclear@0 59 while(!eof) {
nuclear@0 60 chunk = read_chunk_header(file);
nuclear@0 61
nuclear@0 62 Curve *curve;
nuclear@0 63
nuclear@0 64 switch(chunk.id) {
nuclear@0 65 case Chunk_Main_3DEditor:
nuclear@0 66 break; // dont skip
nuclear@0 67
nuclear@0 68 case Chunk_Edit_Object:
nuclear@0 69 if((curve = read_curve(file, chunk))) {
nuclear@0 70 scn->curves.push_back(curve);
nuclear@0 71 }
nuclear@0 72 break;
nuclear@0 73
nuclear@0 74 default:
nuclear@0 75 skip_chunk(file, chunk);
nuclear@0 76 }
nuclear@0 77 }
nuclear@0 78
nuclear@0 79 fclose(file);
nuclear@0 80 return true;
nuclear@0 81 }
nuclear@0 82
nuclear@0 83 static uint8_t read_byte(FILE *fp) {
nuclear@0 84 uint8_t v;
nuclear@0 85 if(fread(&v, 1, 1, fp) <= 0) {
nuclear@0 86 eof = true;
nuclear@0 87 return 0;
nuclear@0 88 }
nuclear@0 89 read_counter++;
nuclear@0 90 return v;
nuclear@0 91 }
nuclear@0 92
nuclear@0 93 static uint16_t read_int16(FILE *fp) {
nuclear@0 94 uint16_t v;
nuclear@0 95 if(fread(&v, 2, 1, fp) <= 0) {
nuclear@0 96 eof = true;
nuclear@0 97 return 0;
nuclear@0 98 }
nuclear@0 99 read_counter += 2;
nuclear@0 100 return v;
nuclear@0 101 }
nuclear@0 102
nuclear@0 103 static uint32_t read_int32(FILE *fp) {
nuclear@0 104 uint32_t v;
nuclear@0 105 if(fread(&v, 4, 1, fp) <= 0) {
nuclear@0 106 eof = true;
nuclear@0 107 return 0;
nuclear@0 108 }
nuclear@0 109 read_counter += 4;
nuclear@0 110 return v;
nuclear@0 111 }
nuclear@0 112
nuclear@0 113 static float read_float(FILE *fp)
nuclear@0 114 {
nuclear@0 115 int32_t tmp = read_int32(fp);
nuclear@0 116 return *((float*)&tmp);
nuclear@0 117 }
nuclear@0 118
nuclear@0 119 static Vector3 read_vector(FILE *file, bool flip_yz)
nuclear@0 120 {
nuclear@0 121 Vector3 vector;
nuclear@0 122 vector.x = read_float(file);
nuclear@0 123 if(!flip_yz) vector.y = read_float(file);
nuclear@0 124 vector.z = read_float(file);
nuclear@0 125 if(flip_yz) vector.y = read_float(file);
nuclear@0 126 return vector;
nuclear@0 127 }
nuclear@0 128
nuclear@0 129 static std::string read_string(FILE *file)
nuclear@0 130 {
nuclear@0 131 std::string str;
nuclear@0 132 char c;
nuclear@0 133 while((c = (char)read_byte(file))) {
nuclear@0 134 str.push_back(c);
nuclear@0 135 }
nuclear@0 136 read_counter++;
nuclear@0 137
nuclear@0 138 return str;
nuclear@0 139 }
nuclear@0 140
nuclear@0 141 static ChunkHeader read_chunk_header(FILE *file)
nuclear@0 142 {
nuclear@0 143 ChunkHeader chunk;
nuclear@0 144 chunk.id = (ChunkID)read_int16(file);
nuclear@0 145 chunk.size = read_int32(file);
nuclear@0 146 return chunk;
nuclear@0 147 }
nuclear@0 148
nuclear@0 149 static void skip_chunk(FILE *file, const ChunkHeader &chunk)
nuclear@0 150 {
nuclear@0 151 if(eof) return;
nuclear@0 152 fseek(file, chunk.size - HEADER_SIZE, SEEK_CUR);
nuclear@0 153 read_counter += chunk.size - HEADER_SIZE;
nuclear@0 154 }
nuclear@0 155
nuclear@0 156 static Curve *read_curve(FILE *file, const ChunkHeader &ch)
nuclear@0 157 {
nuclear@0 158 read_counter = HEADER_SIZE; // reset the global read counter
nuclear@0 159
nuclear@0 160 std::string name = read_string(file);
nuclear@0 161
nuclear@0 162 ChunkHeader chunk;
nuclear@0 163 chunk = read_chunk_header(file);
nuclear@0 164 if(chunk.id == Chunk_Obj_TriMesh) {
nuclear@0 165 // object is a trimesh... load it
nuclear@0 166 Vector3 *varray = 0;
nuclear@0 167 uint32_t vertex_count = 0;
nuclear@0 168
nuclear@0 169 uint32_t obj_chunk_size = ch.size;
nuclear@0 170
nuclear@0 171 while(read_counter < obj_chunk_size) { // make sure we only read subchunks of this object chunk
nuclear@0 172 chunk = read_chunk_header(file);
nuclear@0 173
nuclear@0 174 switch(chunk.id) {
nuclear@0 175 case Chunk_TriMesh_VertexList:
nuclear@0 176 vertex_count = (uint32_t)read_int16(file);
nuclear@0 177 varray = new Vector3[vertex_count];
nuclear@0 178
nuclear@0 179 for(uint32_t i=0; i<vertex_count; i++) {
nuclear@0 180 varray[i] = read_vector(file);
nuclear@0 181 }
nuclear@0 182
nuclear@0 183 break;
nuclear@0 184
nuclear@0 185 case Chunk_TriMesh_FaceDesc:
nuclear@0 186 // it is a real object not a curve since it has triangles
nuclear@0 187 delete [] varray;
nuclear@0 188 varray = 0;
nuclear@0 189 break;
nuclear@0 190
nuclear@0 191 default:
nuclear@0 192 skip_chunk(file, chunk);
nuclear@0 193 }
nuclear@0 194 }
nuclear@0 195
nuclear@0 196 if(varray) {
nuclear@0 197 Curve *curve = new Curve;
nuclear@0 198 curve->set_name(name.c_str());
nuclear@0 199 for(uint32_t i=0; i<vertex_count; i++) {
nuclear@0 200 curve->add_point(varray[i]);
nuclear@0 201 }
nuclear@0 202 return curve;
nuclear@0 203 }
nuclear@0 204 }
nuclear@0 205
nuclear@0 206 return 0;
nuclear@0 207 }