logo
Main

Forums

Downloads

Unreal-Netiquette

Donate for Oldunreal:
Donate

borderline

Links to our wiki:
Wiki

Walkthrough

Links

Tutorials

Unreal Reference

Usermaps

borderline

Contact us:
Submit News
Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic [WIP|Help] Wavefront to Unreal Mesh (except in C++) (Read 188 times)
Gustavo6046(BR)
New Member
*
Offline


Oldunreal member

Posts: 6
Joined: Sep 27th, 2016
Gender: Male
[WIP|Help] Wavefront to Unreal Mesh (except in C++)
Sep 27th, 2016 at 9:25pm
Print Post  
Hello all guys!

And yes, it seems this forums is just going to get way more active... I beter take care of how much I say regularly. Tongue

I am working in a converter from Wavefront .obj files into .3d files in C++ (since Python doesn't seems to work very well with Unreal's format using the byte manipulation at the vertex formula).

I've read very carefully Paul Borke's thing a million times, and this is probably the 093875825973825892385923975th try I do at such a converter! *breath* But since this is in C++ and it allows for better manipulation of bytes, it seems I'm closer at the point.

It is going nice. Right now it's crashing because of some weird problem converting some (rather usual) face into an Unreal Poly struct. But I managed to get pretty far, and it imports the .obj files (seemingly succesfully), one after another, each a frame! Grin

Also, it'll probably give me a distorted mesh once it... "works". >_<
Although I hope it doesn't!

I'll only post the source files if anyone asks for them, though. I still have a lot to do, for an upcoming UT gametype (which could be considered a new game in some ways); Sentient Mushes II!

Thanks for consideration.
  
Back to top
YouTube  
IP Logged
 
Kajgue
Global Moderator
Betatester
*****
Offline


Super-sexy-Kung-Fu-H
obo-sunva-bitch

Posts: 498
Location: Apophizal (T:S:B) Headquarters
Joined: Oct 17th, 2005
Gender: Male
Re: [WIP|Help] Wavefront to Unreal Mesh (except in C++)
Reply #1 - Sep 27th, 2016 at 9:33pm
Print Post  
I've made a few threads accross some forums like here and ut99.org about importing a skeletal animated mesh that has been exported as a .PSK/.PSA file from Blender 2.72.

A friend of mine tried to import the .psk/.psa file through the .UCC commandlet, although the end result just looked like a wedge/diamond looking thing instead of having any resemblance to the original model.

Might you also happen to have much knowledge about importing .psk/.psa files from Blender into Unreal successfully?

Thanks in advance!
  

AKA - ( T : S : B ) Ice-Lizard


Whistleblower Ted Gunderson
Back to top
IP Logged
 
Gustavo6046(BR)
New Member
*
Offline


Oldunreal member

Posts: 6
Joined: Sep 27th, 2016
Gender: Male
Re: [WIP|Help] Wavefront to Unreal Mesh (except in C++)
Reply #2 - Sep 27th, 2016 at 9:39pm
Print Post  
Kajgue wrote on Sep 27th, 2016 at 9:33pm:
I've made a few threads accross some forums like here and ut99.org about importing a skeletal animated mesh that has been exported as a .PSK/.PSA file from Blender 2.72.

A friend of mine tried to import the .psk/.psa file through the .UCC commandlet, although the end result just looked like a wedge/diamond looking thing instead of having any resemblance to the original model.

Might you also happen to have much knowledge about importing .psk/.psa files from Blender into Unreal successfully?

Thanks in advance!


Sorry, I never really tried to import PSK/PSA's from Blender's default exporter (specially since I know they're skeletal (not really the style I'm looking for) and probably for Unreal Engine 2!). I'd rather help Sad

But thanks for consideration!
  
Back to top
YouTube  
IP Logged
 
Kajgue
Global Moderator
Betatester
*****
Offline


Super-sexy-Kung-Fu-H
obo-sunva-bitch

Posts: 498
Location: Apophizal (T:S:B) Headquarters
Joined: Oct 17th, 2005
Gender: Male
Re: [WIP|Help] Wavefront to Unreal Mesh (except in C++)
Reply #3 - Sep 27th, 2016 at 9:42pm
Print Post  
As far as I know, .PSK/.PSA is compatible with Unreal 227 and UT, but ah.

