Пример #1
0
/* \brief destroys the current glhck context */
GLHCKAPI void glhckContextTerminate(void)
{
   if (!glhckInitialized()) return;
   TRACE(0);

   /* destroy queues */
   _glhckFree(GLHCKRD()->objects.queue);
   _glhckFree(GLHCKRD()->textures.queue);

   /* destroy world */
   glhckMassacreWorld();

   /* terminate internal vertex/index types */
   _glhckGeometryTerminate();

   /* close display */
   glhckDisplayClose();

   /* terminate allocation tracking */
#ifndef NDEBUG
   puts("\nExit graph, this should be empty.");
   glhckMemoryGraph();
   _glhckTrackTerminate();
#endif

#if !GLHCK_DISABLE_TRACE
   /* terminate trace system */
   _glhckTraceTerminate();
#endif

   /* finally remove the context */
   free(_glhckContext);
   glhckContextSet(NULL);
}
Пример #2
0
static int processBonesAndAnimations(glhckObject *object, const struct aiScene *sc)
{
    unsigned int i, b,  numBones = 0, oldNumBones;
    const struct aiMesh *mesh;
    glhckObject *child;
    glhckBone **bones = NULL;
    glhckSkinBone **skinBones = NULL;

    /* import bones */
    if (!(bones = _glhckCalloc(ASSIMP_BONES_MAX, sizeof(glhckBone*))))
        goto fail;
    if (!(skinBones = _glhckCalloc(ASSIMP_BONES_MAX, sizeof(glhckSkinBone*))))
        goto fail;

    for (i = 0; i != sc->mNumMeshes; ++i) {
        mesh = sc->mMeshes[i];

        /* FIXME: UGLY */
        char pointer[16];
        snprintf(pointer, sizeof(pointer), "%p", mesh);
        if (!(child = findObject(object, pointer))) continue;

        if (mesh->mNumBones)  {
            oldNumBones = numBones;
            processBones(sc->mRootNode, sc->mRootNode, mesh, bones, skinBones, &numBones);
            if (numBones) glhckObjectInsertSkinBones(child, skinBones+oldNumBones, numBones-oldNumBones);
            for (b = oldNumBones; b < numBones; ++b) glhckSkinBoneFree(skinBones[b]);
        }
    }

    /* we don't need skin bones anymore */
    NULLDO(_glhckFree, skinBones);

    /* store all bones in root object */
    if (numBones) glhckObjectInsertBones(object, bones, numBones);
    for (b = 0; b < numBones; ++b) glhckBoneFree(bones[b]);
    NULLDO(_glhckFree, bones);

    /* import animations */
    if (sc->mNumAnimations && processAnimations(object, sc) != RETURN_OK)
        goto fail;

    return RETURN_OK;

fail:
    if (bones) {
        for (i = 0; i < ASSIMP_BONES_MAX; ++i)
            if (bones[i]) glhckBoneFree(bones[i]);
        _glhckFree(bones);
    }
    if (skinBones) {
        for (i = 0; i < ASSIMP_BONES_MAX; ++i)
            if (skinBones[i]) glhckSkinBoneFree(skinBones[i]);
        _glhckFree(skinBones);
    }
    return RETURN_FAIL;
}
Пример #3
0
/* \brief helper function for importers.
 * helps finding texture files.
 * maybe we could have a _default_ texture for missing files? */
