home *** CD-ROM | disk | FTP | other *** search
- #define __MILETOS_MESH3DS_CPP__
-
- //
- // Libmiletos
- //
- // Copyright (C) Lauris Kaplinski 2008
- //
-
- static const int debug = 0;
-
- #include <string.h>
- #include <stdio.h>
-
- #include <libnr/nr-image.h>
-
- #include <elea/geometry.h>
-
- #include <sehle/commonmaterials.h>
- #include <sehle/material-multipass-dns.h>
-
- #include "uri.h"
- #include "image.h"
- #include "material.h"
-
- #include "mesh3ds.h"
-
- namespace Miletos {
-
- // SD3Data
-
- SD3Data::SD3Data (const unsigned char *cdata, size_t csize, const char *purl)
- : DataBlock (purl, "SD3Data")
- {
- parse (cdata, csize);
- }
-
- SD3Data::~SD3Data (void)
- {
- }
-
- SD3Data *
- SD3Data::getSD3Data (const char *purl)
- {
- SD3Data *sd3 = NULL;
- if (purl) {
- sd3 = (SD3Data *) lookupDataBlock (purl, "SD3Data");
- if (sd3) return sd3;
- URI::URLHandler *handler = URI::getHandler (purl);
- if (handler) {
- size_t csize;
- const unsigned char *cdata = handler->mmapData ((const unsigned char *) purl, &csize);
- if (cdata) {
- sd3 = new SD3Data (cdata, csize, purl);
- handler->munmapData (cdata);
- }
- handler->unRef ();
- }
- }
- return sd3;
- }
-
- SD3Data *
- SD3Data::getSD3Data (const unsigned char *cdata, size_t csize, const char *purl)
- {
- SD3Data *sd3 = NULL;
- if (purl) {
- sd3 = (SD3Data *) lookupDataBlock (purl, "SD3Data");
- if (sd3) return sd3;
- if (cdata) {
- sd3 = new SD3Data (cdata, csize, purl);
- }
- }
- return sd3;
- }
-
- static const u32 SD3_EOF = 0x0000;
- static const u32 SD3_MAIN = 0x4D4D;
- static const u32 SD3_MDATA = 0x3D3D;
- static const u32 SD3_KEYFRAMES = 0xB000;
- static const u32 SD3_OBJECT = 0x4000;
- static const u32 SD3_MESH = 0x4100;
- static const u32 SD3_LIGHT = 0x4600;
- static const u32 SD3_CAMERA = 0x4700;
- static const u32 SD3_VERTICES = 0x4110;
- static const u32 SD3_FACES = 0x4120;
- static const u32 SD3_FACE_MATERIALS = 0x4130;
- static const u32 SD3_UV = 0x4140;
- static const u32 SD3_MATRIX = 0x4160;
- static const u32 SD3_MATERIAL = 0xAFFF;
- static const u32 SD3_MATERIAL_NAME = 0xA000;
- static const u32 SD3_MATERIAL_AMBIENT = 0xA010;
- static const u32 SD3_MATERIAL_DIFFUSE = 0xA020;
- static const u32 SD3_MATERIAL_SPECULAR = 0xA030;
- static const u32 SD3_MATERIAL_SHININESS = 0xA040;
- static const u32 SD3_MATERIAL_TEXTUREMAP = 0xA200;
- static const u32 SD3_MATERIAL_SPECULARMAP = 0xA204;
- static const u32 SD3_MATERIAL_OPACITYMAP = 0xA210;
- static const u32 SD3_MATERIAL_REFLECTIONMAP = 0xA220;
- static const u32 SD3_MATERIAL_BUMPMAP = 0xA230;
- static const u32 SD3_MATERIAL_MAP_FILENAME = 0xA300;
- static const u32 SD3_MATERIAL_MAP_PARAMETERS = 0xA351;
- static const u32 SD3_COLOR_F = 0x0010;
- static const u32 SD3_COLOR_24 = 0x0011;
- static const u32 SD3_COLOR_LIN_F = 0x0013;
- static const u32 SD3_COLOR_LIN_24 = 0x0012;
- static const u32 SD3_INT_PERCENTAGE = 0x0030;
- static const u32 SD3_FLOAT_PERCENTAGE = 0x0031;
-
- static unsigned int
- get_chunk (const unsigned char *cdata, size_t csize, size_t& cpos, u32 &id, u32& size)
- {
- if (cpos == csize) {
- id = SD3_EOF;
- size = 0;
- return true;
- }
- if ((cpos + 6) > csize) return false;
- id = ((u32) cdata[cpos + 1] << 8) | cdata[cpos + 0];
- size = ((u32) cdata[cpos + 5] << 24) | ((u32) cdata[cpos + 4] << 16) | ((u32) cdata[cpos + 3] << 8) | cdata[cpos + 2];
- if (debug > 1) fprintf (stderr, "Chunk: %4x %x\n", id, size);
- return true;
- }
-
- static unsigned int
- get_u8 (const unsigned char *cdata, size_t csize, size_t& cpos, u8& val)
- {
- if ((cpos + 1) > csize) {
- return false;
- } else {
- val = cdata[cpos + 0];
- cpos += 1;
- return true;
- }
- }
-
- static unsigned int
- get_u16 (const unsigned char *cdata, size_t csize, size_t& cpos, u16& val)
- {
- if ((cpos + 2) > csize) {
- return false;
- } else {
- val = ((u32) cdata[cpos + 1] << 8) | cdata[cpos + 0];
- cpos += 2;
- return true;
- }
- }
-
- static unsigned int
- get_u32 (const unsigned char *cdata, size_t csize, size_t& cpos, u32& val)
- {
- if ((cpos + 4) > csize) {
- return false;
- } else {
- val = ((u32) cdata[cpos + 3] << 24) | ((u32) cdata[cpos + 2] << 16) | ((u32) cdata[cpos + 1] << 8) | cdata[cpos + 0];
- cpos += 4;
- return true;
- }
- }
-
- static unsigned int
- get_f32 (const unsigned char *cdata, size_t csize, size_t& cpos, f32& val)
- {
- if ((cpos + 4) > csize) {
- return false;
- } else {
- val = *((f32 *) (cdata + cpos));
- cpos += 4;
- return true;
- }
- }
-
- static unsigned int
- get_string (const unsigned char *cdata, size_t csize, size_t& cpos, const char *& val)
- {
- const char *tval = (const char *) cdata + cpos;
- while (cdata[cpos] && (cpos < csize)) cpos += 1;
- if (cpos >= csize) return false;
- cpos += 1;
- val = tval;
- return true;
- }
-
- unsigned int
- SD3Data::parse (const unsigned char *cdata, size_t csize)
- {
- size_t cpos = 0;
- u32 id;
- u32 size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- if (id != SD3_MAIN) return false;
- if (!parseMAIN (cdata + cpos, size)) return false;
- return true;
- }
-
- unsigned int
- SD3Data::parseMAIN (const unsigned char *cdata, size_t csize)
- {
- size_t cpos = 6;
- bool mdatafound = 0;
- u32 id;
- u32 size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- while (id != SD3_EOF) {
- if (id == SD3_MDATA) {
- if (mdatafound) {
- fprintf (stderr, "SD3Data::parseMAIN: Multiple MData nodes in file\n");
- } else {
- if (!parseMDATA (cdata + cpos, size, mdata)) return false;
- mdatafound = true;
- }
- } else {
- if (debug) fprintf (stderr, "MAIN: %4x %x\n", id, size);
- }
- cpos += size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- }
- return true;
- }
-
- unsigned int
- SD3Data::parseMDATA (const unsigned char *cdata, size_t csize, MData& mdata)
- {
- size_t cpos = 6;
- u32 id;
- u32 size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- while (id != SD3_EOF) {
- if (id == SD3_OBJECT) {
- Object obj;
- if (!parseOBJECT (cdata + cpos, size, obj)) return false;
- mdata.objects.push_back (obj);
- } else if (id == SD3_MATERIAL) {
- Material mat;
- mat.diffuse = Elea::Color4fWhite;
- if (!parseMATERIAL (cdata + cpos, size, mat)) return false;
- mdata.materials.push_back (mat);
- } else {
- if (debug) fprintf (stderr, "MDATA: %4x %x\n", id, size);
- }
- cpos += size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- }
- return true;
- }
-
- unsigned int
- SD3Data::parseOBJECT (const unsigned char *cdata, size_t csize, Object& obj)
- {
- size_t cpos = 6;
- const char *name;
- if (!get_string (cdata, csize, cpos, name)) return false;
- obj.name = name;
- bool meshfound = 0;
- u32 id;
- u32 size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- while (id != SD3_EOF) {
- if (id == SD3_MESH) {
- if (meshfound) {
- fprintf (stderr, "SD3Data::parseOBJECT: Multiple Mesh nodes in file\n");
- } else {
- if (!parseMESH (cdata + cpos, size, obj.mesh)) return false;
- meshfound = true;
- }
- } else if (id == SD3_LIGHT) {
- } else if (id == SD3_CAMERA) {
- } else {
- if (debug) fprintf (stderr, "OBJECT: %4x %x\n", id, size);
- }
- cpos += size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- }
- return true;
- }
-
- unsigned int
- SD3Data::parseMESH (const unsigned char *cdata, size_t csize, Mesh& mesh)
- {
- size_t cpos = 6;
- u32 id;
- u32 size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- while (id != SD3_EOF) {
- if (id == SD3_VERTICES) {
- if (!parseVERTICES (cdata + cpos, size, mesh)) return false;
- } else if (id == SD3_FACES) {
- if (!parseFACES (cdata + cpos, size, mesh)) return false;
- } else if (id == SD3_UV) {
- if (!parseUV (cdata + cpos, size, mesh)) return false;
- } else if (id == SD3_MATRIX) {
- if (!parseMATRIX (cdata + cpos, size, mesh)) return false;
- } else {
- if (debug) fprintf (stderr, "MESH: %4x %x\n", id, size);
- }
- cpos += size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- }
- return true;
- }
-
- unsigned int
- SD3Data::parseVERTICES (const unsigned char *cdata, size_t csize, Mesh& mesh)
- {
- size_t cpos = 6;
- u16 count;
- if (!get_u16 (cdata, csize, cpos, count)) return false;
- mesh.vdata.resize (count);
- for (unsigned int i = 0; i < count; i++) {
- for (int j = 0; j < 3; j++) {
- if (!get_f32 (cdata, csize, cpos, mesh.vdata[i][j])) {
- return false;
- }
- }
- }
- return true;
- }
-
- unsigned int
- SD3Data::parseFACES (const unsigned char *cdata, size_t csize, Mesh& mesh)
- {
- size_t cpos = 6;
- u16 count;
- if (!get_u16 (cdata, csize, cpos, count)) return false;
- mesh.fdata.resize (count * 4);
- for (unsigned int i = 0; i < (unsigned int) count * 4; i++) {
- if (!get_u16 (cdata, csize, cpos, mesh.fdata[i])) return false;
- }
- u32 id;
- u32 size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- while (id != SD3_EOF) {
- if (id == SD3_FACE_MATERIALS) {
- MGroup mgroup;
- if (!parseMGROUP (cdata + cpos, size, mgroup)) return false;
- mesh.mgroups.push_back (mgroup);
- } else {
- if (debug) fprintf (stderr, "FACES: %4x %x\n", id, size);
- }
- cpos += size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- }
- return true;
- }
-
- unsigned int
- SD3Data::parseMGROUP (const unsigned char *cdata, size_t csize, MGroup& mgroup)
- {
- size_t cpos = 6;
- const char *name;
- if (!get_string (cdata, csize, cpos, name)) return false;
- mgroup.matname = name;
- u16 count;
- if (!get_u16 (cdata, csize, cpos, count)) return false;
- mgroup.faces.resize (count);
- for (unsigned int i = 0; i < (unsigned int) count; i++) {
- if (!get_u16 (cdata, csize, cpos, mgroup.faces[i])) return false;
- }
- return true;
- }
-
- unsigned int
- SD3Data::parseUV (const unsigned char *cdata, size_t csize, Mesh& mesh)
- {
- size_t cpos = 6;
- u16 count;
- if (!get_u16 (cdata, csize, cpos, count)) return false;
- mesh.tdata.resize (count);
- for (unsigned int i = 0; i < count; i++) {
- for (int j = 0; j < 2; j++) {
- if (!get_f32 (cdata, csize, cpos, mesh.tdata[i][j])) {
- return false;
- }
- }
- }
- return true;
- }
-
- unsigned int
- SD3Data::parseMATRIX (const unsigned char *cdata, size_t csize, Mesh& mesh)
- {
- return true;
- }
-
- unsigned int
- SD3Data::parseMATERIAL (const unsigned char *cdata, size_t csize, Material& mat)
- {
- size_t cpos = 6;
- const char *name = NULL;
- u32 id;
- u32 size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- while (id != SD3_EOF) {
- if (id == SD3_MATERIAL_NAME) {
- size_t pos = 6;
- if (!get_string (cdata + cpos, size, pos, name)) return false;
- mat.name = name;
- } else if (id == SD3_MATERIAL_AMBIENT) {
- if (!parseCOLOR (cdata + cpos, size, mat.ambient)) return false;
- } else if (id == SD3_MATERIAL_DIFFUSE) {
- if (!parseCOLOR (cdata + cpos, size, mat.diffuse)) return false;
- } else if (id == SD3_MATERIAL_SPECULAR) {
- if (!parseCOLOR (cdata + cpos, size, mat.specular)) return false;
- } else if (id == SD3_MATERIAL_SHININESS) {
- if (!parsePERCENTAGE (cdata + cpos, size, mat.shininess)) return false;
- } else if (id == SD3_MATERIAL_TEXTUREMAP) {
- if (!parseMAP (cdata + cpos, size, mat.filename)) return false;
- } else if (id == SD3_MATERIAL_SPECULARMAP) {
- } else if (id == SD3_MATERIAL_OPACITYMAP) {
- if (!parseMAP (cdata + cpos, size, mat.opacitymap)) return false;
- } else if (id == SD3_MATERIAL_REFLECTIONMAP) {
- } else if (id == SD3_MATERIAL_BUMPMAP) {
- } else {
- if (debug) fprintf (stderr, "MATERIAL: %4x %x\n", id, size);
- }
- cpos += size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- }
- return true;
- }
-
- unsigned int
- SD3Data::parseMAP (const unsigned char *cdata, size_t csize, std::string& filename)
- {
- size_t cpos = 6;
- u32 id;
- u32 size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- while (id != SD3_EOF) {
- if (id == SD3_MATERIAL_MAP_FILENAME) {
- size_t pos = 6;
- const char *name = NULL;
- if (!get_string (cdata + cpos, size, pos, name)) return false;
- filename = name;
- } else {
- if (debug) fprintf (stderr, "MAP: %4x %x\n", id, size);
- }
- cpos += size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- }
- return true;
- }
-
- unsigned int
- SD3Data::parseCOLOR (const unsigned char *cdata, size_t csize, Elea::Color4f& color)
- {
- size_t cpos = 6;
- u32 id;
- u32 size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- while (id != SD3_EOF) {
- size_t pos = cpos + 6;
- if (id == SD3_COLOR_F) {
- for (int i = 0; i < 3; i++) {
- if (!get_f32 (cdata, csize, pos, color[i])) return false;
- }
- } else if (id == SD3_COLOR_LIN_F) {
- for (int i = 0; i < 3; i++) {
- if (!get_f32 (cdata, csize, pos, color[i])) return false;
- }
- } else if (id == SD3_COLOR_24) {
- u8 c;
- for (int i = 0; i < 3; i++) {
- if (!get_u8 (cdata, csize, pos, c)) return false;
- color[i] = (float) c / 255;
- }
- } else if (id == SD3_COLOR_LIN_24) {
- u8 c;
- for (int i = 0; i < 3; i++) {
- if (!get_u8 (cdata, csize, pos, c)) return false;
- color[i] = (float) c / 255;
- }
- } else {
- if (debug) fprintf (stderr, "COLOR: %4x %x\n", id, size);
- }
- cpos += size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- }
- color[Elea::A] = 1;
- return true;
- }
-
- unsigned int
- SD3Data::parsePERCENTAGE (const unsigned char *cdata, size_t csize, float& value)
- {
- size_t cpos = 6;
- u32 id;
- u32 size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- while (id != SD3_EOF) {
- size_t pos = cpos + 6;
- if (id == SD3_INT_PERCENTAGE) {
- u16 val;
- if (!get_u16 (cdata, csize, pos, val)) return false;
- value = val / 65535.0f;
- } else if (id == SD3_FLOAT_PERCENTAGE) {
- float val;
- if (!get_f32 (cdata, csize, pos, val)) return false;
- value = val;
- } else {
- if (debug) fprintf (stderr, "PERCENTAGE: %4x %x\n", id, size);
- }
- cpos += size;
- if (!get_chunk (cdata, csize, cpos, id, size)) return false;
- }
- return true;
- }
-
- // Geometry3DS
-
- Geometry3DS::Geometry3DS (void)
- : StaticGeometry(0), obj(NULL)
- {
- }
-
- static Object *
- geometry3ds_factory (void)
- {
- return new Geometry3DS();
- }
-
- const Object::Type *
- Geometry3DS::objectType (void)
- {
- return type ();
- }
-
- const Object::Type *
- Geometry3DS::type (void)
- {
- static Type *mytype = NULL;
- static const Attribute attrs[] = {
- { "source", NULL, 0 }
- };
- if (!mytype) mytype = new Type(StaticGeometry::type (), "Geometry3DS", "geometry3DS", geometry3ds_factory, sizeof (attrs) / sizeof (attrs[0]), attrs);
- return mytype;
- }
-
- void
- Geometry3DS::build (Thera::Node *pnode, Document *doc, BuildCtx *ctx)
- {
- StaticGeometry::build (pnode, doc, ctx);
- buildAllAttributes (type (), ctx);
- }
-
- void
- Geometry3DS::release (void)
- {
- clear ();
- StaticGeometry::release ();
- }
-
- void
- Geometry3DS::set (const char *attrid, const char *val)
- {
- if (!strcmp (attrid, "source")) {
- clear ();
- if (val) {
- obj = SD3Data::getSD3Data (val);
- if (obj) loadData ();
- }
- requestUpdate (MODIFIED | MESH_DEFINITION_MODIFIED);
- } else {
- StaticGeometry::set (attrid, val);
- }
- }
-
- TextureInfo *
- Geometry3DS::getTextureInfo (unsigned int matidx, unsigned int texidx, unsigned int getimage)
- {
- if (texidx >= ntextures) return NULL;
- if (!textures[texidx]) return NULL;
- if (nr_image_is_empty (textures[texidx]->pixels)) return NULL;
- TextureInfo *tex = new TextureInfo();
- tex->urn = strdup (textures[texidx]->url.c_str ());
- if (getimage) {
- tex->image = textures[texidx]->pixels;
- nr_image_ref (tex->image);
- }
- return tex;
- }
-
- u32
- Geometry3DS::getMaterialInfo (Miletos::MaterialInfo *mat, u32 matidx)
- {
- if (matidx >= (u32) nmaterials) return false;
- if (mat) {
- if (textures[matidx] && !nr_image_is_empty (textures[matidx]->pixels)) {
- mat->type = MaterialInfo::TEXTURE;
- mat->diffuseTexture = (int) matidx;
- } else {
- mat->type = Miletos::MaterialInfo::COLOR;
- mat->diffuseTexture = -1;
- }
- mat->id = obj->mdata.materials[matidx].name.c_str ();
- mat->diffuseColor = obj->mdata.materials[matidx].diffuse;
- mat->specularColor = obj->mdata.materials[matidx].specular;
- mat->specularShininess = obj->mdata.materials[matidx].shininess;
- mat->normalTexture = -1;
- mat->specularTexture = -1;
- }
- return true;
- }
-
- Sehle::Material *
- Geometry3DS::getMaterial (int matidx, Sehle::Engine *engine)
- {
- if ((matidx < 0) || (matidx >= (int) nmaterials)) {
- Sehle::WireMaterial *mat = Sehle::WireMaterial::newWireMaterial (engine, "Poser:Geometry:invalidMaterial");
- if (!mat->built) mat->setColor (Elea::Color4fRed);
- return mat;
- }
- if (textures[matidx] && !nr_image_is_empty (textures[matidx]->pixels)) {
- Sehle::MaterialMultipassDNS *mat = Sehle::MaterialMultipassDNS::newMaterialMultipassDNS (engine, textures[matidx]->url.c_str ());
- if (!mat->built) {
- mat->setMap (Sehle::MaterialMultipassDNS::COLOR, textures[matidx]->url.c_str (), &textures[matidx]->pixels->pixels);
- }
- return mat;
- }
- Sehle::ColorMaterial *mat = Sehle::ColorMaterial::newColorMaterial (engine, obj->mdata.materials[matidx].name.c_str ());
- if (!mat->built) mat->setColor (obj->mdata.materials[matidx].diffuse);
- return mat;
- }
-
- void
- Geometry3DS::clear (void)
- {
- for (size_t i = 0; i < textures.size (); i++) {
- if (textures[i]) {
- nr_image_unref (textures[i]->pixels);
- delete textures[i];
- }
- }
- textures.clear ();
- if (obj) {
- obj->unRef ();
- obj = NULL;
- }
- StaticGeometry::clear ();
- }
-
- static NRImage *
- add_alpha (NRImage *c, NRImage *a)
- {
- if ((c->pixels.area.x0 != a->pixels.area.x0) || (c->pixels.area.x1 != a->pixels.area.x1) ||
- (c->pixels.area.y0 != a->pixels.area.y0) || (c->pixels.area.y1 != a->pixels.area.y1)) {
- nr_image_ref (c);
- return c;
- }
- NRImage *d = nr_image_new ();
- int width = c->pixels.area.x1 - c->pixels.area.x0;
- int height = c->pixels.area.x1 - c->pixels.area.x0;
- int cbpp = NR_PIXBLOCK_BPP (&c->pixels);
- int abpp = NR_PIXBLOCK_BPP (&a->pixels);
- nr_pixblock_setup (&d->pixels, NR_PIXBLOCK_MODE_R8G8B8A8N, 0, 0, width, height, 0);
- for (int y = 0; y < height; y++) {
- unsigned char *dp = NR_PIXBLOCK_PX (&d->pixels) + y * d->pixels.rs;
- unsigned char *cp = NR_PIXBLOCK_PX (&c->pixels) + y * c->pixels.rs;
- unsigned char *ap = NR_PIXBLOCK_PX (&a->pixels) + y * a->pixels.rs;
- for (int x = 0; x < width; x++) {
- if (cbpp == 1) {
- dp[0] = cp[0];
- dp[1] = cp[0];
- dp[2] = cp[0];
- } else {
- dp[0] = cp[0];
- dp[1] = cp[1];
- dp[2] = cp[2];
- }
- dp[3] = 255 - ap[0];
- dp += 4;
- cp += cbpp;
- ap += abpp;
- }
- }
- d->pixels.empty = 0;
- return d;
- }
-
- void
- Geometry3DS::loadData (void)
- {
- if (!obj) return;
- if (obj->mdata.materials.empty ()) return;
-
- // Materials
- ntextures = obj->mdata.materials.size ();
- nmaterials = obj->mdata.materials.size ();
- // fixme: Sort out texture stuff
- textures.resize (nmaterials, NULL);
- URI::URLHandler *handler = URI::getHandler (obj->uri);
- if (handler) {
- for (unsigned int i = 0; i < nmaterials; i++) {
- if (!obj->mdata.materials[i].filename.empty ()) {
- Texture *tex = NULL;
- size_t csize;
- const unsigned char *cdata = handler->mmapDataRelative (obj->mdata.materials[i].filename.c_str (), &csize);
- if (cdata) {
- NRImage *img = nr_image_new ();
- if (Image::load (&img->pixels, cdata, csize)) {
- tex = new Texture ();
- // fixme:
- tex->url = obj->mdata.materials[i].filename;
- tex->pixels = img;
- textures[i] = tex;
- } else {
- nr_image_unref (img);
- }
- handler->munmapData (cdata);
- // Try opacity
- if (tex && !obj->mdata.materials[i].opacitymap.empty ()) {
- cdata = handler->mmapDataRelative (obj->mdata.materials[i].opacitymap.c_str (), &csize);
- if (cdata) {
- img = nr_image_new ();
- if (Image::load (&img->pixels, cdata, csize)) {
- NRImage *newimg = add_alpha (tex->pixels, img);
- nr_image_unref (tex->pixels);
- tex->pixels = newimg;
- }
- nr_image_unref (img);
- handler->munmapData (cdata);
- }
- }
- }
- }
- }
- handler->unRef ();
- }
-
- u32 lnumv = 0;
- u32 lnumi = 0;
- std::vector<u32> vstart;
- for (size_t i = 0; i < obj->mdata.objects.size (); i++) {
- vstart.push_back (lnumv);
- lnumv += obj->mdata.objects[i].mesh.vdata.size ();
- lnumi += 3 * (obj->mdata.objects[i].mesh.fdata.size () / 4);
- }
- // Vertices
- setNumVertices (lnumv, true, true, false);
- for (size_t i = 0; i < obj->mdata.objects.size (); i++) {
- if (obj->mdata.objects[i].mesh.vdata.empty ()) continue;
- memcpy (&vbase[vstart[i]], &obj->mdata.objects[i].mesh.vdata[0], obj->mdata.objects[i].mesh.vdata.size () * sizeof (Elea::Vector3f));
- if (obj->mdata.objects[i].mesh.tdata.size () == obj->mdata.objects[i].mesh.vdata.size ()) {
- memcpy (&xbase[vstart[i]], &obj->mdata.objects[i].mesh.tdata[0], obj->mdata.objects[i].mesh.tdata.size () * sizeof (Elea::Vector2f));
- }
- }
- // Indices
- setNumIndices (lnumi);
- setNumFrags (nmaterials);
- // Assign indices
- unsigned int iidx = 0;
- for (unsigned int i = 0; i < nmaterials; i++) {
- Frag *frag = &frags[i];
- frag->matidx = i;
- frag->firstindex = iidx;
- frag->visible = 1;
- const char *matname = obj->mdata.materials[i].name.c_str ();
- for (size_t j = 0; j < obj->mdata.objects.size (); j++) {
- for (size_t k = 0; k < obj->mdata.objects[j].mesh.mgroups.size (); k++) {
- if (!obj->mdata.objects[j].mesh.mgroups[k].matname.compare (matname)) {
- // Assign this MGroup to current fragment
- for (size_t l = 0; l < obj->mdata.objects[j].mesh.mgroups[k].faces.size (); l++) {
- unsigned int fidx = obj->mdata.objects[j].mesh.mgroups[k].faces[l];
- for (int m = 0; m < 3; m++) {
- indices[iidx++] = vstart[j] + obj->mdata.objects[j].mesh.fdata[4 * fidx + m];
- }
- }
- }
- }
- }
- frag->numindices = iidx - frag->firstindex;
- }
-
- if (nindices > 0) {
- Elea::Geometry::calculateNormals (nbase[0], sizeof (nbase[0]), vbase[0], sizeof (vbase[0]), nvertices, &indices[0], nindices, true);
- }
-
- requestUpdate (MODIFIED | MESH_DEFINITION_MODIFIED);
- }
-
- } // Namespace Miletos
-
-