Using part of the engine source (MD2 and X model loader)

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Mills
Posts: 3
Joined: Sun Aug 09, 2015 12:42 pm

Using part of the engine source (MD2 and X model loader)

Post by Mills »

Hi.

I'm making my own little game for Play Station Portable, and i'd love to use the model loader source on it.

I got a copy of LTE engine for PSP, then i tried to understand the code and isolate the parts i want. But i'm not a very skilled C programmer, so the engine was too much for me.

All the nodes, scenes etc, are very confusing, so I'd like to "rip" just the code for .MD2 and/or .X loader, to use animated models in my game, without the rest of the engine.

To be more specific, i'll just use something like this pseudocode:
"LoadModel()"
"RenderModel(Frame_interval,speed)"

If somebody helps me i'd really apreciate it. Of course I'll credit the engine and people.

Thanks a lot.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Using part of the engine source (MD2 and X model loader)

Post by CuteAlien »

How will you do the animations then without the engine? Much of what the loader does is to create the animation data from file in the internal format needed by Irrlicht. Similar for material data, mesh-data and so on. If you don't use the engine then it doesn't really make much sense to use the loader.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Mills
Posts: 3
Joined: Sun Aug 09, 2015 12:42 pm

Re: Using part of the engine source (MD2 and X model loader)

Post by Mills »

CuteAlien wrote:How will you do the animations then without the engine? Much of what the loader does is to create the animation data from file in the internal format needed by Irrlicht. Similar for material data, mesh-data and so on. If you don't use the engine then it doesn't really make much sense to use the loader.
That's what i saw...
I found a md2 loader with all needed code in one file. But this code did not load the face normals, so the objects can't use lights.

This Irrlicht has all code in many different files, so i guess it is nearly impossible to use the object loader and renderer without all the engine... unless I could merge these two functions...

1 -MD2 loader from "resonate" a 2008 PSP homebrew Game, does not load object normals. But it works with just 3 or 4 more functions inside the same file (image load, animation...):

Code: Select all

 
struct AnimMesh *md2Load(const char *filename)
{
    struct AnimMesh *mesh=0;
    MD2Model m;
    memset(&m,0,sizeof(MD2Model));
    FILE *file=fopen(filename,"rb");
    
    if(!file) return 0;
 
    MD2Header header;
    fread(&header,sizeof(header),1,file);
    
    // Copy the header attributes.
    m.frameCount=header.numFrames;
    m.glcmdCount=header.numGlcmds;
    m.vertexCount=header.numVertices;
    m.skinCount=header.numSkins;
    m.texCoordCount=header.numSt;
    m.triangleCount=header.numTris;
    
    m.skinWidth=header.skinwidth;
    m.skinHeight=header.skinheight;
    
    fseek(file,header.offsetSkins,SEEK_SET);
    m.skins=(MD2Skin *)malloc(sizeof(MD2Skin)*header.numSkins);
    fread(m.skins,sizeof(MD2Skin),header.numSkins,file);
    
    fseek(file,header.offsetSt,SEEK_SET);
    m.texCoords=(MD2TexCoord *)malloc(sizeof(MD2TexCoord)*header.numSt);
    fread(m.texCoords,sizeof(MD2TexCoord),header.numSt,file);
    
    fseek(file,header.offsetTris,SEEK_SET);
    m.triangles=(MD2Triangle *)malloc(sizeof(MD2Triangle)*header.numTris);
    fread(m.triangles,sizeof(MD2Triangle),header.numTris,file);
    
    fseek(file,header.offsetFrames,SEEK_SET);
    m.frames=(MD2Frame *)malloc(sizeof(MD2Frame)*header.numFrames);
    int i;
    for(i=0;i<m.frameCount;i++) {
        fread(m.frames+i,sizeof(MD2Frame)-4,1,file);
        m.frames[i].verts=(MD2Vertex *)malloc(sizeof(MD2Vertex)*m.vertexCount);
        fread(m.frames[i].verts,sizeof(MD2Vertex),m.vertexCount,file);
    }
    
    fseek(file,header.offsetGlcmds,SEEK_SET);
    m.glcmds=(int *)malloc(sizeof(int)*header.numGlcmds);
    fread(m.glcmds,sizeof(int),header.numGlcmds,file);
    
    fclose(file);
    // Convert to AnimMesh format
    
