/* \brief import Assimp file */ int _glhckImportAssimp(glhckObject *object, const char *file, const glhckImportModelParameters *params, glhckGeometryIndexType itype, glhckGeometryVertexType vtype) { const struct aiScene *scene; glhckObject *first = NULL; unsigned int aflags; CALL(0, "%p, %s, %p", object, file, params); /* import the model using assimp * TODO: make import hints tunable? * Needs changes to import protocol! */ aflags = aiProcessPreset_TargetRealtime_Fast | aiProcess_OptimizeGraph; if (!params->animated && params->flatten) aflags |= aiProcess_PreTransformVertices; scene = aiImportFile(file, aflags); if (!scene) goto assimp_fail; /* mark ourself as special root object. * this makes most functions called on root object echo to children */ object->flags |= GLHCK_OBJECT_ROOT; /* this is going to be the first object in mesh, * the object returned by this importer is just invisible root object. */ if (!(first = glhckObjectNew())) goto fail; glhckObjectAddChild(object, first); glhckObjectFree(first); /* process the model */ if (processModel(file, object, first, scene, scene->mRootNode, itype, vtype, params) != RETURN_OK) goto fail; /* process the animated model part */ if (params->animated && processBonesAndAnimations(object, scene) != RETURN_OK) goto fail; /* close file */ NULLDO(aiReleaseImport, scene); RET(0, "%d", RETURN_OK); return RETURN_OK; assimp_fail: DEBUG(GLHCK_DBG_ERROR, aiGetErrorString()); fail: IFDO(aiReleaseImport, scene); IFDO(glhckObjectFree, first); RET(0, "%d", RETURN_FAIL); return RETURN_FAIL; }
Object::~Object() { glhckObjectFree(o); }
UfoLaser::~UfoLaser() { glhckObjectFree(o); }
static int processModel(const char *file, glhckObject *object, glhckObject *current, const struct aiScene *sc, const struct aiNode *nd, glhckGeometryIndexType itype, glhckGeometryVertexType vtype, const glhckImportModelParameters *params) { unsigned int m, f; unsigned int numVertices = 0, numIndices = 0; unsigned int ioffset, voffset; glhckImportIndexData *indices = NULL; glhckImportVertexData *vertexData = NULL; glhckMaterial *material = NULL; glhckTexture **textureList = NULL, *texture = NULL; glhckAtlas *atlas = NULL; const struct aiMesh *mesh; const struct aiFace *face; int canFreeCurrent = 0; int hasTexture = 0; assert(file); assert(object && current); assert(sc && nd); /* combine && atlas loading path */ if (params->flatten) { /* prepare atlas for texture combining */ if (!(atlas = glhckAtlasNew())) goto assimp_no_memory; /* texturelist for offseting coordinates */ if (!(textureList = _glhckCalloc(nd->mNumMeshes, sizeof(_glhckTexture*)))) goto assimp_no_memory; /* gather statistics */ for (m = 0; m != nd->mNumMeshes; ++m) { mesh = sc->mMeshes[nd->mMeshes[m]]; if (!mesh->mVertices) continue; for (f = 0; f != mesh->mNumFaces; ++f) { face = &mesh->mFaces[f]; if (!face) goto fail; numIndices += face->mNumIndices; } numVertices += mesh->mNumVertices; if ((texture = textureFromMaterial(file, sc->mMaterials[mesh->mMaterialIndex]))) { glhckAtlasInsertTexture(atlas, texture); glhckTextureFree(texture); textureList[m] = texture; hasTexture = 1; } } /* allocate vertices */ if (!(vertexData = _glhckCalloc(numVertices, sizeof(glhckImportVertexData)))) goto assimp_no_memory; /* allocate indices */ if (!(indices = _glhckMalloc(numIndices * sizeof(glhckImportIndexData)))) goto assimp_no_memory; /* pack combined textures */ if (hasTexture) { if (glhckAtlasPack(atlas, GLHCK_RGBA, 1, 0, glhckTextureDefaultParameters()) != RETURN_OK) goto fail; } else { NULLDO(glhckAtlasFree, atlas); NULLDO(_glhckFree, textureList); } /* join vertex data */ for (m = 0, ioffset = 0, voffset = 0; m != nd->mNumMeshes; ++m) { mesh = sc->mMeshes[nd->mMeshes[m]]; if (!mesh->mVertices) continue; if (textureList) texture = textureList[m]; else texture = NULL; joinMesh(mesh, voffset, indices+ioffset, vertexData+voffset, atlas, texture); for (f = 0; f != mesh->mNumFaces; ++f) { face = &mesh->mFaces[f]; if (!face) goto fail; ioffset += face->mNumIndices; } voffset += mesh->mNumVertices; } /* create material */ if (hasTexture && !(material = glhckMaterialNew(texture))) goto assimp_no_memory; /* finally build the model */ if (buildModel(current, numIndices, numVertices, indices, vertexData, itype, vtype) == RETURN_OK) { _glhckObjectFile(current, nd->mName.data); if (material) glhckObjectMaterial(current, material); if (!(current = glhckObjectNew())) goto fail; glhckObjectAddChild(object, current); glhckObjectFree(current); canFreeCurrent = 1; } /* free stuff */ IFDO(glhckAtlasFree, atlas); IFDO(glhckMaterialFree, material); IFDO(_glhckFree, textureList); NULLDO(_glhckFree, vertexData); NULLDO(_glhckFree, indices); } else { /* default loading path */ for (m = 0, ioffset = 0, voffset = 0; m != nd->mNumMeshes; ++m) { mesh = sc->mMeshes[nd->mMeshes[m]]; if (!mesh->mVertices) continue; /* gather statistics */ numIndices = 0; for (f = 0; f != mesh->mNumFaces; ++f) { face = &mesh->mFaces[f]; if (!face) goto fail; numIndices += face->mNumIndices; } numVertices = mesh->mNumVertices; // FIXME: create materialFromAssimpMaterial // that returns glhckMaterial with correct stuff /* get texture */ hasTexture = 0; if ((texture = textureFromMaterial(file, sc->mMaterials[mesh->mMaterialIndex]))) hasTexture = 1; /* create material */ if (hasTexture && !(material = glhckMaterialNew(texture))) goto assimp_no_memory; /* allocate vertices */ if (!(vertexData = _glhckCalloc(numVertices, sizeof(glhckImportVertexData)))) goto assimp_no_memory; /* allocate indices */ if (!(indices = _glhckMalloc(numIndices * sizeof(glhckImportIndexData)))) goto assimp_no_memory; /* fill arrays */ joinMesh(mesh, 0, indices, vertexData, NULL, NULL); /* build model */ if (buildModel(current, numIndices, numVertices, indices, vertexData, itype, vtype) == RETURN_OK) { /* FIXME: UGLY */ char pointer[16]; snprintf(pointer, sizeof(pointer), "%p", mesh); _glhckObjectFile(current, pointer); if (material) glhckObjectMaterial(current, material); if (!(current = glhckObjectNew())) goto fail; glhckObjectAddChild(object, current); glhckObjectFree(current); canFreeCurrent = 1; } /* free stuff */ NULLDO(_glhckFree, vertexData); NULLDO(_glhckFree, indices); IFDO(glhckTextureFree, texture); IFDO(glhckMaterialFree, material); } } /* process childrens */ for (m = 0; m != nd->mNumChildren; ++m) { if (processModel(file, object, current, sc, nd->mChildren[m], itype, vtype, params) == RETURN_OK) { if (!(current = glhckObjectNew())) goto fail; glhckObjectAddChild(object, current); glhckObjectFree(current); canFreeCurrent = 1; } } /* we din't do anything to the next * allocated object, so free it */ if (canFreeCurrent) glhckObjectRemoveFromParent(current); return RETURN_OK; assimp_no_memory: DEBUG(GLHCK_DBG_ERROR, "Assimp not enough memory."); fail: IFDO(_glhckFree, vertexData); IFDO(_glhckFree, indices); IFDO(_glhckFree, textureList); IFDO(glhckTextureFree, texture); IFDO(glhckMaterialFree, material); IFDO(glhckAtlasFree, atlas); if (canFreeCurrent) glhckObjectRemoveFromParent(current); return RETURN_FAIL; }
/* \brief render scene */ GLHCKAPI void glhckRender(void) { unsigned int ti, oi, ts, os, tc, oc; char kt; glhckTexture *t; glhckObject *o; __GLHCKobjectQueue *objects; __GLHCKtextureQueue *textures; GLHCK_INITIALIZED(); TRACE(2); /* can't render */ if (!glhckInitialized() || !_glhckRenderInitialized()) return; objects = &GLHCKRD()->objects; textures = &GLHCKRD()->textures; /* store counts for enumeration, +1 for untexture objects */ tc = textures->count+1; oc = objects->count; /* nothing to draw */ if (!oc) return; /* draw in sorted texture order */ for (ti = 0, ts = 0; ti != tc; ++ti) { if (ti < tc-1) { if (!(t = textures->queue[ti])) continue; } else t = NULL; /* untextured object */ for (oi = 0, os = 0, kt = 0; oi != oc; ++oi) { if (!(o = objects->queue[oi])) continue; if (o->material) { /* don't draw if not same texture or opaque, * opaque objects are drawn last */ if (o->material->texture != t || (o->material->blenda != GLHCK_ZERO || o->material->blendb != GLHCK_ZERO)) { if (o->material->texture == t) kt = 1; /* don't remove texture from queue */ if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } } else if (t) { /* no material, but texture requested */ if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } /* render object */ glhckObjectRender(o); glhckObjectFree(o); /* referenced on draw call */ objects->queue[oi] = NULL; --objects->count; } /* check if we need texture again or not */ if (kt) { if (ts != ti) textures->queue[ti] = NULL; textures->queue[ts++] = t; } else { if (t) { glhckTextureFree(t); /* ref is increased on draw call! */ textures->queue[ti] = NULL; --textures->count; } } } /* store counts for enumeration, +1 for untextured objects */ tc = textures->count+1; oc = objects->count; /* FIXME: shift queue here */ if (oc) { } /* draw opaque objects next, * FIXME: this should not be done in texture order, * instead draw from farthest to nearest. (I hate opaque objects) */ for (ti = 0; ti != tc && oc; ++ti) { if (ti < tc-1) { if (!(t = textures->queue[ti])) continue; } else t = NULL; /* untextured object */ for (oi = 0, os = 0; oi != oc; ++oi) { if (!(o = objects->queue[oi])) continue; if (o->material) { /* don't draw if not same texture */ if (o->material->texture != t) { if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } } else if (t) { if (os != oi) objects->queue[oi] = NULL; objects->queue[os++] = o; continue; } /* render object */ glhckObjectRender(o); glhckObjectFree(o); /* referenced on draw call */ objects->queue[oi] = NULL; --objects->count; } /* this texture is done for */ if (t) { glhckTextureFree(t); /* ref is increased on draw call! */ textures->queue[ti] = NULL; --textures->count; } /* no texture, time to break */ if (!t) break; } /* FIXME: shift queue here if leftovers */ /* good we got no leftovers \o/ */ if (objects->count) { /* something was left un-drawn :o? */ for (oi = 0; oi != objects->count; ++oi) glhckObjectFree(objects->queue[oi]); memset(objects->queue, 0, objects->count * sizeof(glhckObject*)); objects->count = 0; } if (textures->count) { /* something was left un-drawn :o? */ DEBUG(GLHCK_DBG_CRAP, "COUNT UNLEFT %u", textures->count); for (ti = 0; ti != textures->count; ++ti) glhckTextureFree(textures->queue[ti]); memset(textures->queue, 0, textures->count * sizeof(glhckTexture*)); textures->count = 0; } }
Ship::~Ship() { glhckObjectFree(o); glhckObjectFree(shield); }
Shot::~Shot() { glhckObjectFree(o); }
Plasma::~Plasma() { glhckObjectFree(o); glhckObjectFree(oGlow); }