Thanks anyway though Smiley
  

AKA - ( T : S : B ) Ice-Lizard


Whistleblower Ted Gunderson
Back to top
IP Logged
 
[]KAOS[]Casey
Developer Team
Betatester
Offline


nedm

Posts: 3188
Joined: Aug 7th, 2011
Gender: Male
Re: [WIP|Help] Wavefront to Unreal Mesh (except in C++)
Reply #4 - Sep 28th, 2016 at 7:52pm
Print Post  
Kajgue wrote on Sep 27th, 2016 at 9:42pm:
.PSK/.PSA is compatible with Unreal 227 and UT


yep
  
Back to top
 
IP Logged
 
Gustavo6046(BR)
New Member
*
Offline


Oldunreal member

Posts: 6
Joined: Sep 27th, 2016
Gender: Male
Re: [WIP|Help] Wavefront to Unreal Mesh (except in C++)
Reply #5 - Sep 28th, 2016 at 10:18pm
Print Post  
Ok so now I'm gonna post the source code for the sake of it!
main.cpp
Code
Select All
#include <iostream>
#include <vector>
#include <fstream>
#include <cstdlib>
#include <cstring>

#include "mesh.hpp"
#include "export.cpp"
#include "ssplit.cpp"

using std::cout;
using std::cin;
using std::vector;
using std::string;
using std::pair;
using std::ifstream;
using std::stringstream;
using std::strcmp;

struct stats
{
    unsigned int parsedlines;
    unsigned int parsedverts;
    unsigned int parseduvs;
    unsigned int parsedfaces;
    unsigned int totallines;
};

bool parseObjLine(string line, mesh* out, stats* out_stats)
{
    face newface;
    vector<double> curd;
    vector<string> pieces;
    string cur = "";

    // Split lines with space delimiter
    for ( unsigned int i = 0; i < line.size(); i++ )
    {
        if ( line[i] == ' ' )
        {
            pieces.push_back(cur);
            cur = "";
        }

        else
            cur += line[i];
    }

    if ( cur != "" )
        pieces.push_back(cur);

    // Check if vertex; if so, append to mesh vertex list
    if ( line.find("v ") == 0 )
    {
        if ( pieces.size() < 4 )
            return false;

        for ( unsigned int i = 0; i < 3; i++ )
            curd.push_back(strtod(pieces[i + 1].c_str(), 0));

        out->vertices.push_back(curd);

        out_stats->parsedverts++;
        return true;
    }

    // Check if texture UV vertex too
    else if ( line.find("vt") == 0 )
    {
        if ( pieces.size() < 3 )
            return false;

        for ( unsigned int i = 0; i < 2; i++ )
            curd.push_back(strtod(pieces[i + 1].c_str(), 0));

        out->uv.push_back(curd);

        out_stats->parseduvs++;
        return true;
    }

    //...and for faces
    else if ( line.find("f") == 0 )
    {
        if ( pieces.size() < 4 )
            return false;

        vector< vector<int> > indexes;
        vector<string> indexlist;
        string curr = "";

        for ( unsigned int i = 1; i < pieces.size(); i++ )
        {
            indexlist.clear();
            curr = "";

            for ( unsigned int j = 0; j < pieces[i].size(); j++ )
            {
                if ( pieces[i][j] == '/' )
                {
                    indexlist.push_back(curr);
                    curr = "";
                }

                else
                    curr += pieces[i][j];
            }

            if ( curr != "" )
            {
                indexlist.push_back(curr);
            }

            vector<int> new_index;

            new_index.push_back(atoi(indexlist[0].c_str()));
            new_index.push_back(atoi(indexlist[1].c_str()));

            indexes.push_back(new_index);
        }

        for ( int i = 0; i < 3; i++ )
        {
            newface.vertices[i] = indexes[i][0];
            newface.uv[i] = indexes[i][1];
        }

        out->faces.push_back(newface);

        out_stats->parsedfaces++;
        return true;
    }

    return false;
}