    mesh=(struct AnimMesh *)malloc(sizeof(struct AnimMesh));
//  mesh->texture=loadCell(m.skins[0].name);
    mesh->texture=0;
    mesh->frameCount=m.frameCount;
    mesh->polyCount=m.triangleCount;
    mesh->skinWidth=m.skinWidth;
    mesh->skinHeight=m.skinHeight;
    mesh->frames=malloc(mesh->frameCount*sizeof(struct AnimFrame));
    for(i=0;i<mesh->frameCount;i++) {
        frameToAnimMesh(&m,mesh,i);
    }
    
    // Clean up
    if(m.skins) free(m.skins); m.skins=0;
    if(m.texCoords) free(m.texCoords); m.texCoords=0;
    if(m.triangles) free(m.triangles); m.triangles=0;
    for(i=0;i<m.frameCount;i++) {
        if(m.frames[i].verts) free(m.frames[i].verts);
    }
    if(m.frames) free(m.triangles); m.triangles=0;
    if(m.glcmds) free(m.glcmds); m.glcmds=0;
    
    return mesh;
}
 
2 -MD2 loader from LTE, a irrlight port for PSP, it loads object normals. But it needs the entire engine to be compiled :(:

Code: Select all

 
bool CAnimatedMeshMD2::loadFile(io::IReadFile* file)
{
    if (!file)
        return false;
 
    s8* frames = 0;
 
 
    file->read(&header, sizeof(SMD2Header));
 
#ifdef PPC
    printf("" "PPC è attivo\n");
    header.magic = OSReadSwapInt32(&header.magic,0);
    header.version = OSReadSwapInt32(&header.version,0);
    header.skinWidth = OSReadSwapInt32(&header.skinWidth,0);
    header.skinHeight = OSReadSwapInt32(&header.skinHeight,0);
    header.frameSize = OSReadSwapInt32(&header.frameSize,0);
    header.numSkins = OSReadSwapInt32(&header.numSkins,0);
    header.numVertices = OSReadSwapInt32(&header.numVertices,0);
    header.numTexcoords = OSReadSwapInt32(&header.numTexcoords,0);
    header.numTriangles = OSReadSwapInt32(&header.numTriangles,0);
    header.numGlCommands = OSReadSwapInt32(&header.numGlCommands,0);
    header.numFrames = OSReadSwapInt32(&header.numFrames,0);
    header.offsetSkins = OSReadSwapInt32(&header.offsetSkins,0);
    header.offsetTexcoords = OSReadSwapInt32(&header.offsetTexcoords,0);
    header.offsetTriangles = OSReadSwapInt32(&header.offsetTriangles,0);
    header.offsetFrames = OSReadSwapInt32(&header.offsetFrames,0);
    header.offsetGlCommands = OSReadSwapInt32(&header.offsetGlCommands,0);
    header.offsetEnd = OSReadSwapInt32(&header.offsetEnd,0);
#endif
 
 
    if (header.magic != MD2_MAGIC_NUMBER || header.version != MD2_VERSION)
    {
        os::Printer::log("MD2 Loader: Wrong file header", file->getFileName(), ELL_WARNING);
        return false;
    }
 
    // create Memory for indices and frames
 
 
    Indices.reallocate(header.numTriangles);
    //FrameList = new core::array<video::S3DVertex>[header.numFrames];
    FrameCount = header.numFrames;
 
    s32 i = 0;
 
    // read TextureCoords
 
    file->seek(header.offsetTexcoords, false);
    textureCoords = new SMD2TextureCoordinate[header.numTexcoords];
 
    if (!file->read(textureCoords, sizeof(SMD2TextureCoordinate)*header.numTexcoords))
    {
        os::Printer::log("MD2 Loader: Error reading TextureCoords.", file->getFileName(), ELL_ERROR);
        return false;
    }
 
    // read Triangles
 
    file->seek(header.offsetTriangles, false);
 
    triangles = new SMD2Triangle[header.numTriangles];
    if (!file->read(triangles, header.numTriangles *sizeof(SMD2Triangle)))
    {
        os::Printer::log("MD2 Loader: Error reading triangles.", file->getFileName(), ELL_ERROR);
        return false;
    }
 
 
    // read Vertices
 
    s8 buffer[MD2_MAX_VERTS*4+128];
    frame = (SMD2Frame*)buffer;
 
    vertices = new core::array< core::vector3df >[header.numFrames];
    normals = new core::array< core::vector3df >[header.numFrames];
 
    file->seek(header.offsetFrames, false);
 
    for (i = 0; i<header.numFrames; ++i)
    {
        // read vertices
 
        vertices[i].reallocate(header.numVertices);
        file->read(frame, header.frameSize);
 
        // store frame data
 
        SFrameData fdata;
        fdata.begin = i;
        fdata.end = i;
        fdata.fps = 7;
        if (frame->name[0])
        {
            for (s32 s = 0; frame->name[s]!=0 && (frame->name[s] < '0' ||
                                                  frame->name[s] > '9'); ++s)
                fdata.name += frame->name[s];
 
            if (!FrameData.empty() && FrameData[FrameData.size()-1].name == fdata.name)
                ++FrameData[FrameData.size()-1].end;
            else
                FrameData.push_back(fdata);
        }
 
        // add vertices
 
        for (s32 j=0; j<header.numVertices; ++j)
        {
            core::vector3df v;
            v.X = (f32)frame->vertices[j].vertex[0] * frame->scale[0] + frame->translate[0];
            v.Z = (f32)frame->vertices[j].vertex[1] * frame->scale[1] + frame->translate[1];
            v.Y = (f32)frame->vertices[j].vertex[2] * frame->scale[2] + frame->translate[2];
 
            vertices[i].push_back(v);
 
            s32 normalidx = frame->vertices[j].lightNormalIndex;
            if (normalidx > 0 && normalidx < Q2_VERTEX_NORMAL_TABLE_SIZE)
            {
                v.X = Q2_VERTEX_NORMAL_TABLE[normalidx][0];
                v.Y = Q2_VERTEX_NORMAL_TABLE[normalidx][1];
                v.Z = Q2_VERTEX_NORMAL_TABLE[normalidx][2];
            }
 
            normals[i].push_back(v);
        }
 
        // calculate bounding boxes
        if (header.numVertices)
        {
            core::aabbox3d<f32> box;
            box.reset(vertices[i][0]);
 
            for (s32 j=1; j<header.numVertices; ++j)
                box.addInternalPoint(vertices[i][j]);
 
            BoxList.push_back(box);
        }
 
    }
 
 
    // put triangles into frame list
 
    dmaxs = 1.0f/(header.skinWidth);
    dmaxt = 1.0f/(header.skinHeight);
 
 
    // create indices
 
    Indices.reallocate(header.numVertices);
    s32 count = header.numTriangles*3;
    for (s32 n=0; n<count; n+=3)
    {
        Indices.push_back(n);
        Indices.push_back(n+1);
        Indices.push_back(n+2);
    }
 
    //calculateNormals();
 
    video::S3DVertex vtx;
    vtx.Color = video::SColor(255,255,255,255);
    // reallocate interpolate buffer
    if (header.numFrames)
    {
        core::array<video::S3DVertex> p = getFrameList(0);
 
        InterpolateBuffer = new core::array<video::S3DVertex>;
        InterpolateBuffer->set_used(p.size());
        s32 count = p.size();
        for (i=0; i<count; ++i)
        {
            InterpolateBuffer->pointer()[i].TCoords = p.pointer()[i].TCoords;
            InterpolateBuffer->pointer()[i].Color = vtx.Color.toOpenGLColor();
        }
    }
 
 
    TriangleCount = Indices.size() / 3;
 
    // return
    calculateBoundingBox();
 
    return true;
}
 
Last edited by Mills on Sun Aug 09, 2015 9:30 pm, edited 1 time in total.
REDDemon
Developer
Posts: 1044
Joined: Tue Aug 31, 2010 8:06 pm
Location: Genova (Italy)

Re: Using part of the engine source (MD2 and X model loader)

Post by REDDemon »

You can compute normals yourself
Junior Irrlicht Developer.
Real value in social networks is not about "increasing" number of followers, but about getting in touch with Amazing people.
- by Me
Mills
Posts: 3
Joined: Sun Aug 09, 2015 12:42 pm

Re: Using part of the engine source (MD2 and X model loader)

Post by Mills »

Hi again, MD2 models did not work well on PSP... so now i'm foccused on .X models

I just want to know, where is the source with the function to load animated models in .X format?

Thanks again.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Using part of the engine source (MD2 and X model loader)

Post by CuteAlien »

The source is in CXMeshFileLoader.cpp/.h
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply