The online racing simulator
Question about the SMX file
(11 posts, started )
Question about the SMX file
How come I don't get the complete track from the SMX file? Problem with my program or is that the whole thing you get from the SMX? (see attachment)
Attached images
BL.PNG
I've not touched the SMX files in frigging ages, but it looks complete to me?

The entire race-able track is there..
Do you have the newest SMX? I don't know much about them but thats my only guess...
#5 - Stuff
That looks fine to me.. except for the colors I think. Here is a comparison to mine in the attachment. To fix the colors, swap your red and blue colors. Don't know why, but it works.
Oh! To get the results Scawen has in that thread, you would have to add all the objects that are not included in the smx and texture them all. Not really plausible imo.
Attached images
renders.jpg
I guess we need whatever is in the wld folder. Maybe we can play a guessing game what everything is.

Thanks for the tip about the color, didn't even notice that hehe.

If you switch to a white background do you also get those little white spots portruding from the track?

And how long does it take for your program to read the SMX. Mine was 16 seconds for Blackwood, got it down to 10, but still seems too much.
#7 - Stuff
Good luck with the wld folder. The smx is hard enough!
Yeah, I too get those white spots. They vary though depending on camera position of course as they are just rendering artifacts where some triangles dont exactly touch because of the crazy math. A small bit of anti-aliasing should fix it. I have not tried that though. I use C/C++ and OpenGL so my loading times are pretty quick. Blackwood takes no longer than a second to open for me. AMD 2600+, 1gb, Radeon 9800 Pro. Below is the code I use, might help.. (C++, OpenGL, include stdio.h, no fread checks yet)


FILE *file;
file = fopen(filename_, "rb");
if (file == NULL) {
open_ = false;
// TODO: raise error, could not open
} else {
lfsSMX_HEADER smxHeader;
fread(&smxHeader, sizeof(lfsSMX_HEADER), 1, file);

glBegin(GL_TRIANGLES);
for (int i = 1; i <= smxHeader.num_objects; i++) {
lfsSMX_OBJECT smxObject;
fread(&smxObject, sizeof(lfsSMX_OBJECT), 1, file);

// store object points for use below when we get the triangles
lfsSMX_POINT smxPoints[smxObject.num_points];
fread(smxPoints, sizeof(lfsSMX_POINT), smxObject.num_points, file);

// easy to adjust opacity
int alpha = 255;

// read all the triangles for this object
for (int j = 1; j <= smxObject.num_tris; j++) {
lfsSMX_TRIANGLE smxTriangle;
fread(&smxTriangle, sizeof(lfsSMX_TRIANGLE), 1, file);

glColor4ub(smxPoints[smxTriangle.vertex_A].colour[2], smxPoints[smxTriangle.vertex_A].colour[1], smxPoints[smxTriangle.vertex_A].colour[0], alpha);
glVertex3i(smxPoints[smxTriangle.vertex_A].X, smxPoints[smxTriangle.vertex_A].Y, smxPoints[smxTriangle.vertex_A].Z);
glColor4ub(smxPoints[smxTriangle.vertex_B].colour[2], smxPoints[smxTriangle.vertex_B].colour[1], smxPoints[smxTriangle.vertex_B].colour[0], alpha);
glVertex3i(smxPoints[smxTriangle.vertex_B].X, smxPoints[smxTriangle.vertex_B].Y, smxPoints[smxTriangle.vertex_B].Z);
glColor4ub(smxPoints[smxTriangle.vertex_C].colour[2], smxPoints[smxTriangle.vertex_C].colour[1], smxPoints[smxTriangle.vertex_C].colour[0], alpha);
glVertex3i(smxPoints[smxTriangle.vertex_C].X, smxPoints[smxTriangle.vertex_C].Y, smxPoints[smxTriangle.vertex_C].Z);
}
}
glEnd();

open_ = true;
}

Maybe those artifacts have something to do with Z-buffer accuracy? I still need to read into this. Doesn't really matter all that much anyway.

One question about your code. What is lfsSMX_HEADER smxHeader, lfsSMX_POINT smxPoints and lfsSMX_TRIANGLE smxTriangle? Those are functions that you defined?

It seems my code isn't so slow after all. It takes ~10 seconds to read the Blackwood SMX if I run inside the Visual Studio with debugger. But if you run the .exe from the outside it reads it in 0,7 seconds on my Intel Core2Duo E6400 2,12 Ghz. Doh why didn't I think about the debugger.


Here's my code:

FileStream fs = new FileStream(SMX_file_name, FileMode.Open);
BinaryReader br = new BinaryReader(fs);

int numOfPoints, numOfTriangles;
fs.Position = 60;
int numberOfObjects = br.ReadInt32();

int[] pointX = new int[3000];
int[] pointY = new int[3000];
int[] pointZ = new int[3000];
Color[] vertexColor = new Color[3000];
int red, green, blue;
int triangleA, triangleB, triangleC;
int vert_offset = 0;

