Loading and display of basic 3DS models.
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAGICNUMBER 0xB3D0
#define CHUNKMAIN 0x4D4D
#define CHUNKMAINVERSION 0x0002
#define CHUNK3D 0x3D3D
#define CHUNK3DVERSION 0x3D3E
#define CHUNK3DOBJECT 0x4000
#define CHUNK3DOBJECTMESH 0x4100
#define CHUNK3DOBJECTMESHVERTICES 0x4110
#define CHUNK3DOBJECTMESHFACES 0x4120
#define CHUNK3DOBJECTMESHMATGROUP 0x4130
#define CHUNK3DOBJECTMESHMAPPING 0x4140
#define CHUNK3DMATERIAL 0xAFFF
#define MATNAME 0xA000
#define MATDIFFUSE 0xA020
#define MATSPECULAR 0xA030
#define MATTRANSPARENCY 0xA050
#define COLOR_F 0x0010
#define COLOR_24 0x0011
#define LIN_COLOR_24 0x0012
#define LIN_COLOR_F 0x0013
#define INT_PERCENTAGE 0x0030
#define FLOAT_PERCENTAGE 0x0031
class Material {
public:
Material() {
color[0] = color[1] = color[2] = 0;
transparency = 0;
}
~Material() { }
};
typedef struct _Chunk {
UInt_t offset, len, endoffset;
} Chunk;
typedef struct _Vertex {
typedef struct _Face {
} Face;
class Model {
public:
char matname[256];
Face *flist;
Model() {
sprintf(matname,"");
vlist = 0;
flist = 0;
numverts = numfaces = 0;
}
~Model() {
if (vlist != 0) delete [] vlist;
if (flist != 0) delete [] flist;
}
};
Int_t ReadChunk(FILE*, Chunk*);
Int_t ReadMainChunk(FILE*);
Int_t ReadVerticesChunk(FILE*);
Int_t ReadFacesChunk(FILE*);
Int_t ReadMappingChunk(FILE*);
Int_t ReadASCIIZ(FILE*,
char*);
Int_t ReadObjectMaterial(FILE *);
Model model;
Material *material[1024];
Int_t Read3DSFile(
const char *fname)
{
FILE *infile;
infile = fopen(fname, "rb");
if (infile == 0) {
printf("Error : Input File Could Not Be Opened!\n");
return -1;
}
if (ReadMainChunk(infile) != 0) {
printf("Error : Input File Could Not Be Read!\n");
}
fclose(infile);
return 0;
}
{
c->endoffset =
c->offset +
c->len;
return(0);
}
{
Chunk chunk;
if (chunk.idnum != CHUNKMAIN) return(-1);
while ((ReadChunk(
f, &chunk) == 0) && (!feof(
f))) {
if (chunk.idnum == CHUNK3D) {
Read3DChunk(
f, chunk.endoffset);
}
else {
fseek(
f, chunk.offset + chunk.len, SEEK_SET);
}
}
return 0;
}
{
Chunk chunk;
while ((ReadChunk(
f, &chunk) == 0) && (!feof(
f))) {
if (chunk.idnum == CHUNK3DOBJECT) {
ReadObjectChunk(
f, chunk.endoffset);
fseek(
f, chunk.endoffset, SEEK_SET);
}
else if (chunk.idnum == CHUNK3DMATERIAL) {
ReadMaterialChunk(
f, chunk.endoffset);
fseek(
f, chunk.endoffset, SEEK_SET);
}
else {
if (chunk.endoffset < len) {
fseek(
f, chunk.endoffset, SEEK_SET);
}
else {
break;
}
}
}
return 0;
}
{
Chunk chunk;
material[nummaterials] = new Material();
while ((ReadChunk(
f, &chunk) == 0) && (!feof(
f))) {
if (chunk.idnum == MATNAME) {
strcpy(material[nummaterials]->
name,
name);
fseek(
f, chunk.endoffset, SEEK_SET);
}
else if (chunk.idnum == MATDIFFUSE) {
ReadColor(
f, chunk.endoffset);
fseek(
f, chunk.endoffset, SEEK_SET);
}
else if (chunk.idnum == MATTRANSPARENCY) {
ReadTransparency(
f, chunk.endoffset);
fseek(
f, chunk.endoffset, SEEK_SET);
}
else {
if (chunk.endoffset < len) {
fseek(
f, chunk.endoffset, SEEK_SET);
}
else {
break;
}
}
}
nummaterials++;
return 0;
}
{
Chunk chunk;
float fr, fg, fb;
while ((ReadChunk(
f, &chunk) == 0) && (!feof(
f))) {
if (chunk.idnum == LIN_COLOR_24) {
fread(&material[nummaterials]->color[0],
sizeof(
UChar_t), 1,
f);
fread(&material[nummaterials]->color[1],
sizeof(
UChar_t), 1,
f);
fread(&material[nummaterials]->color[2],
sizeof(
UChar_t), 1,
f);
fseek(
f, chunk.endoffset, SEEK_SET);
}
else if (chunk.idnum == COLOR_24) {
fread(&material[nummaterials]->color[0],
sizeof(
UChar_t), 1,
f);
fread(&material[nummaterials]->color[1],
sizeof(
UChar_t), 1,
f);
fread(&material[nummaterials]->color[2],
sizeof(
UChar_t), 1,
f);
fseek(
f, chunk.endoffset, SEEK_SET);
}
else if (chunk.idnum == LIN_COLOR_F) {
fseek(
f, chunk.endoffset, SEEK_SET);
}
else if (chunk.idnum == COLOR_F) {
fseek(
f, chunk.endoffset, SEEK_SET);
}
else {
if (chunk.endoffset < len) {
fseek(
f, chunk.endoffset, SEEK_SET);
}
else {
break;
}
}
}
return 0;
}
{
Chunk chunk;
float ftransp;
while ((ReadChunk(
f, &chunk) == 0) && (!feof(
f))) {
if (chunk.idnum == INT_PERCENTAGE) {
material[nummaterials]->transparency = stransp;
fseek(
f, chunk.endoffset, SEEK_SET);
}
else if (chunk.idnum == FLOAT_PERCENTAGE) {
fread(&ftransp,
sizeof(
float), 1,
f);
fseek(
f, chunk.endoffset, SEEK_SET);
}
else {
if (chunk.endoffset < len) {
fseek(
f, chunk.endoffset, SEEK_SET);
}
else {
break;
}
}
}
return 0;
}
Int_t ReadObjectMaterial(FILE *
f)
{
ReadASCIIZ(
f, model.matname);
return 0;
}
{
Chunk chunk;
while ((ReadChunk(
f, &chunk) == 0) && (!feof(
f))) {
if (chunk.idnum == CHUNK3DOBJECTMESH) {
ReadMeshChunk(
f, chunk.endoffset,
name);
}
else {
if (chunk.endoffset < len) {
fseek(
f, chunk.endoffset, SEEK_SET);
}
else {
break;
}
}
}
return 0;
}
{
Chunk chunk;
model.vlist = 0;
model.flist = 0;
model.numverts = model.numfaces = 0;
sprintf(model.name, "%s", objname);
printf("Reading Mesh : %s\n", objname);
while ((ReadChunk(
f, &chunk) == 0) && (!feof(
f))) {
if (chunk.idnum == CHUNK3DOBJECTMESHVERTICES) {
}
else if (chunk.idnum == CHUNK3DOBJECTMESHFACES) {
}
else if (chunk.idnum == CHUNK3DOBJECTMESHMAPPING) {
}
else if (chunk.idnum == CHUNK3DOBJECTMESHMATGROUP) {
}
else {
if (chunk.endoffset < len) {
fseek(
f, chunk.endoffset, SEEK_SET);
}
else {
break;
}
}
}
ConvertModel();
if (model.vlist != 0) delete [] model.vlist;
if (model.flist != 0) delete [] model.flist;
model.vlist = 0;
model.flist = 0;
model.numverts = model.numfaces = 0;
sprintf(model.name,"");
nummodels++;
return 0;
}
Int_t ReadVerticesChunk(FILE *
f)
{
printf("Reading %i Vertices...", numv);
model.vlist =
new Vertex[numv];
if (model.vlist == 0) {
for (i = 0; i < numv; i++) {
}
printf("\nWarning : Insufficient Memory to Load Vertices!\n");
return -1;
}
for (i = 0; i < numv; i++) {
fread(&model.vlist[i].x,
sizeof(
Float_t), 1,
f);
fread(&model.vlist[i].y,
sizeof(
Float_t), 1,
f);
fread(&model.vlist[i].z,
sizeof(
Float_t), 1,
f);
}
model.numverts = (
UInt_t) numv;
printf("Done!\n");
return 0;
}
{
printf("Reading %i Faces...", numf);
model.flist = new Face[numf];
if (model.flist == 0) {
for (i = 0; i < numf; i++) {
}
printf("\nWarning : Insufficient Memory to Load Faces!\n");
return -1;
}
for (i = 0; i < numf; i++) {
model.flist[i].v1 = (
UInt_t)(v1);
model.flist[i].v2 = (
UInt_t)(v2);
model.flist[i].v3 = (
UInt_t)(v3);
}
model.numfaces = (
UInt_t)(numf);
printf("Done!\n");
return 0;
}
Int_t ReadMappingChunk(FILE *
f)
{
printf("Reading %i Texture Coordinates...", numuv);
if (numuv != model.numverts) {
for (i = 0; i < numuv; i++) {
}
printf("\nWarning : Number of Vertices and Mapping Data do not match!\n");
return -1;
}
for (i = 0; i < numuv; i++) {
fread(&model.vlist[i].u,
sizeof(
Float_t), 1,
f);
fread(&model.vlist[i].v,
sizeof(
Float_t), 1,
f);
}
printf("Done!\n");
return 0;
}
{
do {
fread(&
c,
sizeof(
char), 1,
f);
index++;
if (index == 255) {
}
}
while ((
c != 0) && (!feof(
f)));
return 0;
}
{
if (ts[nummodels] == 0)
return -1;
for (i=0; i<model.numverts; ++i) {
ts[nummodels]->
SetVertex(i, model.vlist[i].x, model.vlist[i].y,
model.vlist[i].z);
}
for (i=0; i<model.numfaces; ++i) {
ts[nummodels]->
SetTriangle(i, model.flist[i].v1, model.flist[i].v2,
model.flist[i].v3);
}
ts[nummodels]->
SetName(model.name);
for (i = 0; i < nummaterials; i++) {
if (strcmp(model.matname, material[i]->name) == 0) {
material[i]->color[1],
material[i]->color[2]);
break;
}
}
return 0;
}
void view3ds(const char *fname = "nasashuttle.3ds")
{
for (i=0;i<2048;i++) ts[i] = 0;
for (i=0;i<1024;i++) material[i] = 0;
model.vlist = 0;
model.flist = 0;
nummodels = 0;
if (Read3DSFile(fname) == 0) {
for (i=0;i<nummodels;i++) {
if (ts[i]) {
}
}
}
for (i = 0; i < nummaterials; i++)
if (material[i] != 0) delete material[i];
}
R__EXTERN TEveManager * gEve
virtual void AddElement(TEveElement *el)
Add el to the list of children.
virtual void SetMainTransparency(Char_t t)
Set main-transparency.
virtual TEveTrans & RefMainTrans()
Return reference to main transformation.
virtual void SetMainColor(Color_t color)
Set main color of the element.
void SetMainColorRGB(UChar_t r, UChar_t g, UChar_t b)
Convert RGB values to Color_t and call SetMainColor.
void AddElement(TEveElement *element, TEveElement *parent=0)
Add an element.
static TEveManager * Create(Bool_t map_window=kTRUE, Option_t *opt="FIV")
If global TEveManager* gEve is not set initialize it.
void Redraw3D(Bool_t resetCameras=kFALSE, Bool_t dropLogicals=kFALSE)
void RotateLF(Int_t i1, Int_t i2, Double_t amount)
Rotate in local frame. Does optimised version of MultRight.
Made from a list of vertices and a list of triangles (triplets of vertex indices).
void SetTriangle(Int_t i, Int_t v0, Int_t v1, Int_t v2)
void SetVertex(Int_t i, Float_t x, Float_t y, Float_t z)
void GenerateTriangleNormals()
Generate triangle normals via cross product of triangle edges.
virtual void SetName(const char *name)
Set the name of the TNamed.
void Vertex(const Double_t *v)