char* _glhckImportTexturePath(const char* odd_texture_path, const char* model_path)
{
   char *textureFile, *modelFolder, *modelPath;
   char textureInModelFolder[2048];
   CALL(0, "%s, %s", odd_texture_path, model_path);

   /* these are must to check */
   if (!odd_texture_path || !odd_texture_path[0])
      goto fail;

   /* lets try first if it contains real path to the texture */
   textureFile = (char*)odd_texture_path;

   /* guess not, lets try basename it */
   if (access(textureFile, F_OK) != 0)
      textureFile = gnu_basename((char*)odd_texture_path);
   else {
      RET(0, "%s", textureFile);
      return _glhckStrdup(textureFile);
   }

   /* hrmm, we could not even basename it?
    * I think we have a invalid path here Watson! */
   if (!textureFile)
      goto fail; /* Sherlock, you are a genius */

   /* these are must to check */
   if (!model_path || !model_path[0])
      goto fail;

   /* copy original path */
   if (!(modelPath = _glhckStrdup(model_path)))
      goto fail;

   /* grab the folder where model resides */
   modelFolder = dirname(modelPath);

   /* ok, maybe the texture is in same folder as the model? */
   snprintf(textureInModelFolder, sizeof(textureInModelFolder)-1, "%s/%s", modelFolder, textureFile);

   /* free this */
   _glhckFree(modelPath);

   /* gah, don't give me missing textures damnit!! */
   if (access(textureInModelFolder, F_OK) != 0)
      goto fail;

   /* return, remember to free */
   RET(0, "%s", textureInModelFolder);
   return _glhckStrdup(textureInModelFolder);

fail:
   RET(0, "%p", NULL);
   return NULL;
}
Пример #4
0
static void _glhckTriStripReverse(glhckImportIndexData *indices, unsigned int memb)
{
   unsigned int i;
   glhckImportIndexData *original;

   if (!(original = _glhckCopy(indices, memb * sizeof(glhckImportIndexData))))
      return;

   for (i = 0; i != memb; ++i)
      indices[i] = original[memb-1-i];

   _glhckFree(original);
}
Пример #5
0
glhckTexture* textureFromMaterial(const char *file, const struct aiMaterial *mtl)
{
    glhckTexture *texture;
    struct aiString textureName;
    enum aiTextureMapping textureMapping;
    enum aiTextureOp op;
    enum aiTextureMapMode textureMapMode[3] = {0,0,0};
    unsigned int uvwIndex, flags;
    float blend;
    char *texturePath;
    glhckTextureParameters params;
    assert(file && mtl);

    if (!aiGetMaterialTextureCount(mtl, aiTextureType_DIFFUSE))
        return NULL;

    if (aiGetMaterialTexture(mtl, aiTextureType_DIFFUSE, 0,
                             &textureName, &textureMapping, &uvwIndex, &blend, &op,
                             textureMapMode, &flags) != AI_SUCCESS)
        return NULL;

    memcpy(&params, glhckTextureDefaultParameters(), sizeof(glhckTextureParameters));
    switch (textureMapMode[0]) {
    case aiTextureMapMode_Clamp:
    case aiTextureMapMode_Decal:
        params.wrapR = GLHCK_WRAP_CLAMP_TO_EDGE;
        params.wrapS = GLHCK_WRAP_CLAMP_TO_EDGE;
        params.wrapT = GLHCK_WRAP_CLAMP_TO_EDGE;
        break;
    case aiTextureMapMode_Mirror:
        params.wrapR = GLHCK_WRAP_MIRRORED_REPEAT;
        params.wrapS = GLHCK_WRAP_MIRRORED_REPEAT;
        params.wrapT = GLHCK_WRAP_MIRRORED_REPEAT;
        break;
    default:
        break;
    }

    if (!(texturePath = _glhckImportTexturePath(textureName.data, file)))
        return NULL;

    DEBUG(0, "%s", texturePath);
    texture = glhckTextureNewFromFile(texturePath, NULL, &params);
    _glhckFree(texturePath);
    return texture;
}
Пример #6
0
/* \brief import MikuMikuDance PMD file */
int _glhckImportPMD(_glhckObject *object, const char *file, const glhckImportModelParameters *params,
      glhckGeometryIndexType itype, glhckGeometryVertexType vtype)
{
   FILE *f;
   char *texturePath;
   mmd_data *mmd = NULL;
   glhckAtlas *atlas = NULL;
   glhckMaterial *material = NULL;
   glhckTexture *texture = NULL, **textureList = NULL;
   glhckImportVertexData *vertexData = NULL;
   glhckImportIndexData *indices = NULL, *stripIndices = NULL;
   unsigned int geometryType = GLHCK_TRIANGLE_STRIP;
   unsigned int i, i2, ix, start, numFaces, numIndices = 0;
   CALL(0, "%p, %s, %p", object, file, params);

   if (!(f = fopen(file, "rb")))
      goto read_fail;

   if (!(mmd = mmd_new(f)))
      goto mmd_no_memory;

   if (mmd_read_header(mmd) != 0)
      goto mmd_import_fail;

   if (mmd_read_vertex_data(mmd) != 0)
      goto mmd_import_fail;

   if (mmd_read_index_data(mmd) != 0)
      goto mmd_import_fail;

   if (mmd_read_material_data(mmd) != 0)
      goto mmd_import_fail;

   /* close file */
   NULLDO(fclose, f);

   if (mmd->header.name) {
      DEBUG(GLHCK_DBG_CRAP, "%s\n", mmd->header.name);
   }
   if (mmd->header.comment) printf("%s\n\n", mmd->header.comment);

   if (!(vertexData = _glhckCalloc(mmd->num_vertices, sizeof(glhckImportVertexData))))
      goto mmd_no_memory;

   if (!(indices = _glhckMalloc(mmd->num_indices * sizeof(unsigned int))))
      goto mmd_no_memory;

   if (!(textureList = _glhckCalloc(mmd->num_materials, sizeof(_glhckTexture*))))
      goto mmd_no_memory;

   if (!(atlas = glhckAtlasNew()))
      goto mmd_no_memory;

   /* add all textures to atlas packer */
   for (i = 0; i < mmd->num_materials; ++i) {
      if (!mmd->materials[i].texture) continue;

      if (!(texturePath = _glhckImportTexturePath(mmd->materials[i].texture, file)))
         continue;

      if ((texture = glhckTextureNewFromFile(texturePath, NULL, NULL))) {
         glhckAtlasInsertTexture(atlas, texture);
         glhckTextureFree(texture);
         textureList[i] = texture;
      }

      _glhckFree(texturePath);
   }

   for (i = 0; i < mmd->num_materials && !textureList[i]; ++i);
   if (i >= mmd->num_materials) {
      /* no textures found */
      NULLDO(glhckAtlasFree, atlas);
      NULLDO(_glhckFree, textureList);
   } else {
      /* pack textures */
      if (glhckAtlasPack(atlas, GLHCK_RGBA, 1, 0, glhckTextureDefaultParameters()) != RETURN_OK)
         goto fail;
   }

   /* assign data */
   for (i = 0, start = 0; i < mmd->num_materials; ++i, start += numFaces) {
      numFaces = mmd->materials[i].face;
      for (i2 = start; i2 < start + numFaces; ++i2) {
         ix = mmd->indices[i2];

         /* vertices */
         vertexData[ix].vertex.x = mmd->vertices[ix*3+0];
         vertexData[ix].vertex.y = mmd->vertices[ix*3+1];
         vertexData[ix].vertex.z = mmd->vertices[ix*3+2];

         /* normals */
         vertexData[ix].normal.x = mmd->normals[ix*3+0];
         vertexData[ix].normal.y = mmd->normals[ix*3+1];
         vertexData[ix].normal.z = mmd->normals[ix*3+2];

         /* texture coords */
         vertexData[ix].coord.x = mmd->coords[ix*2+0];
         vertexData[ix].coord.y = mmd->coords[ix*2+1] * -1;

         /* fix coords */
         if (vertexData[ix].coord.x < 0.0f)
            vertexData[ix].coord.x += 1.0f;
         if (vertexData[ix].coord.y < 0.0f)
            vertexData[ix].coord.y += 1.0f;

         /* if there is packed texture */
         if (atlas && textureList[i]) {
            kmVec2 coord;
            coord.x = vertexData[ix].coord.x;
            coord.y = vertexData[ix].coord.y;
            glhckAtlasTransformCoordinates(atlas, textureList[i], &coord, &coord);
            vertexData[ix].coord.x = coord.x;
            vertexData[ix].coord.y = coord.y;
         }

         indices[i2] = ix;
      }
   }

   if (atlas) {
      if (!(material = glhckMaterialNew(glhckAtlasGetTexture(atlas))))
         goto mmd_no_memory;

      glhckObjectMaterial(object, material);
      NULLDO(glhckMaterialFree, material);
      NULLDO(glhckAtlasFree, atlas);
      NULLDO(_glhckFree, textureList);
   }

   /* triangle strip geometry */
   if (!(stripIndices = _glhckTriStrip(indices, mmd->num_indices, &numIndices))) {
      /* failed, use non stripped geometry */
      geometryType   = GLHCK_TRIANGLES;
      numIndices    = mmd->num_indices;
      stripIndices  = indices;
   } else NULLDO(_glhckFree, indices);

   /* set geometry */
   glhckObjectInsertIndices(object, itype, stripIndices, numIndices);
   glhckObjectInsertVertices(object, vtype, vertexData, mmd->num_vertices);
   object->geometry->type = geometryType;

   /* finish */
   NULLDO(_glhckFree, vertexData);
   NULLDO(_glhckFree, stripIndices);
   NULLDO(mmd_free, mmd);

   RET(0, "%d", RETURN_OK);
   return RETURN_OK;

read_fail:
   DEBUG(GLHCK_DBG_ERROR, "Failed to open: %s", file);
   goto fail;
mmd_import_fail:
   DEBUG(GLHCK_DBG_ERROR, "MMD importing failed.");
   goto fail;
mmd_no_memory:
   DEBUG(GLHCK_DBG_ERROR, "MMD not enough memory.");
fail:
   IFDO(fclose, f);
   IFDO(glhckAtlasFree, atlas);
   IFDO(mmd_free, mmd);
   IFDO(_glhckFree, textureList);
   IFDO(_glhckFree, vertexData);
   IFDO(_glhckFree, indices);
   IFDO(_glhckFree, stripIndices);
   RET(0, "%d", RETURN_FAIL);
   return RETURN_FAIL;
}
Пример #7
0
static int processAnimations(glhckObject *object, const struct aiScene *sc)
{
    glhckAnimationVectorKey *vectorKeys;
    glhckAnimationQuaternionKey *quaternionKeys;
    unsigned int i, n, k, numAnimations, numNodes;
    glhckAnimation *animation;
    glhckAnimationNode *node;
    const struct aiNodeAnim *assimpNode;
    const struct aiAnimation *assimpAnimation;

    glhckAnimation *animations[sc->mNumAnimations];
    for (i = 0, numAnimations = 0; i != sc->mNumAnimations; ++i) {
        assimpAnimation = sc->mAnimations[i];

        /* allocate new animation */
        if (!(animation = glhckAnimationNew()))
            continue;

        /* set animation properties */
        glhckAnimationTicksPerSecond(animation, assimpAnimation->mTicksPerSecond);
        glhckAnimationDuration(animation, assimpAnimation->mDuration);
        glhckAnimationName(animation, assimpAnimation->mName.data);

        glhckAnimationNode *nodes[assimpAnimation->mNumChannels];
        for (n = 0, numNodes = 0; n != assimpAnimation->mNumChannels; ++n) {
            assimpNode = assimpAnimation->mChannels[n];

            /* allocate new animation node */
            if (!(node = glhckAnimationNodeNew()))
                continue;

            /* set bone name for this node */
            glhckAnimationNodeBoneName(node, assimpNode->mNodeName.data);

            /* translation keys */
            vectorKeys = _glhckCalloc(assimpNode->mNumPositionKeys, sizeof(glhckAnimationVectorKey));
            if (!vectorKeys) continue;

            for (k = 0; k != assimpNode->mNumPositionKeys; ++k) {
                vectorKeys[k].vector.x = assimpNode->mPositionKeys[k].mValue.x;
                vectorKeys[k].vector.y = assimpNode->mPositionKeys[k].mValue.y;
                vectorKeys[k].vector.z = assimpNode->mPositionKeys[k].mValue.z;
                vectorKeys[k].time = assimpNode->mPositionKeys[k].mTime;
            }
            glhckAnimationNodeInsertTranslations(node, vectorKeys, assimpNode->mNumPositionKeys);
            _glhckFree(vectorKeys);

            /* scaling keys */
            vectorKeys = _glhckCalloc(assimpNode->mNumScalingKeys, sizeof(glhckAnimationVectorKey));
            if (!vectorKeys) continue;

            for (k = 0; k != assimpNode->mNumScalingKeys; ++k) {
                vectorKeys[k].vector.x = assimpNode->mScalingKeys[k].mValue.x;
                vectorKeys[k].vector.y = assimpNode->mScalingKeys[k].mValue.y;
                vectorKeys[k].vector.z = assimpNode->mScalingKeys[k].mValue.z;
                vectorKeys[k].time = assimpNode->mScalingKeys[k].mTime;
            }
            glhckAnimationNodeInsertScalings(node, vectorKeys, assimpNode->mNumScalingKeys);
            _glhckFree(vectorKeys);

            /* rotation keys */
            quaternionKeys = _glhckCalloc(assimpNode->mNumRotationKeys, sizeof(glhckAnimationQuaternionKey));
            if (!quaternionKeys) continue;

            for (k = 0; k != assimpNode->mNumRotationKeys; ++k) {
                quaternionKeys[k].quaternion.x = assimpNode->mRotationKeys[k].mValue.x;
                quaternionKeys[k].quaternion.y = assimpNode->mRotationKeys[k].mValue.y;
                quaternionKeys[k].quaternion.z = assimpNode->mRotationKeys[k].mValue.z;
                quaternionKeys[k].quaternion.w = assimpNode->mRotationKeys[k].mValue.w;
                quaternionKeys[k].time = assimpNode->mRotationKeys[k].mTime;
            }
            glhckAnimationNodeInsertRotations(node, quaternionKeys, assimpNode->mNumRotationKeys);
            _glhckFree(quaternionKeys);

            /* increase imported nodes count */
            nodes[numNodes++] = node;
        }

        /* set nodes to animation */
        if (numNodes) {
            glhckAnimationInsertNodes(animation, nodes, numNodes);
            for (n = 0; n != numNodes; ++n) glhckAnimationNodeFree(nodes[n]);
        }

        /* increase imported animations count */
        animations[numAnimations++] = animation;
    }

    /* insert animations to object */
    if (numAnimations) {
        glhckObjectInsertAnimations(object, animations, numAnimations);
#if 0
        unsigned int numChildren;
        glhckObject **children;
        children = glhckObjectChildren(object, &numChildren);
        for (i = 0; i != numChildren; ++i) glhckObjectInsertAnimations(children[i], animations, numAnimations);
#endif
        for (i = 0; i != numAnimations; ++i) glhckAnimationFree(animations[i]);
    }
    return RETURN_OK;
}