int main(int argc, char* argv[])
{
    anim animation;
    mesh model;
    stats statistic;

    // Title :3
    cerr << "===================================\nOBJ2UNR: Wavefront Converter for Unreal Engine 1\n\n   - by Gustavo6046 (Gustavo R. Rehermann)\n===================================\n\n";

    if ( argc < 4 )
    {
        if ( argc > 1 && strcmp(argv[1], "-txt") == 0 )
        {
            cerr << "The framelist (text file of any extension passed through stdin) must contain the relative or absolute path of each .obj file used as frames for the model.\ne.g.:\n\na.obj\nb.obj\nc.obj\n\nwould import three frames:\n\n1 -> a.obj\n2 -> b.obj\n3 -> c.obj\n\nin the order they have been put in the .txt project. You can use third-party tools to automate the task of creating the .txt file :^)\n     -Gustavo\n";

            return 0;
        }

        cerr << "Syntax: obj2unr *aniv name* *data name* *name of .txt file; see `obj2unr -txt` for more*\n";

        return 4;
    }

    string fnam;
    string line;

    ifstream otxt;
    otxt.open(argv[3]);
    std::getline(otxt, fnam);

    ifstream currfile;
    currfile.open(fnam.c_str());

    for (; std::getline(otxt, fnam) && currfile; )
    {
        // clean statistics
        statistic.parsedlines = 0;
        statistic.parsedverts = 0;
        statistic.parseduvs = 0;
        statistic.parsedfaces = 0;
        statistic.totallines = 0;

        // parse each of these FREAKING LINES
        for (; std::getline(currfile, line);  )
        {
            if ( parseObjLine(line, &model, &statistic) )
                statistic.parsedlines++;

            statistic.totallines++;
        }

        // add frame to animation
        animation.frames.push_back(model);

        if ( animation.frames.size() < 2 )
            animation.polys = model.faces;

        // log statistics
        cerr << "Imported model '" << fnam << "': Parsed " << statistic.totallines << " lines (" << statistic.totallines - statistic.parsedlines << " lines skipped), with " << statistic.parsedverts << " vertices, " << statistic.parseduvs << " UV coordinates and " << statistic.parsedfaces << " faces.\n";

        // open new file
        currfile.close();
        currfile.open(fnam.c_str());
    }

    currfile.close();

    if ( animation.frames.size() <= 0 )
    {
        cerr << "Error: Invalid model imported! (No imported frames detected!)";

        return 1;
    }

    if ( animation.polys.size() <= 0 )
    {
        cerr << "Error: Invalid model imported! (No polygons!)";

        return 2;
    }

    if ( animation.frames[0].vertices.size() <= 0 )
    {
        cerr << "Error: Invalid model imported! (No vertices in first frame!)";

        return 3;
    }

    for ( unsigned int i = 0; i < animation.polys.size(); i++ )
    {
        for ( unsigned int j = 0; j < 3; j++ )
            if ( animation.polys[i].vertices[j] > animation.frames[0].vertices.size() )
            {
                cerr << "Error: Invalid model imported! (Face's vertex index out of range!)";

                return 5;
            }

        for ( unsigned int j = 0; j < 2; j++ )
            if ( animation.polys[i].uv[j] > animation.frames[0].uv.size() )
            {
                cerr << "Error: Invalid model imported! (Face's UV index out of range!)";

                return 6;
            }
    }

    double real_scale;
    real_scale = 16;

    export_model(&animation, argv[1], argv[2], &real_scale);
    cerr << "Done converting model!";
}
 



mesh.cpp
Code
Select All
#ifndef MESH_HPP_INCLUDED
#define MESH_HPP_INCLUDED

#include <vector>
using std::vector;

struct face
{
    unsigned short uv[3];
    unsigned short vertices[3];
};

struct mesh
{
    vector<face> faces;
    vector< vector<double> > vertices;
    vector< vector<double> > uv;
};

struct anim
{
    vector<face> polys;
    vector<mesh> frames;
};

#endif // MESH_HPP_INCLUDED
 



umesh.cpp
Code
Select All
struct unrealpolyh
{
    unsigned short NumPolygons, NumVertices;
    static const unsigned short UnusedS[2];
    static const unsigned long UnusedL[7];
    static const unsigned char UnusedC[12];
};

