mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 06:45:39 -06:00
Adding uppdev....
git-svn-id: svn://ultimatepp.org/upp/trunk@328 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
dc9f782ba5
commit
4a1c627474
2823 changed files with 619073 additions and 0 deletions
396
uppdev/GLShadow/load3ds.c
Normal file
396
uppdev/GLShadow/load3ds.c
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
/* load 3ds file
|
||||
*
|
||||
* written by Alexander Zaprjagaev
|
||||
* frustum@public.tsu.ru
|
||||
*
|
||||
* usage:
|
||||
* float *load_3ds(char *name,int *num_vertex);
|
||||
* 1,2,3 - xyz
|
||||
* 4,5,6 - normal
|
||||
* 7,8 - st
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#define CHUNK_MAIN 0x4d4d
|
||||
#define CHUNK_OBJMESH 0x3d3d
|
||||
#define CHUNK_OBJBLOCK 0x4000
|
||||
#define CHUNK_TRIMESH 0x4100
|
||||
#define CHUNK_VERTLIST 0x4110
|
||||
#define CHUNK_FACELIST 0x4120
|
||||
#define CHUNK_MAPLIST 0x4140
|
||||
#define CHUNK_SMOOLIST 0x4150
|
||||
|
||||
typedef struct {
|
||||
float x,y,z;
|
||||
} vector_t;
|
||||
|
||||
typedef struct {
|
||||
float u,v;
|
||||
} uvmap_t;
|
||||
|
||||
typedef struct {
|
||||
vector_t *vertex;
|
||||
int num_vertex;
|
||||
uvmap_t *uvmap;
|
||||
int num_uvmap;
|
||||
int *face;
|
||||
int *smoothgroup;
|
||||
vector_t *normal;
|
||||
int num_face;
|
||||
} trimesh_t;
|
||||
|
||||
typedef struct {
|
||||
trimesh_t *trimesh;
|
||||
int num_trimesh;
|
||||
} mesh_t;
|
||||
|
||||
typedef int (*process_chunk)(FILE *file,
|
||||
unsigned short type,int size,void *data);
|
||||
|
||||
/*
|
||||
*/
|
||||
static void vector_copy(vector_t *a,vector_t *b) {
|
||||
b->x = a->x;
|
||||
b->y = a->y;
|
||||
b->z = a->z;
|
||||
}
|
||||
|
||||
static void vector_add(vector_t *a,vector_t *b,vector_t *c) {
|
||||
c->x = a->x + b->x;
|
||||
c->y = a->y + b->y;
|
||||
c->z = a->z + b->z;
|
||||
}
|
||||
|
||||
static void vector_sub(vector_t *a,vector_t *b,vector_t *c) {
|
||||
c->x = a->x - b->x;
|
||||
c->y = a->y - b->y;
|
||||
c->z = a->z - b->z;
|
||||
}
|
||||
|
||||
static void vector_cross(vector_t *a,vector_t *b,vector_t *c) {
|
||||
c->x = a->y * b->z - a->z * b->y;
|
||||
c->y = a->z * b->x - a->x * b->z;
|
||||
c->z = a->x * b->y - a->y * b->x;
|
||||
}
|
||||
|
||||
static float vector_normalize(vector_t *a,vector_t *b) {
|
||||
float length = sqrt(a->x * a->x + a->y * a->y + a->z * a->z);
|
||||
if(length) {
|
||||
float ilength = 1.0 / length;
|
||||
b->x = a->x * ilength;
|
||||
b->y = a->y * ilength;
|
||||
b->z = a->z * ilength;
|
||||
return length;
|
||||
}
|
||||
b->x = 0.0;
|
||||
b->y = 0.0;
|
||||
b->z = 0.0;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
static void skeep_bytes(FILE *file,int bytes) {
|
||||
fseek(file,bytes,SEEK_CUR);
|
||||
}
|
||||
|
||||
static int skeep_string(FILE *file) {
|
||||
int i = 0;
|
||||
while(fgetc(file) != '\0') i++;
|
||||
return ++i;
|
||||
}
|
||||
|
||||
static unsigned short read_ushort(FILE *file) {
|
||||
unsigned short ret;
|
||||
fread(&ret,1,sizeof(unsigned short),file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int read_int(FILE *file) {
|
||||
int ret;
|
||||
fread(&ret,1,sizeof(int),file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static float read_float(FILE *file) {
|
||||
float ret;
|
||||
fread(&ret,1,sizeof(float),file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int read_chunk(FILE *file,process_chunk chunk_func,void *data) {
|
||||
unsigned short chunk_type;
|
||||
int chunk_size,content_size;
|
||||
chunk_type = read_ushort(file);
|
||||
chunk_size = read_int(file);
|
||||
content_size = chunk_size - 6;
|
||||
if(!chunk_func(file,chunk_type,content_size,data))
|
||||
skeep_bytes(file,content_size);
|
||||
return chunk_size;
|
||||
}
|
||||
|
||||
static int read_chunks(FILE *file,int bytes,
|
||||
process_chunk chunk_func,void *data) {
|
||||
int bytes_read = 0;
|
||||
while(bytes_read < bytes)
|
||||
bytes_read += read_chunk(file,chunk_func,data);
|
||||
if(bytes_read != bytes)
|
||||
fprintf(stderr,"expected %d bytes but read %d\n",bytes_read,bytes);
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
static int process_smoolist(FILE *file,unsigned short type,
|
||||
int size,void *data) {
|
||||
int i;
|
||||
trimesh_t *trimesh = (trimesh_t*)data;
|
||||
if(type == CHUNK_SMOOLIST) {
|
||||
trimesh->smoothgroup = malloc(sizeof(int) * trimesh->num_face);
|
||||
for(i = 0; i < trimesh->num_face; i++) {
|
||||
trimesh->smoothgroup[i] = read_int(file);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_trimesh(FILE *file,unsigned short type,
|
||||
int size,void *data) {
|
||||
int i;
|
||||
trimesh_t *trimesh = (trimesh_t*)data;
|
||||
if(type == CHUNK_VERTLIST) { /* vertlist */
|
||||
trimesh->num_vertex = read_ushort(file);
|
||||
trimesh->vertex = malloc(sizeof(vector_t) * trimesh->num_vertex);
|
||||
for(i = 0; i < trimesh->num_vertex; i++) {
|
||||
trimesh->vertex[i].x = read_float(file);
|
||||
trimesh->vertex[i].y = read_float(file);
|
||||
trimesh->vertex[i].z = read_float(file);
|
||||
}
|
||||
return 1;
|
||||
} else if(type == CHUNK_MAPLIST) { /* maplist */
|
||||
trimesh->num_uvmap = read_ushort(file);
|
||||
trimesh->uvmap = malloc(sizeof(uvmap_t) * trimesh->num_uvmap);
|
||||
for(i = 0; i < trimesh->num_uvmap; i++) {
|
||||
trimesh->uvmap[i].u = read_float(file);
|
||||
trimesh->uvmap[i].v = 1.0 - read_float(file);
|
||||
}
|
||||
return 1;
|
||||
} else if(type == CHUNK_FACELIST) { /* facelist */
|
||||
int bytes_left;
|
||||
trimesh->num_face = read_ushort(file);
|
||||
trimesh->face = malloc(sizeof(int) * trimesh->num_face * 3);
|
||||
for(i = 0; i < trimesh->num_face * 3; i += 3) {
|
||||
trimesh->face[i + 0] = read_ushort(file);
|
||||
trimesh->face[i + 1] = read_ushort(file);
|
||||
trimesh->face[i + 2] = read_ushort(file);
|
||||
read_ushort(file);
|
||||
}
|
||||
bytes_left = size - trimesh->num_face * sizeof(unsigned short) * 4 - 2;
|
||||
if(bytes_left > 0)
|
||||
read_chunks(file,bytes_left,process_smoolist,(void*)trimesh);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_objblock(FILE *file,unsigned short type,
|
||||
int size,void *data) {
|
||||
mesh_t *mesh = (mesh_t*)data;
|
||||
if(type == CHUNK_TRIMESH) {
|
||||
mesh->num_trimesh++;
|
||||
if(mesh->trimesh == NULL) mesh->trimesh = malloc(sizeof(trimesh_t));
|
||||
else mesh->trimesh = realloc(mesh->trimesh,
|
||||
sizeof(trimesh_t) * mesh->num_trimesh);
|
||||
memset(&mesh->trimesh[mesh->num_trimesh - 1],0,sizeof(trimesh_t));
|
||||
read_chunks(file,size,process_trimesh,
|
||||
(void*)&mesh->trimesh[mesh->num_trimesh - 1]);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_objmesh(FILE *file,unsigned short type,
|
||||
int size,void *data) {
|
||||
if(type == CHUNK_OBJBLOCK) {
|
||||
size -= skeep_string(file);
|
||||
read_chunks(file,size,process_objblock,data);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_main(FILE *file,unsigned short type,
|
||||
int size,void *data) {
|
||||
if(type == CHUNK_OBJMESH) {
|
||||
read_chunks(file,size,process_objmesh,data);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*/
|
||||
static void create_trimesh(trimesh_t *trimesh) {
|
||||
int i;
|
||||
uvmap_t *uvmap;
|
||||
vector_t *vertex,*normal_face,*normal_vertex;
|
||||
int *face,*vertex_count,**vertex_face,*smoothgroup;
|
||||
/* calc normals */
|
||||
normal_face = calloc(1,sizeof(vector_t) * trimesh->num_face);
|
||||
normal_vertex = calloc(1,sizeof(vector_t) * trimesh->num_face * 3);
|
||||
vertex_count = calloc(1,sizeof(int) * trimesh->num_face * 3);
|
||||
vertex_face = calloc(1,sizeof(int*) * trimesh->num_face * 3);
|
||||
trimesh->normal = normal_vertex;
|
||||
vertex = trimesh->vertex;
|
||||
face = trimesh->face;
|
||||
smoothgroup = trimesh->smoothgroup;
|
||||
for(i = 0; i < trimesh->num_face; i++) {
|
||||
int j = i * 3;
|
||||
vector_t a,b;
|
||||
int v0 = face[j + 0];
|
||||
int v1 = face[j + 1];
|
||||
int v2 = face[j + 2];
|
||||
vertex_count[v0]++;
|
||||
vertex_count[v1]++;
|
||||
vertex_count[v2]++;
|
||||
vector_sub(&vertex[v1],&vertex[v0],&a);
|
||||
vector_sub(&vertex[v2],&vertex[v0],&b);
|
||||
vector_cross(&a,&b,&normal_face[i]);
|
||||
vector_normalize(&normal_face[i],&normal_face[i]);
|
||||
}
|
||||
for(i = 0; i < trimesh->num_face * 3; i++) {
|
||||
vertex_face[i] = malloc(sizeof(int) * (vertex_count[i] + 1));
|
||||
vertex_face[i][0] = vertex_count[i];
|
||||
}
|
||||
for(i = 0; i < trimesh->num_face; i++) {
|
||||
int j = i * 3;
|
||||
int v0 = face[j + 0];
|
||||
int v1 = face[j + 1];
|
||||
int v2 = face[j + 2];
|
||||
vertex_face[v0][vertex_count[v0]--] = i;
|
||||
vertex_face[v1][vertex_count[v1]--] = i;
|
||||
vertex_face[v2][vertex_count[v2]--] = i;
|
||||
}
|
||||
for(i = 0; i < trimesh->num_face; i++) {
|
||||
int j = i * 3,k;
|
||||
int v0 = face[j + 0];
|
||||
int v1 = face[j + 1];
|
||||
int v2 = face[j + 2];
|
||||
for(k = 1; k <= vertex_face[v0][0]; k++) {
|
||||
int l = vertex_face[v0][k];
|
||||
if(i == l || (smoothgroup && smoothgroup[i] & smoothgroup[l]))
|
||||
vector_add(&normal_vertex[j + 0],&normal_face[l],
|
||||
&normal_vertex[j + 0]);
|
||||
}
|
||||
for(k = 1; k <= vertex_face[v1][0]; k++) {
|
||||
int l = vertex_face[v1][k];
|
||||
if(i == l || (smoothgroup && smoothgroup[i] & smoothgroup[l]))
|
||||
vector_add(&normal_vertex[j + 1],&normal_face[l],
|
||||
&normal_vertex[j + 1]);
|
||||
}
|
||||
for(k = 1; k <= vertex_face[v2][0]; k++) {
|
||||
int l = vertex_face[v2][k];
|
||||
if(i == l || (smoothgroup && smoothgroup[i] & smoothgroup[l]))
|
||||
vector_add(&normal_vertex[j + 2],&normal_face[l],
|
||||
&normal_vertex[j + 2]);
|
||||
}
|
||||
}
|
||||
for(i = 0; i < trimesh->num_face * 3; i++) {
|
||||
vector_normalize(&normal_vertex[i],&normal_vertex[i]);
|
||||
free(vertex_face[i]);
|
||||
}
|
||||
free(normal_face);
|
||||
free(vertex_count);
|
||||
free(vertex_face);
|
||||
/* create linear arrays for vertex and uvmap */
|
||||
vertex = calloc(1,sizeof(vector_t) * trimesh->num_face * 3);
|
||||
uvmap = calloc(1,sizeof(uvmap_t) * trimesh->num_face * 3);
|
||||
for(i = 0; i < trimesh->num_face * 3; i += 3) {
|
||||
vector_copy(&trimesh->vertex[trimesh->face[i + 0]],&vertex[i + 0]);
|
||||
vector_copy(&trimesh->vertex[trimesh->face[i + 1]],&vertex[i + 1]);
|
||||
vector_copy(&trimesh->vertex[trimesh->face[i + 2]],&vertex[i + 2]);
|
||||
}
|
||||
free(trimesh->vertex);
|
||||
trimesh->vertex = vertex;
|
||||
trimesh->num_vertex = trimesh->num_face * 3;
|
||||
if(trimesh->uvmap) {
|
||||
for(i = 0; i < trimesh->num_face * 3; i += 3) {
|
||||
uvmap[i + 0].u = trimesh->uvmap[trimesh->face[i + 0]].u;
|
||||
uvmap[i + 0].v = trimesh->uvmap[trimesh->face[i + 0]].v;
|
||||
uvmap[i + 1].u = trimesh->uvmap[trimesh->face[i + 1]].u;
|
||||
uvmap[i + 1].v = trimesh->uvmap[trimesh->face[i + 1]].v;
|
||||
uvmap[i + 2].u = trimesh->uvmap[trimesh->face[i + 2]].u;
|
||||
uvmap[i + 2].v = trimesh->uvmap[trimesh->face[i + 2]].v;
|
||||
}
|
||||
free(trimesh->uvmap);
|
||||
}
|
||||
trimesh->uvmap = uvmap;
|
||||
trimesh->num_uvmap = trimesh->num_face * 3;
|
||||
free(trimesh->face);
|
||||
trimesh->face = NULL;
|
||||
}
|
||||
|
||||
static float *create_mesh(mesh_t *mesh,int *num_vertex) {
|
||||
int i,j;
|
||||
float *vertex;
|
||||
for(i = 0, *num_vertex = 0; i < mesh->num_trimesh; i++) {
|
||||
create_trimesh(&mesh->trimesh[i]);
|
||||
*num_vertex += mesh->trimesh[i].num_face;
|
||||
}
|
||||
*num_vertex *= 3;
|
||||
vertex = malloc(sizeof(float) * *num_vertex * 8);
|
||||
for(i = 0, j = 0; i < mesh->num_trimesh; i++) {
|
||||
int k;
|
||||
for(k = 0; k < mesh->trimesh[i].num_face * 3; k++, j += 8) {
|
||||
vertex[j + 0] = mesh->trimesh[i].vertex[k].x;
|
||||
vertex[j + 1] = mesh->trimesh[i].vertex[k].y;
|
||||
vertex[j + 2] = mesh->trimesh[i].vertex[k].z;
|
||||
vertex[j + 3] = mesh->trimesh[i].normal[k].x;
|
||||
vertex[j + 4] = mesh->trimesh[i].normal[k].y;
|
||||
vertex[j + 5] = mesh->trimesh[i].normal[k].z;
|
||||
vertex[j + 6] = mesh->trimesh[i].uvmap[k].u;
|
||||
vertex[j + 7] = mesh->trimesh[i].uvmap[k].v;
|
||||
}
|
||||
if(mesh->trimesh[i].vertex) free(mesh->trimesh[i].vertex);
|
||||
if(mesh->trimesh[i].normal) free(mesh->trimesh[i].normal);
|
||||
if(mesh->trimesh[i].uvmap) free(mesh->trimesh[i].uvmap);
|
||||
if(mesh->trimesh[i].face) free(mesh->trimesh[i].face);
|
||||
if(mesh->trimesh[i].smoothgroup) free(mesh->trimesh[i].smoothgroup);
|
||||
}
|
||||
free(mesh->trimesh);
|
||||
return vertex;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
float *load_3ds(char *name,int *num_vertex) {
|
||||
FILE *file;
|
||||
mesh_t *mesh;
|
||||
float *vertex;
|
||||
unsigned short chunk_type;
|
||||
int chunk_size,content_size;
|
||||
file = fopen(name,"rb");
|
||||
if(!file) {
|
||||
fprintf(stderr,"error open %s file\n",name);
|
||||
return NULL;
|
||||
}
|
||||
chunk_type = read_ushort(file);
|
||||
chunk_size = read_int(file);
|
||||
content_size = chunk_size - 6;
|
||||
if(chunk_type != CHUNK_MAIN) {
|
||||
fprintf(stderr,"wrong main chunk\n");
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
mesh = calloc(1,sizeof(mesh_t));
|
||||
read_chunks(file,content_size,process_main,(void*)mesh);
|
||||
fclose(file);
|
||||
vertex = create_mesh(mesh,num_vertex);
|
||||
free(mesh);
|
||||
return vertex;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue