#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <iterator>
#include <cstring>
using namespace std;
char *CHAR;
string Input;
string Output;
///We already know what this does.
string fn_DecToHex (unsigned int value) {
char conHex[256];
int rawDec = value; //this is variable
sprintf(conHex,"%x",rawDec);
return conHex;
}
int fn_HexToDec (char rawHex[]) {
int conDec;
sscanf(rawHex, "%x", &conDec);
return conDec;
}
string fn_IntToString(int intValue) {
char *myBuff;
string strRetVal;
myBuff = new char[100];
memset(myBuff,'\0',100);
itoa(intValue,myBuff,10);
strRetVal = myBuff;
delete[] myBuff;
return(strRetVal);
}
int fn_StringToInt(string strConvert) {
int intReturn;
intReturn = atoi(strConvert.c_str());
return(intReturn);
}
void fn_StringToChar(string STR) {
int TempNumOne=STR.size();
for (int a=0;a<=TempNumOne;a++)
{
CHAR[a]=STR[a];
}
}
int main() {
///Same as before.
string line;///Makes a new variable called 'line', the 'line' in this case being the entire hex contained copy-pasted within the .txt, so it's large.
cout << "Opening files." << endl;///This just shows text in command prompt, and makes a new line.
cout << "Input file: ";
cin >> Input;///This asks for the complete filename.
cout << endl;///New line.
ifstream myfile (Input.c_str());///Makes a filename out of 'Input'.
cout << "Output file: ";
cin >> Output;
cout << endl;
ofstream outfile (Output.c_str()); ///Makes a filename out of 'Output'.
cout << "Writing vertice data to file." << endl;
if (myfile.is_open() && outfile.is_open())
{
while (! myfile.eof() )
{
///Same variables.
getline (myfile,line);
CHAR = new char[100];
unsigned int Offset = 0;
unsigned int MaxOffset = line.length();
string HexA;
string HexB;
///Ok, here we go.
unsigned int Face1;///Stores the vertice number for first triangle point.
unsigned int Face2;///Stores the vertice number for second triangle point.
unsigned int Face3;///Stores the vertice number for third triangle point.
unsigned int Face4;///Stores the vertice number in-case of a quadratic.
unsigned int Duration;///Stores the Datablock size.
//0xB8 // points
//0xA8 // lines
//0xB0 // line strip
//0x90 // triangles
//0x98 // triangle strip
//0xA0 // triangle fan
//0x80 // quads
///Just all the different faces.
string LineNor = "A8 0";
string LineStrip = "B0 0";
string TriStrip = "98 0";
string TriNor = "90 0";
string TriFan = "A0 0";
string Quad = "80 0";
///////////////////////
string LengthA;
int LengthB;
///This aids in the search through the string.
size_t found;
///These values are mainly for debugging; they basically show where the nearest face value is on every step.
int TriStripFound;
int TriNorFound;
int QuadFound;
///The offset for the line after all equations are performed.
int FinalOffset = 0;
string Type = "";
///Length is back///
unsigned int Length;
/////////////////////////////////
unsigned int FileOffset;
///Loop.
FindLength:
///These are for debugging. The '999' prevents the search from skipping over a particular header.
Duration = 0;
TriStripFound = 999;
TriNorFound = 999;
QuadFound = 999;
///Convert the first 9 characters ('98 00 23 ' for example) to characters.
fn_StringToChar(line.substr(FinalOffset,9));
///Used for debugging. Basically, it prints the above string, so I can look for a flaw in my code if it isn't '98', '80' etc.
//cout << "Last Offset words: " << CHAR << endl;
///Get's rid of everything we were working on before we looped (later), leaving the start of the file to be '98 00 23 '.
///This prevents overly large offset numbers.
line.erase(0,FinalOffset);
///Look for the first occurence of a Triangle Strip, over 36 characters (12 lots of hex).
found = line.find(TriStrip,36);
//cout << "\n" << "TriStrip found at: " << found << endl;///Debug; Show me where you found it. It worked if it is 36 (or 0, only at the start of the process).
if (found!=string::npos)///If you actually found it at all...
{
if (int(found) == 36 || int(found) == 0)///If it's the right values.
{
TriStripFound = int(found);///Make this equal where you found it.
}
else
{
///Now, when changing headers, theres usually an intermission of '00' before. So the Triangle Strip would not be at position 36 anymore.
///This solves that problem (although, not too well).
found = line.find("00 00 00 00 00 " + TriStrip,0);
if (found!=string::npos)
{
TriStripFound = int(found)+15;///It adds 15, because of the '00's.
}
}
}
///Now do the same for other face types.
found = line.find(TriNor,36);
//cout << "TriNor found at: " << found << endl;
if (found!=string::npos)
{
if (int(found) == 36 || int(found) == 0)
{
TriNorFound = int(found);
}
else
{
found = line.find("00 00 00 00 00 " + TriNor,0);
if (found!=string::npos)
{
TriNorFound = int(found)+15;
}
}
}
///And again.
found = line.find(Quad,36);
//cout << "Quad found at: " << found << endl;
if (found!=string::npos)
{
if (int(found) == 36 || int(found) == 0)
{
QuadFound = int(found);
}
else
{
found = line.find("00 00 00 00 00 " + Quad,0);
if (found!=string::npos)
{
QuadFound = int(found)+15;
}
}
}
if (line.find(TriNor,36) == line.find(Quad,36) && line.find(TriNor,36) == line.find(TriStrip,36))
{
goto Done;///THIS CONPARRISSON MIGHT NOT WORK ALL THE TIME! I DOUBT IT DOES, BECAUSE, WHAT IF IT FINDS ONE LEGIT, BUT CAN'T FIND TWO? MAYBE COMPARE ALL 3?
}
//////////////////
/// DEBUG ZONE ///
//////////////////
/*
cout << "TriFan found at: " << line.find(TriFan,0) << endl;
cout << "LineNor found at: " << line.find(LineNor,0) << endl;
cout << "LineStrip found at: " << line.find(LineStrip,0) << endl;
*/
//////////////////////////////
/// NOW LEAVING DEBUG ZONE ///
//////////////////////////////
///If TriNor (Triangles; '90') is at the location 36 (remember, all others have been set to '999')
if (TriNorFound < TriStripFound)
{
if (TriNorFound < QuadFound)
{
///Go to its offset.
FinalOffset = TriNorFound;
///Now we know what type to convert.
Type = "Nor";
///Go to the convertion.
goto NoConvert;
}
}
///Again.
if (TriStripFound < TriNorFound)
{
//cout << "TriStripFound: " << TriStripFound << endl;
if (TriStripFound < QuadFound)
{
FinalOffset = TriStripFound;
Type = "Strip";
goto NoConvert;
}
}
///Again.
if (QuadFound < TriNorFound)
{
//cout << "QuadFound: " << QuadFound << endl;
if (QuadFound < TriStripFound)
{
FinalOffset = QuadFound;
Type = "Quad";
goto NoConvert;
}
}
///Now we convert.
NoConvert:
///Debug.
//cout << "FinalOffset of type: " << FinalOffset << endl;
//cout << "Type: " << Type << endl;
///This looks familiar. Remember, since 'FinalOffset' is still placed before '98 00 23 ', we need to add values.
///In this case, we're getting '00' as a value.
fn_StringToChar(line.substr(FinalOffset+3,2));
LengthA = CHAR;
///Now LengthA == '00'.
///Now we get '23'
fn_StringToChar(line.substr(FinalOffset+6,2));
///And add to it, so we get '0023'///
///I do this because space (' ') won't get read.
LengthA += CHAR;
///And finally, Length == decimal value of '0023'.
fn_StringToChar(LengthA);
Length = fn_HexToDec(CHAR);
///More debug.
fn_StringToChar(line.substr(FinalOffset,9));
//cout << "Now converting from offset: " << CHAR << endl;
//cout << "The length is: " << Length << endl << endl;
///Like Amy once said, 'just wait a minute'.
///YOU WOULD SERIOUSLY NEED TO CONCIDER REMOVING THIS, OR IT WILL PAUSE AFTER EVERY HEADER.
//system ("pause");
///Add 9, so we go past '98 00 23 ', and reach the first value after. Let's say it's '03 15 '
FinalOffset += 9;
///Now we convert for real.
ConvertFace:
///Convert the '03'.
fn_StringToChar(line.substr(FinalOffset,2));
HexA = CHAR;
///Convert the '15'.
fn_StringToChar(line.substr(FinalOffset+3,2));
HexB = CHAR;
///Our powers combined, we are '0315'.
HexA += HexB;
fn_StringToChar(HexA);
///Now Face1 is the decimal value of that.
Face1 = fn_HexToDec(CHAR);
///We add 1, because '00' counts, yes theres no such thing as the 0th vertice.
Face1++;
///Add to the amount of times we've converted a face.
Duration++;
///And again.
fn_StringToChar(line.substr(FinalOffset+18,2));
HexA = CHAR;
fn_StringToChar(line.substr(FinalOffset+21,2));
HexB = CHAR;
HexA += HexB;
fn_StringToChar(HexA);
Face2 = fn_HexToDec(CHAR);
Face2++;
///And again.
fn_StringToChar(line.substr(FinalOffset+36,2));
HexA = CHAR;
fn_StringToChar(line.substr(FinalOffset+39,2));
HexB = CHAR;
HexA += HexB;
fn_StringToChar(HexA);
Face3 = fn_HexToDec(CHAR);
Face3++;
///And once more, incase we have a Quad.
fn_StringToChar(line.substr(FinalOffset+54,2));
HexA = CHAR;
fn_StringToChar(line.substr(FinalOffset+57,2));
HexB = CHAR;
HexA += HexB;
fn_StringToChar(HexA);
Face4 = fn_HexToDec(CHAR);
Face4++;
///If we're not using a Quad.
///Also checks if we have double values anywhere.
if (Type != "Quad"){
if (Face1 == Face2 || Face1 == Face3 || Face2 == Face3){
if (Face1 == Face2){Face2 = Face4;}
if (Face1 == Face3){Face3 = Face4;}
if (Face2 == Face3){Face3 = Face4;}}
}
///Go forward 6 hex spaces ('XX XX XX XX XX XX ').
FinalOffset += 18;
///Depending on what type, we need to add more than that.
if (Type == "Nor"){
FinalOffset += 36;
Duration += 2;}
if (Type == "Quad"){
FinalOffset += 54;
Duration += 3;}
///Check for duplicate values. It writes 'ERROR!!!' if we do... This rfeally shows how much faith I have in this code.
if (Type != "Quad")
{
if (Face1 == Face2 || Face1 == Face3 || Face2 == Face3)
{
outfile << "f " << Face1 << " " << Face2 << " " << Face3 << " ERROR!!!" << endl;
//cout << "f " << Face1 << " " << Face2 << " " << Face3 << " ERROR!!!" << endl;
}
else
{///And if we don't have duplicates, don't worry, be happy.
outfile << "f " << Face1 << " " << Face2 << " " << Face3 << endl;
//cout << "f " << Face1 << " " << Face2 << " " << Face3 << endl;
}
}
else
{///Quads get special treatment, due to the extra point.
outfile << "f " << Face1 << " " << Face2 << " " << Face3 << " " << Face4 << endl;
//cout << "f " << Face1 << " " << Face2 << " " << Face3 << " " << Face4 << endl;
}
///NOW, THIS PART IS VERY IMPORTANT!
///See how it checks for that particular value?
///That is the way I check to see if we reached the end of the file.
///What I do is, at the end of the text in the .txt, I type a heap of 'CC CC CC CC CC CC CC CC '
///52429 happens to be what you'de get if you converted 'CC CC' to decimal and added 1.
///So it checks if we haven't reached the end of the file.
if (Face1 != 52429)
{
if (Type != "Quad")///If we're not Quad's.
{
if (Length-3 >= Duration)///If we haven't reached the end of the length the header specified.
{
goto ConvertFace;///Go back and convert again.
}
else
{///But if we have.
if (Type == "Nor")
{
FinalOffset -= 36;///This fixes the offset, because '90' triangles are a bit weird for me.
}
goto FindLength;///Look for another header.
}
}
else
{///If we are using Quad's.
if (Length-4 >= Duration)///Etc.
{
goto ConvertFace;
}
else
{
FinalOffset -= 36;
goto FindLength;
}
}
}
else
{
Done:
///If we are done, then tell me.
cout << endl << "Done!" << endl << endl;
}
}
myfile.close();
outfile.close();
}
else cout << "Unable to open file";
system ("pause");
return 0;
}