struct unrealpoly
{
    unsigned short mVertex[3];
    static const char mType = 1;
    static const char mColor = 128;
    unsigned char mTex[3][2];
    static const char mTextureNum = 0;
    static const char mFlags = 0;
};
 



export.cpp
Code
Select All
#include "mesh.hpp"
#include "umesh.cpp"
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <cstring>

using std::cerr;
using std::ofstream;
using std::vector;
using std::stringstream;
using std::string;
using std::strcmp;

unsigned long unreal_vertex(double coord[3])
{
    unsigned long result;

    result =   ( int(coord[0] * 8.0) & 0x7ff ) |
            ( ( int(coord[1] * 8.0) & 0x7ff ) << 11 ) |
            ( ( int(coord[2] * 4.0) & 0x3ff ) << 22 );

    vector<void*> fmt;
    fmt.push_back(&coord[0]);
    fmt.push_back(&coord[1]);
    fmt.push_back(&coord[2]);
    fmt.push_back(&result);

    return result;
}

unrealpoly poly_from_face(face other, mesh* base)
{
    unrealpoly res;

    for ( unsigned int i = 0; i < 3; i++ )
        for ( unsigned int j = 0; j < 2; j++ )
            res.mTex[i][j] = base->uv[other.uv[i] - 1][j] * 255;

    for ( unsigned int i = 0; i < 3; i++ )
    {
        if ( other.vertices[i] - 1 >= 0 )
            res.mVertex[i] = other.vertices[i] - 1;

        else
            res.mVertex[i] = base->vertices.size() - other.vertices[i];
    }

    return res;
}

void export_model(anim* outmodel, char* aniv_name, char* data_name, double* oscale)
{
    double scale;

    if ( oscale == NULL )
        scale = 1;

    else
        scale = *oscale;

    cerr << "Writing data file...\n";
    // export data
    unrealpolyh header;

    header.NumPolygons = outmodel->polys.size();
    header.NumVertices = outmodel->frames[0].vertices.size();

    FILE *fdata;
    fdata = fopen(data_name, "wb");

    fwrite(&header, sizeof(unrealpolyh), 1, fdata);
    cerr << "Wrote data header!\n";

    unrealpoly poly;

    for ( unsigned int i = 0; i < outmodel->polys.size(); i++ )
    {
        poly = poly_from_face(outmodel->polys[i], &outmodel->frames[0]);

        fwrite(&poly, sizeof(unrealpoly), 1, fdata);
    }

    cerr << "Wrote data file!\n";

    fclose(fdata);

    // export anim (aniv)
    cerr << "Writing aniv file...\n";

    FILE *faniv;
    faniv = fopen(aniv_name, "wb");

    // -header...
    short numverts = outmodel->frames.size();
    fwrite(&numverts, sizeof(short), 1, faniv);

    short framesize = header.NumVertices * sizeof(unsigned long);
    fwrite(&framesize, sizeof(short), 1, faniv);

    cerr << "Wrote aniv header!\n";

    // -...and vertexes!
    mesh* frame;
    double coord[3];
    unsigned long uvert;

    for ( unsigned int i = 0; i < outmodel->frames.size(); i++ )
    {
        frame = &outmodel->frames[i];

        for ( unsigned int v = 0; v < frame->vertices.size(); v++ )
        {
            for ( unsigned int j = 0; j < 3; j++ )
                coord[j] = frame->vertices[v][j] * scale;

            uvert = unreal_vertex(coord);
            fwrite(&uvert, sizeof(unsigned long), 1, faniv);
        }
    }

    fclose(faniv);

    cerr << "Wrote aniv file! Wrote " << outmodel->frames.size() << " frames and " << frame->vertices.size() << " vertices.\n";
}
 



A lot of code isn't it! Tongue I'm not too good with C++...

EDIT: The full Code::Blocks project is obj2unr on GitHub. Grin
« Last Edit: Sep 29th, 2016 at 3:52pm by Gustavo6046(BR) »  
Back to top
YouTube  
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint
Bookmarks: del.icio.us Digg Facebook Google Google+ Linked in reddit StumbleUpon Twitter Yahoo