fs.Position = 64;
for (int i = 0; i < numberOfObjects; i++)
{
fs.Position = fs.Position + 16;
numOfPoints = br.ReadInt32();
numOfTriangles = br.ReadInt32();

for (int j = 0; j < numOfPoints; j++)
{
pointX[j] = br.ReadInt32();
pointY[j] = br.ReadInt32();
pointZ[j] = br.ReadInt32();

red = br.ReadByte();
green = br.ReadByte();
blue = br.ReadByte();
vertexColor[j] = Color.FromArgb(blue, green, red);

fs.Position = fs.Position + 1;
}

for (int j = 0; j < numOfTriangles; j++)
{
triangleA = br.ReadInt16();
triangleB = br.ReadInt16();
triangleC = br.ReadInt16();

fs.Position = fs.Position + 2;

vertices[vert_offset].Position = new Vector3(pointX[triangleA], pointY[triangleA], pointZ[triangleA]);
vertices[vert_offset].Color = vertexColor[triangleA].ToArgb();
vertices[vert_offset + 1].Position = new Vector3(pointX[triangleB], pointY[triangleB], pointZ[triangleB]);
vertices[vert_offset + 1].Color = vertexColor[triangleB].ToArgb();
vertices[vert_offset + 2].Position = new Vector3(pointX[triangleC], pointY[triangleC], pointZ[triangleC]);
vertices[vert_offset + 2].Color = vertexColor[triangleC].ToArgb();

vert_offset = vert_offset + 3;


numberOfTrianglesToDraw++;
}
}
fs.Close();
br.Close();

And I attached the .exe if anyone wants to play with it and use it to get 2-D images of tracks. Hold the mouse button and move the mouse to move the camera. Or use arrow keys. Mouse wheel to zoom. Or numpad + and -. Button "open SMX fast" will not work because it wants my own "smx" file. Make sure you put the smx and raf files in the same folder as the exe. And of course you need the .NET framework.
http://www2.arnes.si/~mocko/LFS_S2/LFS_replayAnalyser.exe
#9 - Stuff
Ahh yes. the lfsSMX_ things are structs I defined based on the SMX.txt. They are:


struct lfsSMX_HEADER {
char LFSSMX[6];
unsigned char game_version, game_revision, SMX_version;
unsigned char dimensions, resolution, vertex_colours;
char spare1[4];
char track[32];
unsigned char ground_col[3];
char spare2[9];
int num_objects;
};

struct lfsSMX_OBJECT {
int X, Y, Z, radius;
int num_points, num_tris;
};

struct lfsSMX_POINT {
int X, Y, Z;
unsigned char colour[4];
};

struct lfsSMX_TRIANGLE {
unsigned short vertex_A, vertex_B, vertex_C, spare;
};

About the only thing they do is make reading the file easier. Instead of reading individual chars, ints, etc, it reads into those structs making it easier to manage imo.

For your code, I see you define some big (3000) integer arrays for your points that are not necessary. 3000 * 4 = 12000 bytes of memory a piece.. In a quick test on Blackwood, the max number of points any single object has is 660, so 3000 is a waste that may be slowing you down a bit. On the other hand, redefining the array for every object may slow you down too. Hmm, a quick test will help solve which is faster. It all depends..

Overall, our programs are very similar. I do see your program is technically 3D however. Perspective changes accordingly. You should use an orthographic view if you want a true 2D render. And yeah, your depth/z buffer is a little screwy. Mine is too I think but it gets better once zoomed in. Check out the oval building near the Blackwood pits for a good example.

Also for comparison, I attached what I have so far too. To use, create a folder named 'smx' or 'smxU' along side the .exe, move/copy the smx files inside those, then run it. If the smx are found, you will see a list of buttons on the right to open one. Use w, a, s, d respectively to move around, right mouse button to rotate, mousewheel to zoom, left and right to roll, up and down to adjust fov, space to toggle the overlay, o to toggle a world origin thing. The movement is all keyboard event based so its not smooth. I still need to implement some threaded animation code for that.

Have fun with it! I am
Attached files
LYTe.zip - 34.1 KB - 151 views
Quote from Stuff :On the other hand, redefining the array for every object may slow you down too. Hmm, a quick test will help solve which is faster.

You might find linked lists somewhat handy in this situation

Yes, it'll be slower than a massive predefined space, but it's better than a realloc() each time.
Quote from Stuff :For your code, I see you define some big (3000) integer arrays for your points that are not necessary.

I know, it's a "work in progress don't you dare throw me an IndexOutOfBoundException" thing for me.

Quote from Stuff :Overall, our programs are very similar. I do see your program is technically 3D however. Perspective changes accordingly. You should use an orthographic view if you want a true 2D render. And yeah, your depth/z buffer is a little screwy. Mine is too I think but it gets better once zoomed in. Check out the oval building near the Blackwood pits for a good example.

At first I wanted to add a FPS-style camera, but didn't really see any practical uses for it.

Totally forgot you need orthographic for a 2D picture especially if you want to sow multiple pictures together. It's in the code, but behind one of these: //

Anti alialising doesn't solve that problem where some triangles don't exactly match. But it sure does make things alot prettier. x4 is good enough.

This might help you out. It's how I move the view with the mouse. Porting to c++ shouldn't be that hard. Don't forget to multiply by aspect ratio so the left right movement will be at the same scale.

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
drag = true;
mouseX = e.X;
mouseY = e.Y;
}

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
drag = false;
}

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (drag)
{
vCameraPos.X = vCameraPos.X - (e.X - mouseX) * 70000 * aspectRatio;
vCameraPos.Y = vCameraPos.Y + (e.Y - mouseY) * 70000;

vTarget.X = vTarget.X - (e.X - mouseX) * 70000 * aspectRatio;
vTarget.Y = vTarget.Y + (e.Y - mouseY) * 70000;


drawFromData();
}
mouseX = e.X;
mouseY = e.Y;
}


Question about the SMX file
(11 posts, started )
FGED GREDG RDFGDR GSFDG