PDA

View Full Version : Reverse engineering of Wipeout



aybe
9th May 2015, 12:51 AM
I am opening this new thread to keep things separated from Reverse engineering of Wipeout 3 SE (http://www.wipeoutzone.com/forum/showthread.php?9955-Reverse-engineering-of-Wipeout-3-SE).

After successfully drawing textured models: :D

9469

I found that there's at least 2 new types of polygons : 0x14 and 0x16

But there's also what seems to be a wrongly interpreted header since there are others that have outstanding values.

(been working on COMMON folder)

I'll be back once I made some progress !

Jonny
9th May 2015, 10:08 AM
"Antique Repro"
XD

aybe
9th May 2015, 06:38 PM
"Antique Repro"
XD

:P

@all

I will only post here stuff of interests, such as models and so on, for those fond of tech details I am reporting them here https://github.com/phoboslab/wipeout/issues as it's probably a better place.

tigrou
12th May 2015, 04:55 PM
Hi there,

I’m trying to understand the TRS/VEW files format used in original Wipeout/WipeoutXL game.
I was wondering if somebody could give me some help (aybe maybe?).

Most parts of TRS are now well understood. However the occlusion culling part is still a total mystery.

Here is the content of TRS file. Only what is still unknown is the middle part ("unknown" variables).

They are all, i think, related to occlusion culling or additional track information.


Wipeout.TrackSection = Struct.create(
Struct.int32('nextJunction'),
Struct.int32('previous'),
Struct.int32('next'),
Struct.int32('positionx'),
Struct.int32('positiony'),
Struct.int32('positionz'),

Struct.uint16('unknown1'), //always = 8?
Struct.skip(10), //always = 0 padding ?
Struct.array('unknown2', Struct.uint32(), 15), //PSX RAM addresses to VEW file loaded in memory?
Struct.array('unknown3', Struct.uint16(), 15), //always values like 2, 4, 6, 8. VEW file data offset/length ?

Struct.array('unknown4', Struct.uint16(), 2), //section indexes or scene objects (PRM) indexes, or offsets inside VEW file ? seems to start near zero then keep increasing
Struct.array('unknown5', Struct.uint32(), 1), //always = 0 padding?
Struct.array('unknown6', Struct.uint16(), 2), //very similar to "unknown4"
Struct.int32('unknown7'), //always = 0 padding ?


Struct.uint16('firstFace'),
Struct.uint16('numFaces'),
Struct.int16('unknown8'), //always = -1?
Struct.int16('unknown9'), //always = -1?
Struct.uint16('flags'),
Struct.skip(4) //always = 0 padding?
);

To debug/use it just copy that section into wipeout.js of Phoboslab model viewer.

The VEW file seems to be simpler structure, I think contains only a bunch of indexes, all unsigned 16bit.
Probably indexes to sections or PRM scene objects ? (view lists?)

So it should be something like this :


Wipeout.TrackView = Struct.create(
Struct.uint16('unknown') //indexes to track section/PRM objects?
);

Also: there seems to have some reference to "track radius" and "east/south/west/north view lists" on game CD.

Here is a short passage from BETA.OUT file (from TRACK02 folder)


Starting track radius pre process

Section 0 :: north 32 south 10 west 32 east 41 all 41
Section 1 :: north 34 south 10 west 32 east 43 all 43
Section 2 :: north 35 south 10 west 32 east 44 all 44
Section 3 :: north 37 south 10 west 32 east 46 all 46
Section 4 :: north 38 south 11 west 33 east 48 all 48
Section 5 :: north 39 south 12 west 34 east 50 all 50


Again, some related stuff found in WIPEOUT.EXE file (left by compiler) :


radius.c::TrackRadiusCheckNew: Global View List Full ( North )
radius.c::TrackRadiusCheckNew: Global View List Full ( South )
radius.c::TrackRadiusCheckNew: Global View List Full ( West )
radius.c::TrackRadiusCheckNew: Global View List Full ( East )

Track radius is, I think some information related to how large a given track section is (how far the track extends sideways).

Any help will be appreciated.

aybe
12th May 2015, 07:11 PM
Hi!

Yesterday I've been trying to look at it, the best pattern coming seems to be a 84 bytes length:

9473

However there seems to be variable-length structs as the picture above is skewed at times ... Next thing I did is to disasm Wipeout 2 for PC and found this:

9474

So that's what they call a view list, hintful but not so helpful ... I've found the sections were they load vertices and so on and I think I've seen were they unpack each of the component (4), for the VEW however there seems to be many more things being read but since I don't know ASM ... :blarg Also I've found they use the CDQ mnemonic (http://faydoc.tripod.com/cpu/cdq.htm) so there might be real numbers in there.

There is another problem, recent Windows version, if someone could find a way to run WOXL on it, at least we could use a debugger and step through, I'm pretty sure with a memory viewer we could find how the values are being decoded. I've been trying this http://www.wipeoutzone.com/forum/showthread.php?9031-Wipeout-XL-Win-7-Vista-Multiplayer-tutorial, the game goes black screen then I do get couldn't initialize the desired resolution. This game is from the DirectX 3 era :robot, consequently they rarely work like many pre-DirectX 7 games on newer PCs. Unfortunately there isn't much to be done as the best emulator for these versions do not work on Windows (WineD3D), go figure ! :twisted However the game will run fine under Wine in Linux. On a Win98 PCEM virtual machine, the game will load but PCEM will crash ... (unimplemented opcode or whatever). There is another hope : VirtualBOX which uses WineD3D for acceleration, needs to be tested though.

I still do have my P200 + 3DFX where I used to play it, but the problem is rather is a software one, can we find a convenient debugger for Win98 ? BTW, I've used IDA. Otherwise have you tried no$psx ? It might help though it lacks many of the facilities IDA provides and targets MIPS instead of x86.

Other than that don't you think we can do without it as we already have the essentials bits (TRF,TRV,TRS) ? I mean regarding culling and so on, we don't necessarily need to understand the VEW.

PS: beside this failed attempt, I wrote a WAD unpacker to see whether the files in the PC version were identical to the PSX one and they are. So whatever progress you'll make through the PC version will apply to the PSX game data.

aybe
14th May 2015, 09:25 PM
Some (not so good) news about the VEW format :turd

I've disassembled the code with IDA and CodeExplorer and here's where a VEW is parsed,




struct s0 {
signed char[6] pad6;
int16_t f6;
};

/* zFOPEN? */
int32_t zFOPEN_(int32_t a1, int32_t a2, int32_t a3);

int32_t ga2afa4 = -1;

struct s1 {
signed char[8] pad8;
int32_t f8;
signed char[8] pad20;
void* f20;
int32_t f24;
};

struct s1* ga25644 = (struct s1*)0xffffffff;

void zFATAL_ERROR(int32_t a1, ...);

void sub_411A1E(struct s0* a1, int32_t a2, signed char a3);

void sub_401980(int32_t a1, signed char a2);

void zTRACK_VEW(struct s0* a1) {
uint48_t v1;
uint56_t v2;
int32_t edi3;
int32_t eax4;
int32_t eip5;
signed char v6;
int16_t v7;
int32_t edx8;
int32_t eax9;
signed char v10;
void* v11;
int32_t v12;
int16_t v13;
int16_t v14;
int32_t v15;
int32_t v16;
int32_t v17;
int32_t v18;
int32_t eax19;

*(struct s0**)&v1 = a1;
*(int32_t*)&v2 = *(int32_t*)((int32_t)*(struct s0**)&v1 + (*(struct s0**)&v1)->f6 * 4 + 8);
eax4 = zFOPEN_(ga2afa4, *(int32_t*)&v2 + 32, edi3);
ga25644->f24 = eax4;
if (ga25644->f24 == 0) {
zFATAL_ERROR("Track.c:InitViewList: Failed to allocate memory for view list", "Track.c:InitViewList: Failed to allocate memory for view list");
}
*(int32_t*)((int32_t)&v2 + 3) = eip5;
sub_411A1E(*(struct s0**)&v1, ga25644->f24, v6);
v7 = 0;
while (*(int32_t*)&v2 - edx8 >> 1 > (int32_t)v7) {
eax9 = (int32_t)v7;
sub_401980(eax9 + eax9 + ga25644->f24, v10);
v7 = (int16_t)(v7 + 1);
}
v11 = ga25644->f20;
v12 = 0;
v13 = 0;
while (ga25644->f8 > (int32_t)v13) {
v14 = 0;
while ((int32_t)v14 < 3) {
*(int32_t*)((int32_t)v11 + v14 * 4 + 36) = ga25644->f24 + v12 * 2;
v15 = v12 + *(int16_t*)((int32_t)v11 + v14 * 2 + 96);
*(int32_t*)((int32_t)v11 + v14 * 4 + 48) = ga25644->f24 + v15 * 2;
v16 = v15 + *(int16_t*)((int32_t)v11 + v14 * 2 + 0x66);
*(int32_t*)((int32_t)v11 + v14 * 4 + 60) = ga25644->f24 + v16 * 2;
v17 = v16 + *(int16_t*)((int32_t)v11 + v14 * 2 + 0x6c);
*(int32_t*)((int32_t)v11 + v14 * 4 + 72) = ga25644->f24 + v17 * 2;
v18 = v17 + *(int16_t*)((int32_t)v11 + v14 * 2 + 0x72);
*(int32_t*)((int32_t)v11 + v14 * 4 + 84) = ga25644->f24 + v18 * 2;
v12 = v18 + *(int16_t*)((int32_t)v11 + v14 * 2 + 0x78);
v14 = (int16_t)(v14 + 1);
}
v11 = (void*)((int32_t)v11 + 0x9c);
v13 = (int16_t)(v13 + 1);
}
eax19 = v12;
if (eax19 + eax19 != *(int32_t*)&v2) {
zFATAL_ERROR("track.c::InitViewList():problem with view list", "track.c::InitViewList():problem with view list");
}
return;
}


It does really strange things, reads an offset then somewhere else in the file and so on, doesn't make much sense to me. Also the code does check for invalid data and will fail it finds some. Seems to emit a 16 bytes structs (s1) by reading 5 items ... Note that there also VEWs not only for tracks but also for objects. Could this be the path points of the camera when it is rendered ???

I've been able to run WOXL with the latest dgVoodoo2 in Win8.1 :P However it will crash as soon as Alt-Tab is invoked so debugging is impossible... the other good news is that it runs fine in the latest VirtualBox though it is way too fast. One should try remote debugging that VM with IDA.

The content of a VEW seems to be unsigned integers (indices ?), but for what ?

I've also tried to figure out the texturing issue in Gare d'Europa but all my tests failed ... there is clearly something that is being done we're not aware of, maybe the TTF is misleading after all. There also the TRACK.TEX file which I've tried to grab things from, but there are outstanding values beyond texture count. Basically on the track there are 0xD textures, most of the bytes are in this range but rendering doesn't get any better. Also tried to use the unknown bytes from each face...

EDIT: also, it seems that files inside TRACK.WAD are being used for WOXL, so maybe other files are misleading

EDIT: I've debugged WOXL through VirtualBox, and it works quite well though an exception happens and you must pass it to the game and it will continue.

And that's what I said, this thing reads somewhere with an offset, and write somewhere else with an offset, I couldn't understand any of what it was doing/writing :evil

tigrou
15th May 2015, 10:49 PM
@aybe :

about WOXL gare d'europa and Spliskinanke texture issue : this has been fixed since a long time, see https://github.com/phoboslab/wipeout/pull/16

about your VEW disassembly : thanks for this, this is quite helpful. Anyway i'm doing some good progress with understanding VEW files, something might come in days to come. Stay tuned !

aybe
16th May 2015, 07:22 AM
I should have read better your commits, thanks, going to give it a try right now :P

I'm pretty close to get my whole thing as featured as the WebGL experiment, got track/scene/texturing up, need to merge all this and I guess I'll be done :D

It was not as straight-forward as I thought (especially implementing your booster animations), but it ended up well, basically I wrote a scene along meshes/material just like THREE does; it is clean IMO and both things are independent. Then I will use BEPU for the physics as it looks great and is the only viable/recent option BTW.

Once I'm happy with the results, I will look at the next 2 things, the ability of picking scene elements and get the real data from game files so hopefully RE-ing will progress. My first target would be to get these billboards animations working.


For IDA, I'll go and have another look, basically I ran through all flavors of Wipeout : 1/XL, demo/retail. There are two things of interest I've seen and will try to get and share : there are 4 variable names for the TRS in the strings, the length and the count of the VEW file. Hopefully these will help ! Interestingly, the DOS code produced is more pleasant to read but it cannot be debugged ...

Also I've been trying to get the game running and made good progress, beside running it in VirtualBox : I've got the 2 demos running every time in Win8.1 without any funny stuff, thanks to the latest dgVoodoo. There are 2 issues now, game runs too fast and if you Alt-Tab it will crash. Other than that it works really well :P see @ Running Wipeout 2097/XL in Windows 8.1 (http://www.wipeoutzone.com/forum/showthread.php?9964-Running-Wipeout-2097-XL-in-Windows-8-1)

Next objective is to get the retail games running as they are behaving different, working on it :robot


Can't wait to see progress you're talking about ! :+ :+ :+


EDIT: just got retail ver working (see thread above for instructions), it does not crash anymore when using Alt-Tab, the mouse is hidden though ... we might eventually get debugging running on the same OS :D

aybe
16th May 2015, 12:51 PM
EDIT 2

I've been debugging a bit :g

The instructions that I've put for running it in Win8.1 are pretty good as I've debugged locally :P

Not sure but the exception that sometimes occur may come from dgVoodoo (unimplemented opcode), it occurs less often whenever I navigate with the gamepad...

Anyway, I've got a log being output from the game the whenever it loads a track :



CDMusicStop
CDMusicStop
-Loop number- 3
Mem load 35
Total phys -1
Avail phys -1
Total pagefile -1
Avail pagefile -1
Total virtual 2147352576
Avail virtual 1884729344
d:\Wipeout 2097\track08\track.wad
Track load start
d:\Wipeout 2097\track08\tracktex.cmp
attempting malloc
Track load finish
searching for pit lane
creating new instance of light beam
trying to alloc mem for particles
init particle table
init particle done
doing init explode
init explode done
terminated controlled sounds
start controlled sound
Playing track = 10


So it seems like all we'll ever need to use is in the WAD (basically FYI I've checked a WAD content, it is identical to other files; maybe all these files are simply misleading after all...)

Here's the content of one, haven't checked them but I'd guess they're all similar ...



library.cmp
library.ttf
scene.cmp
scene.prm
sky.cmp
sky.prm
track.trf
track.trs
track.trv
track.vew


The format of the WAD is really simple if you'd want to base yourself on it in the experiment :

Roughly, the name of each item is variable, you have to adjust accordingly, then the next 2 values should be packed/unpacked length -> I assert these are equals; finally extract each item.



private static void Unpack(Options options)
{
using (var stream = File.OpenRead(options.InputFile))
using (var reader = new BinaryReader(stream))
{
// read header
var itemCount = reader.ReadUInt16LE();
var items = new List<Tuple<string, uint, uint>>();
for (var i = 0; i < itemCount; i++)
{
var name = reader.ReadStringAsciiNullTerminated();
stream.Position += 16 - name.Length - 1;
var length1 = reader.ReadUInt32LE();
var length2 = reader.ReadUInt32LE();
stream.Position += 1;
items.Add(new Tuple<string, uint, uint>(name, length1, length2));
}


// check data
var all = items.All(s => s.Item3 == s.Item2);
if (!all)
{
throw new InvalidDataException("Compressed items not supported");
}

var sum = items.Sum(s => s.Item2);
if (sum > stream.Length - stream.Position)
{
throw new InvalidDataException("Not enough bytes left");
}

// extract
var outputDirectory = options.OutputDirectory;
if (string.IsNullOrEmpty(outputDirectory))
{
outputDirectory = Environment.CurrentDirectory;
}

var directoryInfo = new DirectoryInfo(outputDirectory);
if (!directoryInfo.Exists)
{
directoryInfo.Create();
}

foreach (var item in items)
{
var itemName = item.Item1;
var itemLength = item.Item2;
var itemBytes = reader.ReadBytes((int) itemLength);
var itemPath = Path.Combine(directoryInfo.FullName, itemName);
File.WriteAllBytes(itemPath, itemBytes);
}
}
}



If by some magic we could lower the frame rate and play it ... actually I'm as impressed as I was 15 years ago when I used to play it with a 3dfx, it is so smooth and 480p compared to the PSX :):):)

tigrou
16th May 2015, 01:11 PM
Hi there,

I had a look at VEW files and get it working : see my commit https://github.com/tigrouind/wipeout/blob/culling_vew/wipeout.js

Thanks for aybe disassembly, this was VERY useful to get it working.

Notes :
- This is not very efficient way to perform culling on today GPUs: the whole track (without objects around) is about 3000-5000 faces (triangles) which is nothing. This is maybe even slower than no culling at all (because we send new polygons to GPU every frame). A better way (if needed, eg : on low end hardware) would be to cut the track in big pieces, and the perform some frustum culling on it. This is something already implement by threejs (all objects are frustum culled by default), only needed is to cut the track in separate objects.
- VEW files are only used for the track culling , not for other objects around (eg :train, bridge, trees, ...). For these ones another info (inside PRM file) is probably used. I suspect PRM file to contains some sort of bounding spheres/ boxes , organised as a tree (sort of bounding volume hierarchy).

About VEW files (how it works) :

For each track section, there 15 lists defined.




north
south
west
east
all


near
x
x
x
x
x


medium
x
x
x
x
x


far
x
x
x
x
x



- north, south, east, west lists : used for default game play, when camera is behind player. depending how player is oriented with the track, one list is selected. default is north list, when riding reverse, south is used.
- all list : a combination of the 4 lists above. this is used for replays, for cameras around the track

near, medium, far : used for mip mapping. for far sections, low quality texture are used.

Each list contains visible track segments (so for a given section , the renderer only renders visible track segments).

One example : player is in section 47, riding forward (not reverse)
for section 47, in north near list, we have two segments : [400,4] [420,2]

So we will render sections 400,401,402,403,420,421

aybe
16th May 2015, 07:34 PM
Congratulations, you've nailed it:clap:clap:clap

It's incredible how info. can be hidden on the web yet it's just next to us, (haven't thoroughly checked that repo but I guess it's been helpful to you). I did try to IDA the Amiga version as someone shared it with me, but since it showed only dozen of subs I concluded it was not correct and stopped looking at it. I did look at Demo 1 about a week ago but I wasn't on that IDA thing yet.

One of the thing I found really immersive when I first seen the experiment was the drawing distance, but while seeing your branch I have to say that it's nice as well though as you've laid is not essential. Now we know what VEW is about we can always do it properly later.

What is bugging me is whether we'll be able to find all those scenery animations, I don't know if you've paid attention but actually there's a lot, from the rescue ship to those cameras following you etc ... it popped in front of my eyes with the PC version as while the PSX ver. is great, on the PC it's way more detailed.

Which leads me to this, I finally have a working WOXL with the right speed on Win8.1 + dgVoodoo and there's even 1024*768 :g basically those patches were around for a while but there's no real clear help for recent Windows; I will inspect better and update a definitive tutorial !

Otherwise I've found the definitive type of polygons : 23
It's kinda hard to interpret those disasms, sometimes they're correct sometimes not, for instance some of types we already render do heavily use maths as you'll see in IDA, we can get a general overview however.

I'll probably spend a last day with IDA then I'll stop because while it's fun, it's really exhaustive and haven't really progressed on the C# side.

PS just PM-d you right now.

aybe
17th May 2015, 06:58 AM
Hi !

While started implementing your work and looking for the sizeof(TRS), a GREP search outputted the following:



TOTAL: 29 matches in 29 files (119 other files without matches are not listed)
...
1 match in C:\Users\Aybe\Documents\Visual Studio 2013\Projects\WXX-Rebirth\.gamedata\WIPEOUT\TRACK14\TRACK.INF
9 sizeof( Section ) = 156 bytes
1 match in C:\Users\Aybe\Documents\Visual Studio 2013\Projects\WXX-Rebirth\.gamedata\WIPEOUT\TRACK15\TRACK.INF
9 sizeof( Section ) = 48 bytes // <-------------------- this one
1 match in C:\Users\Aybe\Documents\Visual Studio 2013\Projects\WXX-Rebirth\.gamedata\WIPEOUT2\TRACK01\TRACK.INF
9 sizeof( Section ) = 156 bytes
...


(they're all 156 bytes as you know)

The TRACK.INF:



TRACK INFO::
============
dbName = /disk2/wipeout/SOFT/TESTS5
sceneName = V3track_A-Lsave.1-0
outName = trak1
total vertex count = 1710
total polygon count = 1378
sizeof( Face ) = 20 bytes
sizeof( Section ) = 48 bytes


I remember seeing this and I've extracted the TRV of it :

9480

EDIT 1: while plot.ly is cool, I was skeptical of the output and decided to feed my points renderer, makes more sense now !

9481 9482 9483

EDIT 2: It does look like Terramax but when looking at it from bottom :

9484

Here's the track gone through my 'official' renderer :g
(the textures might be okay as I haven't yet implemented the fix you've told for Gare d'Europa)
9485 9486

Looks like we have another unfinished track but in WO1 this time ! strange :?

Do you have any infos about it or did I miss something (again) from the repository ?

Thanks :D

Xpand
17th May 2015, 11:25 AM
That's Terramax
http://wipeout.wikia.com/wiki/Terramax

it looks slightly different in yours due to perspective distortion.

tigrou
17th May 2015, 11:27 AM
@aybe : interesting finding. looks like a beta track of terramax that was left out.

It feel like the CD content of wipeout is actually a full copy of dev working folder, and they then manually deleted what they don't want to show (eg : source files and such), leaving many stuff there by mistake (eg: in wipeout2 TRACK02, there is a LIBRARY.H file). Also, if you look at PS1 DEMO01 CD, in wipeout folder there is even icons of the track editor they used (as CMP file if I remember well).

About your previous comment, where you mention "scenery animations" : they where probably hardcoded in the exe based on model name (found in PRM file).

Most are too specific to be specified in data files (eg : cameras must look at player, some other object must rotate around Y axis and such...). That would explain all those string references to these models found in EXE file.

There is anyway maybe some generic stuff (eg : texture that must rotate for ads panels near tracks ) that we missed out. There is still many unknown fields in PRM files to be discovered.

These could contains some of these animations.

--------------------------------------------------------------------------------------

EDIT : oops, i did not saw your thread (http://www.wipeoutzone.com/forum/showthread.php?9964-Running-Wipeout-2097-XL-in-Windows-8-1), let's give it a try

about reversing engineering the game : i found some interesting part. This is the one that load the track sections.


int zLoadSections() //start at 0044D8F5
{
int result; // eax@2
__int16 j; // [sp+Ch] @3
__int16 k; // [sp+Ch] [bp-Ch]@6
__int16 i; // [sp+10h] [bp-8h]@1
int v4; // [sp+14h] [bp-4h]@1

v4 = *(word_A296D4 + 20);
for ( i = 0; ; ++i )
{
result = word_A296D4;
if ( *(word_A296D4 + 8) <= i )
break;
zReadInt32(v4);
zReadInt32(v4 + 4);
zReadInt32(v4 + 8);
zReadInt32(v4 + 12);
zReadInt32(v4 + 16);
zReadInt32(v4 + 20);
zReadInt16(v4 + 24);
zReadInt16(v4 + 26);
for ( j = 0; j < 3; ++j )
{
zReadInt16(v4 + 2 * j + 96);
zReadInt16(v4 + 2 * j + 102);
zReadInt16(v4 + 2 * j + 108);
zReadInt16(v4 + 2 * j + 114);
zReadInt16(v4 + 2 * j + 120);
}
[B] //unknow data
for ( k = 0; k < 4; ++k )
{
zReadInt16(v4 + 2 * k + 126);
zReadInt16(v4 + 2 * k + 134);
}
zReadInt16(v4 + 142);
zReadInt16(v4 + 144);
zReadInt16(v4 + 146);
zReadInt16(v4 + 148);
zReadInt16(v4 + 150);
zReadInt16(v4 + 152);
v4 += 156;
}
return result;
}

it confirms what we already know about TRS. the part in bold (which is 4 times two 16 bits integers) is still mystery.

I tried to find reference to that special memory zone in code but did not found anything interesting.

Unfortunatly the game does not run on my machine (because 64 bit OS ?). I tried with the Wipeout2097 PC demo, the installer seems to be 16bit :(. The exe just hang out (i have to kill the process).

Would be it possible for you to game in an debugger (eg : ollydbg) and check which part of code read to this address (by putting a memory read breakpoint): *(0x00A296D4 + 20) + 126 ?

aybe
17th May 2015, 09:48 PM
That's Terramax
http://wipeout.wikia.com/wiki/Terramax

it looks slightly different in yours due to perspective distortion.

yes but it is upside down, we'll get a better view once we render the associated scene :D

- - - Updated - - -

@tigrou:

Yes and I was hoping that there's a debug mode because there's a ptiDebug string but I don't think so -> it's been compiled as release mode and probably everything has been left out but the OutputDebugString calls that either Windgb or IDA will show (the log I've posted).

For the scenery and animations we'll probably know once we're comfortable enough with the code base, I can't remember but I did find some tiny file and rendered the vertices, it did look like a whirlpool but did not pay much attention then. Looking back this could have been the animation paths of some scene object. Also I really need to get this scene object picker/reporter up, as once we'll know what raw bytes makes a polygon and so on I'm certain we'll progress on these unknown fields.

I don't know what's going on up here, IDA does not work anymore on the VM apparently of this https://support.microsoft.com/en-us/kb/948854, did revert the snapshot but it didn't help ... the thing is locally I have no mouse so I can hardly use IDA. For this and ollydbg I am looking at it now ...

Also the tutorial I wrote seems to need an overhaul, I'll see if I can address that within the next days. Just tried again and it works here, remember to :

copy CD to a dir
in this dir copy setup32.exe and set Win95 compat, install, etc ...
then edit the registry to point not to this folder but to your CD drive (note: it seems that a proper rip is needed with subchannels, as I've tried a bare ISO and it won't work)
setup dgVooodoo
then make sure Wipeout2.exe is run as admin but no Win95 compat


This is what works here so you should be in-game ...

Things are getting out of control but we are soon to get the control back :D

Xpand
17th May 2015, 10:19 PM
yes but it is upside down, we'll get a better view once we render the associated scene :D


That might just mean the track is mirrored vertically. Have you decompiled any other track to see if that happens with every track? Because that type of thing happens a lot in other games too, including models rotated by 90 degrees in some axis.

aybe
17th May 2015, 11:59 PM
Thus far it's the only folder that we missed, I haven't thoroughly looked at others but from what I remember in the experiment javascript I've seen nothing in the like, i.e. they're all the same.

Regarding mirroring (EDIT: was thinking of reverse in fact...) that's quite interesting, while trying to play the other way around I found that it is not possible in WO -> jumps. This would definitely be a nice perk in the remake, by now, modifying the track is clearly doable though it remains to be seen whether the UX will play fine.

- - - Updated - - -


@aybe : interesting finding. looks like a beta track of terramax that was left out.

....
Would be it possible for you to game in an debugger (eg : ollydbg) and check which part of code read to this address (by putting a memory read breakpoint): *(0x00A296D4 + 20) + 126 ?

I finally got hold of the issue : VC Redist 2008 :turd

This is what I found, it seems to be a byte it is checking for:


int sub_44AF32()
{
int result; // eax@2
__int16 i; // [sp+Ch] [bp-8h]@1
int v2; // [sp+10h] [bp-4h]@1

v2 = *(dword_A25644 + 20);
for ( i = 0; ; ++i )
{
result = dword_A25644;
if ( *(dword_A25644 + 8) <= i )
break;
*(v2 + 4) = *(dword_A25644 + 20) + 156 * *(v2 + 4);
*(v2 + 8) = *(dword_A25644 + 20) + 156 * *(v2 + 8);
if ( *v2 != -1 )
*v2 = *(dword_A25644 + 20) + 156 * *v2;
v2 += 156;
}
return result;
}

The addresses you gave were different btw, also I haven't really understood how ollydbg works ... when you press X on that dword, all the subs using do appear ... but their name is not evocative -> I suggest that we do get in synch by using the same environment. I think the VM way is the best since you don't lose mouse facilities. Going to prepare something and get in touch, not today though but sometimes this week. Also, I'll try to rename as much as possible so we get a good start with the IDB. There's only one thing not working in the VM, -> retail version complain there's no 3d card; i'll see if I can make it work.

vincoof
18th May 2015, 07:52 AM
I’m pretty impressed by the RE you’ve done so far. Keep up the good work guys.

aybe
18th May 2015, 12:09 PM
Thanks, support is really appreciated :D I'm sure we'll get to it :mr-t

- - - Updated - - -

Slight update,

The TRACK15 will not load properly with the current code as its PRM has an older format ...:blarg

aybe
18th May 2015, 07:52 PM
Hey,

I'm pretty close to the level of features of the experiment :P

9489

tigrou
19th May 2015, 08:41 PM
@aybe : about previous post : not sure to understand what you mean :)

Also : WipeoutXL/2097 contains WAD files which in their turn seems to contain TRS/TRF/TRV files.

Are they exactly the same as the files contained in the folder themselves ?

aybe
20th May 2015, 11:57 AM
@aybe : about previous post : not sure to understand what you mean :)

Also : WipeoutXL/2097 contains WAD files which in their turn seems to contain TRS/TRF/TRV files.

Are they exactly the same as the files contained in the folder themselves ?

Remember, I said I was after doing a remake of the first 2 games : https://github.com/aybe/WXX-Rebirth :D So the rendering is okay though there are a few things I've encountered such as the need of writing my own renderer, just by the fact that transparent objects are not rendered correctly ... hopefully this is not too hard as I did peek into THREE.js and all that (seems to be) needed is the sorting of opaque/transparent entities.
This also raised two concerns, the ability to individually pick items to render which will be useful in RE-ing and the integration of a physics engine as the examples I've seen in BEPU do make use of their scene model but what if I stop using it mid-way ? Those should be separate.

WADs

I have implemented the following logic to blindly load a track either from WO1 or WOXL:

1. If there is TRACK.WAD in folder, load all the following files from it :



library.cmp
library.ttf
scene.cmp
scene.prm
sky.cmp
sky.prm
track.trf
track.trs
track.trv
track.vew


Else load them individually.

2. If TRACK.TEX is here, load it and patch TRACK.TRF with it.

That logic loads any track from any game ... So that's all that seems to be needed in WOXL : TRACK.WAD/TRACK.TEX.

BTW, the differences between WOXL PSX/PC is that for PC, textures are in TRACKTEX.CMP (library.cmp for PSX) and they are the 128*128 version so no need to make a collage. I've been trying to compare WADs using FC, there seems to be identical except that there's a few bytes offset ... TBC though. (Haven't tried to parse PC files in my classes, only PSX)

.CHK (checkpoint)

Confident enough I decided to give a try to the only remaining files on track folder in WOXLPC : CHKs

9490

I failed somehow, thought I would find a position in the track and tada but it wasn't that :naughty

Then I thought about your last performance :D could these be PSX offsets ? Been trying to look for such code but I failed again, so when you have a minute or two :P

tigrou
20th May 2015, 06:52 PM
about CHK files : it does not seems to be PSX ram addresses, since only addressable range is 0x00000000 - 0x001FFFFF (2MB)

Most of the time, 0x80 is added in front of them. Eg : 80 44 0B 1D (so PSX address is 0x001D0B44)

I think those checkpoints are either specify directly by section index (eg : check point is at track section 142). the other values would be lap times (depending the class).

or maybe they are defined using a sphere bounding box : sphere position (XYZ = 4 * 3 bytes) + radius (2 or 4 bytes?)

The time in this game is encoded this way : 9:59.9 = (9*600+59*10+9)*5 = 29995 (maximum possible remaining lap time)

Here is one thing you can try (it helped me in my previous searches) : you start a PSX emulator (eg : psxjin r726). Then you search for the content of CHK file in RAM (for TRS they were in memory just like on the filesystem so i just had to search some bytes pattern). You can use cheat search functionality for that or use a lua script (in case of psxjin). Be aware that the byte order can be different than files on CD (big vs little endian).

Then, once you find where the data is (in memory window), you modify it directly in RAM while the game is running and you check how it change the game (in case of checkpoint it could different remaining time for checkpoint OR modify checkpoint position.

You can also (as alternative) rip your game CD to an ISO file (if not already done :)), then modify the ISO directly (open it in a hexadecimal editor and search for a given byte pattern and change it). This is, anyway, a slower iteration than changing in RAM

About WAD files : yep the way you did it is how it work for most game with containers (eg : doom). Anyway you did not answer my question : are the file in the WAD binary different from other files in track folder ?

About VEW files: i give it another try yesterday : there was a minor bug. now the track culling (using VEW files) works perfectly and exactly like on the PSX. Check this branch : https://github.com/tigrouind/wipeout/tree/culling_vew. VEW files have no more secret for me. Check my post from 16/05 on first page of this topic for more info (i edited it). What is still unknown is how culling is performed on scene objects. It seems the game performs culling per object polygon ! (instead of per object). Would this information be contained in the "unknown" fields of the many polygon types the game use ?

aybe
20th May 2015, 08:00 PM
Thanks, I'll work further according your hints and see if I can get any result using a PSX debugger and the TRS as well :D this is going to keep me busy for a while !

For the files in the WAD they are binary identical ... at first I was wrong and I did compare with the content of the WAD for the PC but we can draw extra conclusions from that :



66,976 LIBRARY.CMP
76,636 library.cmp1
504 LIBRARY.TTF
588 library.ttf1
32,728 SCENE.CMP
55,438 scene.cmp1
380,280 SCENE.PRM
382,360 scene.prm1
9,648 sky.cmp1
1,488 SKY.PRM
624 sky.prm1
28,120 TRACK.TRF
37,240 track.trf1
50,076 TRACK.TRS
66,924 track.trs1
27,824 TRACK.TRV
36,912 track.trv1
29,196 TRACK.VEW
40,440 track.vew1


The files ending with 1 are from the WAD from the PC, looks like the geometry has been updated or something :D What I'll do is that I'll integrate these PC files in my pipeline and see if I visually spot any differences and whether they first load without any hitch.

For the VEWs I can only admire the inside you've had with it, I'm quite left out with this hacking/asm part as it's an entirely new topic to me, so well done :clap :clap :clap :clap :clap

Actually I did notice this morning that the zeppelin in Gare d'Europa is affected by the culling as well ...

FWIW here's the data of it I've quickly extracted :



index1: 0x2452
unknown1: 0x27
unknown2: 0x0000, 0x0000, 0x0000, 0x0000, 0x1c0c, 0x0000, 0x0000
unknown3: 0x1c2c, 0x0000, 0x0000, 0x0fb5, 0xa230, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
unknown4: 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x1000, 0xae6e
unknown5: 0x1000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x1000, 0x5518
unknown6: 0x0001, 0x1c0c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 0 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 1 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 2 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 3 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x1008 unknown2: 0x0090 polygon 4 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 5 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x9298, 0x0000 unknown2: 0x0000 polygon 6 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0003, 0x0000 unknown2: 0x0000 polygon 7 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 8 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x006b, 0x0000 unknown2: 0x0000 polygon 9 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xaaa8, 0x1008 unknown2: 0xbbb4 polygon 10 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 11 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 12 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 13 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 14 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 15 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 16 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0001 polygon 17 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0006 polygon 18 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 19 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0xae80 polygon 20 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x1008 unknown2: 0xe220 polygon 21 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xa230, 0x0000 unknown2: 0xae80 polygon 22 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 23 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 24 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 25 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 26 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x1008 unknown2: 0x0090 polygon 27 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 28 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 29 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0006, 0x0000 unknown2: 0x0000 polygon 30 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 31 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x006b, 0x0000 unknown2: 0x0000 polygon 32 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xab28, 0x1008 unknown2: 0xbbb4 polygon 33 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 34 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 35 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 36 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 37 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 38 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x00e1, 0x0000 unknown2: 0x0000 polygon 39 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0001 polygon 40 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0005 polygon 41 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 42 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0xae80 polygon 43 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x1008 unknown2: 0xe250 polygon 44 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xa2f0, 0x0000 unknown2: 0xae80 polygon 45 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 46 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 47 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 48 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 49 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x1008 unknown2: 0x0090 polygon 50 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 51 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 52 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0005, 0x0000 unknown2: 0x0000 polygon 53 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 54 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x006b, 0x0000 unknown2: 0x0000 polygon 55 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xaba8, 0x1008 unknown2: 0xbbb4 polygon 56 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xafe8, 0x0000 unknown2: 0x0000 polygon 57 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 58 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 59 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 60 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xb0c0, 0x0000 unknown2: 0x0000 polygon 61 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 62 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0001 polygon 63 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0006 polygon 64 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 65 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0xae80 polygon 66 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x1008 unknown2: 0xe280 polygon 67 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xa3b0, 0x0000 unknown2: 0xae80 polygon 68 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 69 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 70 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 71 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 72 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x1008 unknown2: 0x0090 polygon 73 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 74 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 75 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0006 unknown2: 0x0000 polygon 76 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x00ea polygon 77 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xae80, 0x0001 unknown2: 0xbf20 polygon 78 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xe298, 0x1008 unknown2: 0xac58 polygon 79 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xae80, 0x0000 unknown2: 0x0000 polygon 80 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0001 unknown2: 0x0000 polygon 81 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 82 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 83 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0001 unknown2: 0x0000 polygon 84 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0090, 0x0000 unknown2: 0x0000 polygon 85 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 86 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 87 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 88 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 89 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0xac88 polygon 90 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xac98, 0x31d3 unknown2: 0x0000 polygon 91 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 92 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 93 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 94 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 95 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0xae80 polygon 96 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 97 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 98 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0001 unknown2: 0x0005 polygon 99 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 100 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0xae80 polygon 101 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x1008 unknown2: 0xaca8 polygon 102 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x1008, 0xa4d0 unknown2: 0x00f0 polygon 103 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 104 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 105 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 106 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 107 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 108 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 109 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 110 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 111 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 112 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 113 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x006b, 0x0000 unknown2: 0x0000 polygon 114 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xacf8, 0x1008 unknown2: 0xbbb5 polygon 115 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 116 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0001 unknown2: 0x0000 polygon 117 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 118 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 119 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0001 unknown2: 0x0000 polygon 120 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0090, 0x0001 unknown2: 0x0000 polygon 121 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 122 (type: TexturedTrisFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 123 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 124 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 125 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0xad58 polygon 126 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xad68, 0x31d3 unknown2: 0x0000 polygon 127 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 128 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 129 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0x0000, 0x0000 unknown2: 0x0000 polygon 130 (type: TexturedQuadFaceColor, subtype: 1)
unknown1: 0xd060, 0x0000 unknown2: 0x0000 polygon 131 (type: TexturedQuadFaceColor, subtype: 1)

tigrou
20th May 2015, 09:29 PM
FYI here is the lua script I use with psxjin r726 :mr-t good luck!


--search whole PSX memory range (change 4 to 1 if pattern is not 32bit aligned)
for readposition = 0x00000000, 0x001fffff, 4 do
--search for a pattern (be careful of big/little endianess)
if (memory.readdwordunsigned(readposition) == 0xff1d10aa) then
print(string.format("%08x", readposition))

end
end

one more thing : the ASM decompile from PC version (using IDA) was (for me) a big waste of time. the only useful part what the disassembly you posted some days ago. the rest i could not make anything useful with it.

most stuff has been discovered by playing with emulator and RAM.

aybe
20th May 2015, 10:37 PM
Thanks, I'll give it a try ! :P

- - - Updated - - -

Ok for IDA, well the thing is that the environment is great but I reckon it might be overkill :blarg

Have you done anything particular with psxjin ? here it runs like the PC version does at 200 fps, no matter which setting I try I can't get normal speed !

tigrou
20th May 2015, 10:51 PM
Yes the emulator is full of bugs. Except things like sound or video that disappear after alt-tab, freezes or crashes.

I was never able to fix the "too fast fps" (there is an option for that in video settings but it just dont work).

I have this piece of code (from some psxjin experiments :)) that should more or less fix it (big hack!)


--framerate lock
framecount = 0
starttime = os.clock()

while true do

--lock framerate at 30 fps
elapsed = os.clock() - starttime

while elapsed < framecount / 30 do
elapsed = os.clock() - starttime
end

framecount = framecount + 1

emu.frameadvance()
end

aybe
21st May 2015, 11:35 AM
Alright, thanks, I'll see if I can make it thru. I've tried again yesterday and I got sound, it's too bad because that LUA facility is really a good thing.

Desperate I've been looking at IDA and continued the renaming of subs ...

The code does funny things like :



qmemcpy(a1, v7, 0x24u);
for ( i = 0; i < 6; ++i )
*((_BYTE *)a1 + 6 * i + 4) = -1;


These positions in the CHK are already 255 ... I'll continue digging on this and see if I do any progress.

tigrou
21st May 2015, 06:36 PM
From code you gave it looks like data is 6 bytes length, starting at offset +4

so if we took check point data you posted in screenshot and align it that way :


05001E00
FFF78B001400
FF3AFFFF0A00
FF7FFFFF0A00
FF00FFFF0A00
FF00FFFF0A00
FFC6

It looks like we have sort of pattern

could the last part be actually a piece to add to the first part ? (to be checked)

so it becomes :


FFC605001E00
FFF78B001400
FF3AFFFF0A00
FF7FFFFF0A00
FF00FFFF0A00
FF00FFFF0A00


:hyper

aybe
21st May 2015, 08:12 PM
From what I could see, there are 6 entries in a CHK each being 6 bytes and they are UINT16. But their value is quite puzzling ...

Other than I've been trying to slow down WOXLPC but I can't get anything that lasts ... I think I've found where the time calculation is being done but I don't really understand how it works.

9494

Tried to change these bit-shifts and modulo but it works for a small amount of time.

Crossing fingers that it's a standard update() loop as we know it by today :|

I will continue the renaming of subs, I have done a couple already and this will grow over time.

Also, I think I've found a struct for some unknown parts of a TRS but it's too early IMO, however, can you confirm that a TRS.FirstFace is never greater than 65535 ? I think so as regarding the models size this should be enough. If it is then we have a refined struct.

EDIT been writing while you've been !

sorry but I don't understand what you mean regarding the CHK, can you elaborate a bit ?

EDIT1

for the code I've put, I've tried locally with a small program and it seems to do nothing as it sets bytes in the CHK that are already 0xFF ... haven't checked with all CHKs though.

EDIT 2
Ok I got it, actually I've seen that pattern you are talking about but I was not really convinced by it but maybe you're right after all !

I haven't yet tried to patch a CHK and see what it does, going to try ...

- - - Updated - - -

EDIT 3

I've made a simple test, replaced all the checkpoints by the latest and it seems that I do have less time to reach a checkpoint

EDIT 4

Byte 1 does nothing beside setting time to 20s
Byte 2 crashes if not 0

Next byte do change the seconds but it's erratic

Now the next 4 bytes at offset 2 do change the time indicator !

9495

Seems a bit more complex than expected :D

EDIT 5 and last

At byte 2, set the number of seconds desired minus 20 (UINT16LE), it will set the time when starting.

The other files and checkpoints don't do anything, I always get 40secs.

Not sure it is worth pursuing this thing, it's not essential after all !? :turd

vincoof
22nd May 2015, 07:19 AM
Reordering data is always dangerous.

IMHO this:

05001E00
FFF78B001400
FF3AFFFF0A00
FF7FFFFF0A00
FF00FFFF0A00
FF00FFFF0A00
FFC6
should be viewed as:

05001E00FFF7
8B001400FF3A
FFFF0A00FF7F
FFFF0A00FF00
FFFF0A00FF00
FFFF0A00FFC6
my2c

aybe
22nd May 2015, 11:51 AM
Well, didn't want to revive this thing but you just gave me an idea :

Index1, Seconds - 20, Index2 (all UINT16BE but seconds) (Indices in TRS, when 0xFFFF ignore, makes sense to me as game crashes when it's wrong, access denied or so ?)

5 entries since max lap count is 5

4 files, one per class

But I won't spend any more time on this :turd, there are more important things IMO :P

tigrou
22nd May 2015, 06:59 PM
But I won't spend any more time on this , there are more important things IMO

Yep, probably.

Anyway : did you noticed there is no checkpoint / startup objects in phoboslab model viewer ? (eg: near repair zone, there is a big white arrow on red background).

http://s3.postimg.org/o8kvbo3kj/Sans_titre.jpg

Same goes about red/amber/green lights at startup.

They are not rendered. Could it be explained because these are set dynamically by the game depending what is found in the checkpoints files?

aybe
22nd May 2015, 08:27 PM
That's an interesting theory, I didn't notice.

9497

These bytes doesn't point to a decent index nor look like a light color, btw that's in light.prm that the model is.

Things are going to stall quite a bit here, have to advance on the game itself, there's enough material to keep one busy and build one. Have started looking for physics, a ground is a ground now !

9498

Still looking for a good arch. as there's the graphics but the physics as well and I need to come up with something easy to handle ...

We might discover new things over time but I expect the discovery rate to be pretty low though !

Cipher
22nd May 2015, 08:54 PM
They are not rendered. Could it be explained because these are set dynamically by the game depending what is found in the checkpoints files?

This is most likely the case, from a game dev point of view it makes sense to load the object once into memory and place it multiple times, instead of wasting verts left and right by creating it into the track model ;)
Great work in here! :)

Cipher

tigrou
22nd May 2015, 11:38 PM
@aybe : what language are you using ? three.js ?

about physics: it seems this is what devs used to model the collisions of the ship against the track :

http://s18.postimg.org/noyg8nosp/col.jpg

see ALCOL.PRM file.

It would be a lot easier if you use a physics engine that roll your own.
Unity might be a good candidate for this.

Xpand
23rd May 2015, 11:06 AM
Those collision models make sense. That's the same technique I'm using in my AG physics engine (programmed in C, no 3rd party physics libraries).

https://www.youtube.com/watch?v=cIxYkZSesEQ

I was thinking about importing WO1 models into it, when I get the basic physics stuff done, like detecting the ship's height above the track's surface, which I'm working on right now.

I would advise you to use unity too. It takes a huge load of programming mesh collision detection and other physics stuff, unless of course, you use a physics library, like Bullet Physics.

aybe
23rd May 2015, 01:22 PM
@tigrou

I use C# and MonoGame.

Thanks this will be very useful ! Yesterday I was wondering on what to use and opted for a cone but this seems to be the thing to use ... once I figure out how to handle collisions according this shape. I opted to use BEPU (https://bepuphysics.codeplex.com/) for the physics, as this is the only recent and free engine I found that supports MonoGame as well.

I have been tempted to use Unity but there are 2 problems with it : the import of models, thought about using Autodesk FBX SDK to convert PRMs but another problem arises -> the game data is shipped by default and IMO this opens the door to those copyright infringement seekers ...

@all

I think BEPU has the potential to realize the physics of the game as it's quite featured, once I figure it out ! I will probably get good support as the author is really involved in helping people as you can see in their forum (http://www.bepu-games.com/forum/).

For BulletPhysics, unfortunately the only port for .NET I've found is bullet-xna (https://code.google.com/p/bullet-xna/) but it seems unmaintained and I don't really know whether it will work with MonoGame.

I am open to any suggestion if you think there's a better route than the one I've said, Unity is very appealing but I've laid out the above 2 issues, let me know if I'm wrong !

Also, regarding physics, this is an entirely new topic to me and suggestions are welcome. My preliminary search about physics for a craft brought the usage of spring physics and/or a raycast stick below the ship ... I am not too worried for now by the exactitude of either approaches, my near future goal is to get physics and rendering in place and decoupled as much as possible. Once this foundation is in place and trustworthy, the refinement of the game will take place and eventually a physics engine change mid-way.

:P

tigrou
23rd May 2015, 04:02 PM
I have been tempted to use Unity but there are 2 problems with it : the import of models, thought about using Autodesk FBX SDK to convert PRMs but another problem arises -> the game data is shipped by default and IMO this opens the door to those copyright infringement seekers ...

Even if import of models is something supported by Unity (as well as asset management) i wouldn't do it that way but rather read the PRM files from the wipeout directory and build model directly at runtime (i have done this previously in Unity this is pretty easy). I would read the other files as well that way (sound, textures,...) . So you solve the 2 problems (copyright stuff) at once. You can take a look at phoboslab viewer code (how to build the models) because you will probably need something similar. The whole JS code to create models is about 70 lines, not a big deal.

Here is a good start for dynamic mesh generation : http://docs.unity3d.com/ScriptReference/Mesh.html

Also : i would not do all the fancy stuff at first (texures, sound, menus or whatever) but rather build a simple prototype with the bare minimum :

- the main track build from TRF/TRV files (no texture, no object around), just a single gray flat polygon stuff
- The ship (from the collision model i give you above)
- Some basic ship physics (collide with the track, push force from behind, accelerate, decelerate, steering, airbrakes)

Then try to get something that feel close to the original and publish for testing. Get feedback and improve until it is good enough. This is the real challenge. Gameplay is everything.

Then you have all the time necessary to add the rest (and get help from other devs because you have a "proof of concept").
That's probably how the first Wipeout game was done, they build a first prototype then tested it : "hey guys this is cool" then add some more graphics and all the rest to make it a real game.

aybe
23rd May 2015, 08:34 PM
Sounds like a good idea but ... here's what happened here :

After getting hold of Visual Studio Tools for Unity and trying to debug the Roll-a-ball tutorial, a simple thing such as the game receiving input while VS has the focus didn't work. This resulting for instance in the inability to debug that PlayerController that moves the ball, as obviously I have to put a breakpoint in VS and the Unity Editor doesn't receive any input ... Also I did not find a single thing about using Unity by code, seems like I'm missing something !

Can you explain how to get started / how you would do it ? thanks :D

tigrou
23rd May 2015, 09:43 PM
I advise you to follow some tuto on youtube. That's how i get started. Unity seems to be a little bit intimidating at start but it's actually pretty easy.

About you debug issue : why don't you use MonoDevelop?

aybe
24th May 2015, 01:40 PM
Ok, I've got something on screen, have a couple of things to do before rendering a track, stay tuned ...

EDIT

I'm getting familiar with the thing and it's pretty good though it crashes from time to time ... re-used most of my low-level classes with little to no changes, in probably 2-3 days I'll have something up (hopefully) :D

aybe
25th May 2015, 01:35 AM
To be continued !

9500

aybe
25th May 2015, 09:49 PM
Here's some more Unity treats :P

9502

Still fighting a bit with Unity tutorials but now on the track to get busy with physics :blarg

tigrou
26th May 2015, 07:03 PM
Good progress :hyper

Is it Altima VII ? if yes, it seems the whole track is flipped around the X axis.

- - - Updated - - -

trivia : on DEMO01 CD (official demo CD delivered when PSX comes out), there is a Wipeout demo.

The CD had to be ready before the game was released so Wipeout was probably still in beta stage.
In "Wipeout" folder, on CD, there is TIM files (textures) that does not look like regular game textures but rather from an editor for the game.

Why TIM files ? was the game developed on machine similar to the PSX itself ? or was the editor running directly on PSX ?

Here is a screenshot of them and my comments (this is pure speculation from me)

http://s2.postimg.org/pm1gxym61/editor.png

BOOM, BOOMW: an unfinished weapon icon ?
BUG : call technical support ? :)
CAMERA : probably allow to define cameras along the track
CHNGTRK : edit track faces textures ?
DPA: ??
EBOLT, ECM, ELECT, FLAR, MINE, MISS, NEG, ROCK, SHLD, TURB : related to bonuses. in the first ever wipeout, were the bonuses placed directly on the track (instead of a "X" cross ?). Or is this to view bonus 3D models ? or to test debug (because the editor run "in game") ?
HALO : ?
EMPTY : ?
LNDONOFF : to switch the land (the scene objects around the track) on/off
RADIUS : to define bounding spheres around scene objects, for occlusion culling.
SAVE : pretty obvious. suprisingly there is no load icon :)
SHIP : to set start position of the ships, or to view 3D model ships in game ? AFAIK, the ships start positions are determined by texture indexes on track (to confirm)
SKY : turn skybox on/off
SMOKE : to add some smoke particles ? (as seen in talon's reach )
TRAKVIEW : track visiblity on/off ? or is it related to VEW files ? (to view actual culling performed at a given position?)
TRANSTRK : to edit track structure ? (eg:extend track on the side, create a tunnel,...)
VRAM : PSX vram debugging (eg : to view loaded textures, actual framebuffer ? ...).

Xpand
26th May 2015, 08:00 PM
Some of those images seem to be part of some developer's debug menu. It isn't rare for developer tools (eve if it's just some part of them) to be left in the final game's files.

Those files are also in the final release version of the game.

tigrou
26th May 2015, 08:28 PM
Those files are also in the final release version of the game.

I did not know that. I would be cool if it was left there and it would be possible to reactivate it.
Anyway the exe seems to not reference any of these files (while the other seems to be referenced) :/

So either there was two EXE's files, or there was two builds (compile switches)

aybe
26th May 2015, 09:07 PM
And they are also in the PC version, can't remember exactly where ... and yes it's Altima VII.

I've been trying to get hold of this ptiDebug variable on the disassembly in hope this infrastructure was still in place and could be triggered but without much success :paperbag

Bit of progress in Unity:

I have a ship that moves and hovers now ! but it can leave the track very easily :g
I need to get hold of how to constraint it close to it as well as the angles as it can become reversed ... any clues are welcome :D

Xpand
26th May 2015, 09:59 PM
What we did for slipstream GX was to basically override Unity's physics regarding rotations and gravity. We use rigidbody components on the ships with frozen rotation and no gravity. The rotation in each axis is then calculated with a script, same with every force on it. That gives a lot more control over the ship.

It'd be a good start to look at the forces in action on a plane, because it's exactly the same thing:
https://howthingsfly.si.edu/sites/default/files/image-large/Cessna-1_lg_0.jpg

tigrou
26th May 2015, 10:38 PM
I was going to post something but Xpand was faster than me :hyper

Here is my two cents :

- either constraint rigid body movement (eg : rotation on X/Z axis) so it wont happen. check rigidbody panel properties; some movement (eg : roll) can be purely visual. to do this you can add ship model inside another parent object and rotate only that one. this is probably Xpand direction (no joke here :P).
- (or) apply a stabilize force (torque) that make sure the ship is always up right. you need measure the difference between actual ship orientation and a target orientation and apply a force accordingly. (like a putching ball)

something like this : http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html#answer-10426. Might be unstable or unable to handle violent collisions.

aybe
27th May 2015, 03:58 PM
Thanks :clap :clap :clap trying to apply your suggestions !

The plane analogy is really great and it seems the way to go as well as constraining rotations.

I have some sort of a plane for now, it does lift off a bit like WO does but it's really naive ... found a plane sample that I'm trying to pick ideas from.

A rough guess is that such kind of physics would more or less give what's needed like aero brakes and so on.

But I've never done any physics as of yet so this is likely to take a bit of time :blarg

Xpand
27th May 2015, 11:08 PM
Here's a code snippet of an Anti-gravity physics engine I'm programming in C:
This takes care of the vertical portion of the forces on the ship:

player->acc.z=player->gravity+(20.0/(0.1+fabs(player->pos.z-player->proj.z))-player->vel.z*player->vel.z*player->vel.z*2.0)/player->mass;

the K/(A+fabs(height)) bit does the AG magic, making the ship float around a certain height above the ground. I can make the ship float higher or lower by increasing or decreasing "K" and make the ship respond more or less to the variations of the track by adjusting the "A" parameter (and also avoids that whole thing becoming infinite when the height is zero).

The three velocity components vel.z take part in damping the ship's wobble. It's basically the drag force present in that airplane diagram, only in the vertical axis. It's there just so the ship's oscillation decays with time.

tigrou
28th May 2015, 07:33 AM
I remember I wrote (some months ago) a game similar to wipeout with a constant force to be applied from the ground. This was prototype wrote for testing only.
The vertical push force was not stable and wobble a lot. I solved this by using a simple PID controller (http://en.wikipedia.org/wiki/PID_controller) :


distance_target = 5.0 //we want object to be always 5 units above the floor
distance_to_ground = cast a ray from object to the floor

error = distance_target - distance_to_ground
derivative = error - last_error

// kp and kd are constants to be adjusted (stability vs speed)
force_to_apply = error * kp + derivative * kd

last_error = error

aybe
28th May 2015, 01:46 PM
Thanks everyone :D This comes in really handy and I hope I'll be able to apply all these tips, I sort of found a couple of decent links yesterday about all this but I still need to read them. I'm quite confident that I'll get to it ... one day ! This is an entirely new topic to me so it's pretty much sound like Chinese to me for now. :bomb

aybe
28th May 2015, 05:20 PM
I remember I wrote (some months ago) a game similar to wipeout with a constant force to be applied from the ground. This was prototype wrote for testing only.
The vertical push force was not stable and wobble a lot. I solved this by using a simple PID controller (http://en.wikipedia.org/wiki/PID_controller) :


distance_target = 5.0 //we want object to be always 5 units above the floor
distance_to_ground = cast a ray from object to the floor

error = distance_target - distance_to_ground
derivative = error - last_error

// kp and kd are constants to be adjusted (stability vs speed)
force_to_apply = error * kp + derivative * kd

last_error = error

this works really well :+

@Xpand still trying to digest your formula :pizza

Xpand
28th May 2015, 06:31 PM
Well it uses real physics (I'm a physics engineer, so I guess that might have something to do with it), hence why it seems more complicated, but it's nothing more than the forces that would exist if the ship existed in real life, with a bit of tweaking for optimization.
The main thing to retain is the "K/(A+fabs(height))" bit, which is basically the equation for the upward force created by a compression spring (like car springs), and the vel.z^3 works as the damper in a car's suspension.

Basically what I have there is:

acceleration in Z axis = gravity + (lift_force+damp_force)/mass

Tigrou's method is best for performance on the long run though, I'd use his idea if I didn't want to waste too many resources calculating the ship's behaviour (although my method doesn't take that much more, it's just because it uses a division operation), or if I wasn't too worried about how accurate the floatiness would be (mine takes into account the ship's mass (inertia) and gravity)

aybe
28th May 2015, 07:25 PM
I'll definitely give a try to your method, it's just that it takes time for me to understand this new topic :brickwall

That's about 2-3 days now I'm on the physics thing and I guess it's going to take quite some time by now, I am confident however !

Here's my little training field : :D

9506

- - - Updated - - -

I haven't been able to reproduce your snippet :brickwall



var gravity = Physics.gravity.y;
var zPos = carRigidbody.position.z;
var zProj = 0;
var zVel = carRigidbody.velocity.z;
var mass = carRigidbody.mass;
var zAccel = gravity + (20.0f / (0.1f + Mathf.Abs(zPos - zProj)) - zVel * zVel * zVel * 2.0) / mass;


I don't understand what
player->proj.z is supposed to be.

Also, I might have missed something but, how does this works against Y axis since you never update it ?

thanks :g

(as you might have guessed, I lack complete knowledge about the subject topic :D, right now I'm still on the phase of copy/paste/run )

Xpand
28th May 2015, 07:39 PM
I'm so sorry, I just copied that from my engine, which uses that variable to get the height of the ship above the track (it calculates proj.z from the projection of the ship's X and Y position on the mesh triangles of the track to get the distance of the track's surface to z=0). It's native to my engine, and not a generic thing (you don't need to use it).

In sum: (pos.z-proj.z) is "height":
K/(A+fabs(height))
You need to tweak the numbers to your liking, hence why I wrote K and A, they're just numbers you choose.

Also in my case the Z axis is vertical. It might not be your case (just change it to the Y axis).

aybe
28th May 2015, 08:23 PM
Okayyyy that's what I just thought and been thinking it was a trap you just set for me :D

I have been able to get some cool results, but it's kinda hard to really understand how the thing works without proper context. Basically for both of your suggestions, they are applied when a ray cast hit is true and then I apply that force to the car (I guess it's correct since both formulas are working).

But your formula brings in 2 other interesting properties : it gets affected by mass and drag (defaults of 1.0, 0.0) while @tigrou's formula is not ... it's like in the Universe -> you discover 1 thing but there are newcomers ... I guess I'll have to document myself a bit more on the overall subject ! This just got me for today but I'll see tomorrow.

Also, I hate those non evocative variable names usually found in math formulas (K, A) but I reckon it's the usual approach. I've been trying to come up with ones a bit more meaningful : stiffness and feedback but this is pure speculation from me. Would you qualify them as such ? thanks :D

Xpand
28th May 2015, 08:49 PM
K is stiffness, higher K makes the ship float higher and makes it harder for it to hit the ground. A is the "give". It's kinda hard to find a word for it. "A" basically determines how violently the ship will react when its height approaches 0. If A=0 then as the height approaches zero, the lift force will tend to infinity, if A=0.1 the lift force will be K/0.1 when the height=0. It provides control to avoid very larger force values that will make the ship shoot up to the sky if it hits the track.

By the way, since Unity already simulates drag, you don't need to have the drag portion of the equation there (the vel.z*vel.z*vel.z), I had to add that because my engine assumes drag is included in the acceleration equation and it's not a separate thing.

tigrou
28th May 2015, 08:55 PM
@Xpand : interesting.

The formula I give (PID) is a general purpose method. This can be used to control systems using a feedback loop (with stability and precision to a certain degree).
Some specific formulas that model concrete physics models (like the one you give), might, however, work better or be more precise.
I would not care too much about CPU performance on today computers. This should not be the bottleneck. I would simply choose a method that can be tweaked easily and give the best gameplay. That is the most important aspect to me.

About the formula you give :
"K/(A+fabs(height)) " and also " vel^3 " where does this came from ? do you have any reference, paper, wiki page? (for learning) i'm (unlike you) not a physical engineer :redface:

I took a look at Hook formula, but it seems to be not that thing.

about "dividing the force by mass", it came from F = m a right (pretty basic stuff :D)?

Xpand
28th May 2015, 09:11 PM
Yes, you divide force by mass to get acceleration, like Newton's 2nd law states: F=mass*acceleration

about the K/(A+fabs(height)), it's a cheat that comes from, for example, the electrostatic force between two charged particles: Fe=Ke*charge1*charge2/(r^2), which states that the repulsion/attraction force between two charged particles is proportional to their charge and inversely proportional to the square of the distance between them (as distance increases, the force decreases). I just considered "Ke*charge1*charge2" as "K" and since I wanted to save some processor cycles I used the absolute value of the distance between the track and the ship fabs(height) instead of calculating its square. I added the "A" to avoid problems with division by 0, like I stated in my previous post.

The vel^3 (cube power of the velocity) comes from the aerodynamic drag equation:
http://upload.wikimedia.org/math/9/9/a/99a6015b6a230860c9b1517b238e5de9.png
all those variables have a meaning you can see here: http://en.wikipedia.org/wiki/Drag_%28physics%29#Types_of_drag I just made them all "2.0" for now.

I know it says v^2 in that equation, I used v^3 because I want to take into account the sign of the velocity (if it's negative or positive), so the force points opposite to the movement of the ship. I can use the v^2 just like that equation, but then I have to multiply by v/abs(v) to get the sign of the force (v/abs(v) can be -1 or 1), but again, to save processor time and avoid divide-by-0 problems I just used the v^3.

The PID method is good for setting variables that you can consider independent, like temperature in an oven, position of a mechanical arm, etc. For something that requires other stuff to characterize it (like a force), the PID leaves out those important variables and treats the force as an independent thing (when it isn't). Because this is a game PID would probably be a better choice than doing a physical simulation of the whole thing due to its simplicity, and I'm pretty sure they used it in the first Wipeouts. When rigidbody physics come up, you get stuff that depends on other stuff and differential equations everywhere, and PID just doesn't cut it.

DIXI200
29th May 2015, 06:38 AM
You guys rock, Amazing how much work .. I checked all your formulas, :dizzy :eek , yes,yes it's all right :g lol

Mobius
29th May 2015, 07:31 AM
The vel^3 (cube power of the velocity) comes from the aerodynamic drag equation:
http://upload.wikimedia.org/math/9/9/a/99a6015b6a230860c9b1517b238e5de9.png
all those variables have a meaning you can see here: http://en.wikipedia.org/wiki/Drag_%28physics%29#Types_of_drag I just made them all "2.0" for now.

I know it says v^2 in that equation, I used v^3 because I want to take into account the sign of the velocity (if it's negative or positive), so the force points opposite to the movement of the ship. I can use the v^2 just like that equation, but then I have to multiply by v/abs(v) to get the sign of the force (v/abs(v) can be -1 or 1), but again, to save processor time and avoid divide-by-0 problems I just used the v^3.


Surely velocity cubed would make the drag parameter unphysical/unrealistic? Would it not be better to define a Heaviside function using logic to ascertain the direction of the drag e.g....?

if (v < 0) {
sign = -1;
} else {
sign = 1;
}

and therefore have your velocity squared again.

Xpand
29th May 2015, 11:02 AM
Oh indeed. I forgot about that function (which is weird because I use it so many times in other stuff)! Thanks!

The velocity^3 would be unrealistic in the sense that the dampening would happen a lot faster than with v^2. Which isn't necessarily a bad thing, but yeah its real world equivalence is the drag Power and not the drag Force: http://upload.wikimedia.org/math/e/3/1/e31430f0898268091f410282a89503b1.png

aybe
29th May 2015, 09:09 PM
Things are stalling over here ... :frown: @Xpand I've somehow tried to 'upgrade' your code with a hover distance but failed miserably, I've also looked at 'hovercraft physics (http://www.llcowell.com/instructional_samples/straightforward/mneidermeir_physics/template.htm)' on the web and got a cube to hover manually, then I tried to use that PID approach on it but again I failed ...

Also I've been looking at thrust/torque, while I can move and turn fine another problem surfaced : it never stops since I'm not on the ground ! Applying a physic material on the rigid body obviously did nothing...

Just to make it clear : should I completely bypass Unity's physics system and think of everything or are there are physics-related things you'd keep on ? (beside constraining X and Z rotations)

thanks !!!

Xpand
29th May 2015, 09:57 PM
You just need to constrain the rotations, because you'll have a rolling ship everytime you enter a banked corner otherwise.

For the linear movement just use the AddForce command in Unity: http://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html
Also use the rigidbody.drag property so your ship doesn't accelerate without limit and slows down when you stop accelerating.

The rotations you have to work with angles directly and transform rotates.

aybe
30th May 2015, 01:06 AM
Ok I'll give it a try and post my results ! thanks !!!

EDIT also, I found that script posted by the BallisticNG author and this is really a good hint; however it cannot be a simple copy/paste, will have to digest those 900 lines and hopefully I'll have something solid !

- - - Updated - - -

Works very well, victory :rock

Next step is to try upgrade your script with hover distance :D

When I get comfortable enough I will start looking at sources of BallisticNG and AGR2280 !

tigrou
30th May 2015, 10:09 AM
I love the look (graphics) and feel (physics) : https://www.youtube.com/watch?v=zuy9sryZSIc

It is very PSXish (it is intended I guess)

Now imagine being able to play this with all W1 & WXL tracks :hyper

EDIT : oops, seems it is discussed on this forum : http://www.wipeoutzone.com/forum/showthread.php?9936-Ballistic-NG-Wipeout-fan-project/page13 :redface:

aybe
31st May 2015, 08:45 PM
Yes it's pretty good but it runs way too fast, I can't stop hitting walls ! There should be some Vector class IMO :P

aybe
2nd June 2015, 05:15 PM
@Xpand

here's the situation here:

I've been striving to do some of the ship physics all by myself, from scratch :D

Using 4 hover points, an angular drag of about 20 and not constraining the rotations : the thing is quite 'okay' in the sense that I've got an automatic leveling to the surface below myself and it's quite realistic. But there were 2 major issues occurring then : this was undesired when on edges of the track and whenever on air the ship was not leveling to the horizon or whatever.

So I began trying address the 'on-air' issue but it just seems that in the end, to get an 'enjoyable' game one has to resort to all kind of hacks (understand here not rely at all on physics provided by Unity), just like the BallisticNG ship controller code that has been posted recently on the forum.

My question is : is this really the way to go or is there a slight hope in getting cool craft physics using the facilities provided by Unity ?

thanks :D

Xpand
2nd June 2015, 06:07 PM
Enjoyable gameplay is indeed riddled with hacks. You have to "bend" the physics engine to your will, and do some trickery for it to do what you want. That happens in pretty much all games.

aybe
2nd June 2015, 06:11 PM
I kind of forgot there were programming patterns recently as I was quite amazed by Unity, but that definitely makes sense.

Okay, I'll just base myself on that BallisticNG ship controller code then and see if I can improve/tune it to my needs ... thanks :+ :+ :+

tigrou
2nd June 2015, 07:40 PM
@aybe : can only agree with Xpand.

About your hover issues : have you tried the following : when you shoot rays against the track, you do it against a special collision track 3D model that has only the "ground" track faces set (these faces have a special flag in the TRF file). These are the one that rise up/down quickly when you use the "Quake disruptor" weapon. Only these faces should be considered when calculating ship/floor distance or actual track orientation.

BTW, you consider ALL track faces when performing regular colisions, because you want don't want ship to go out the track.

To avoid issue with gaps : if a ray does not collide with anything, simply take the latest valid result (that you keep somewhere) :


if(ray.hit(..., out result))
{
lastValidHit = result;
}
else
{
//oops, there is a gap, take latest result
result = lastValidHit;
}

//do something here with "result"
...

or you might consider another approach : the idea is to always have a 3D track orientation for any given ship position. I supsect the original game to do something like that since it's quite easy to calculate. Not need to shoot rays. Here how to do : you loop trought all track sections, calculate the one which is the nearest from the ship (by calculating ship/section distance). Once you have the nearest section, you calculate the normal vector of that section (easy and could be precalculated before and stored). This is the actual track orientation and the one the ship should have. Even if the ship goes out off the track but continue moving forward) you still get a 3D orientation.

To avoid brutal changes, you can smooth that out using an interpolation method :


var orientation = to calculate...
smoothorientation = Quaternion.Slerp(smoothorientation, orientation, 0.7f); //between 0.0 and 1.0

instead of using 4 push forces, you might consider using only one (at center of gravity) and actually rotating the ship by simply applying a torque to the rigid body (so that the ship is always more or less oriented like the track).

aybe
3rd June 2015, 03:49 PM
Thanks everyone, going to give all your suggestions a try !

Bit of a deception here, I thought those 3D frameworks would provide a smarter approach but that seems to apply only when it's fully featured in regards to realistic physics. I guess that BEPU physics is a little more featured but not sure it outweighs the facilities of Unity ... I might give it a try later though as what seemed to be tough is a bit clearer now -> I'd just have to follow that composition pattern of Unity.

Basically at this point it's a simple copy/paste operation, still I'd like it to be a bit more than that ... still have a few links to read and also look at the AGR2280 and I think I'll get started. (and the TRS format as well since I've never used it yet, just seen that debug path in the experiment)

aybe
3rd June 2015, 08:54 PM
Bit of progress here !

- I separated concerns of model and controller
- tried that hovering/leveling again from scratch and it seems it's a better route -> leveling is coherent and it is now unaffected by a tunnel whereas previously it was going crazy (@tigrou seems like I'll need your air tip at some point !)
- also hitting walls is coherent as well though it will certainly need a different physic material to behave like the original game
- edit : I do constrain rotations now

The simplest approach works the best !! The feeling is definitely Wipeout-like when the ship raises/lowers its nose, will need a few magic values later.

For BallisticNG code however, I've abandoned for now as it's too early, I'll certainly take higher-level hints from it but at this point I was not feeling that simply fixing the errors will do the job, plus many constants were missing as well.

So a little victory but definitely more positive than the stalling of last days :D

aybe
7th June 2015, 09:30 PM
Quick update to let you know what's going on:

- cleaned out the classes and now have separate layers for the walls and the ground -> prepped the thing for easier usage
- got some sort of DIY prototype with hovering, pitching, airbrakes, sections and so on, though wall hitting was not right

But I've just started porting the Ballistic NG code :g Been able to guess the missing constants for now, got the hovering and thrusting, still a lot remains to be done. I'm trying to understand the thing a bit at the same time, I kind of went the same route on my own but it was way less tuned ... I should have some solid physics within a few days, hopefully :D

AdHoc
8th June 2015, 09:32 AM
Go go aybe!

aybe
10th June 2015, 11:05 PM
Here is a video of the 1st prototype ! :rock


https://www.youtube.com/watch?v=0hVcILbw4tw

There are still a few issues but the main substance is here, I've been studying the game and tried to mimic its behavior as close as possible.

I've abandoned using code from BallisticNG and AGR2280, problems being that the 1st is incomplete and misses many things, the 2nd while fully available I could hardly find anything to grasp from it (you might disagree). The copy/paste of snippets worked at first but later went problematic, I guess all should be in but I did not feel taking this route :blarg

So what you see above is my DIY approach, different by a couple of aspects, done by a physics newbie not constraining rotations, letting the engine do its job and try to cohabitate with it instead of bending it; over time I got something relatively stable ...

Let me know what you think about the video !

I have a couple of questions for you guys if you can give some hints:

how to make pitching more reactive when going down the long air-jump ?
how are on-air periods approached, is it by using a stronger gravity ?
how to add the user's free pitch and make hovering aware about it ?
proper airbrakes, is it just torque+slowdown or does horizontal force should be considered too ?
high-speeds can still make the ship pass through the ground when landing, even with continuous detection


Thanks :D

EDIT: website secured @ http://wxx-rebirth.com/ :p

tigrou
12th June 2015, 09:17 PM
@aybe :
This is great, lot of hard work so far. Please continue like that...

There still many things to fix until it really feels like the real game but the gates are now open

I take a look at your questions later on, when i will have some time.

aybe
13th June 2015, 04:07 AM
thanks, in the mean time I drop 2 other questions and another video !

what do you think emulating this bouncing ship requires, in the hover spring or the physics material ?

the way to go seems to not use triggers as we don't get contacts and lose some freedom over collisions, or did I miss something ?


https://www.youtube.com/watch?v=HRNm2YA3WLI

(also, I do try to keep some sort of history of changes in the website if you'd like to know what has changed)

tigrou
17th June 2015, 01:33 PM
@aybe : hope you are still working on the project. I took a look at your questions and to be honest I cannot answer any of them.

Let's hope a guy with physics background and/or game dev experience in a wipeout clone will answer (like Xpand)

Cipher
17th June 2015, 02:58 PM
when you're nearing the bottom plane of the collision (read not side walls) you probably want to apply an upwards force relative to the distance between bottom collision plane and ship, if this is managed in the hover effect, you just want to increase the hover strength relative to the distance of the floor, that's how i see it anyway

Airtime & hovering you probably want to have a relation between height between track and ship as well, meaning the hover effect disengages when a certain height is achieved (saves performance too ^^), gravity is too high in both your previews i think (better in the first one, but even there, probably still too high, you could fly really far without pitch on that jump after the big drop)
Airbrakes; i think you have correctly implemented them, just need to add ship rotation to it to make it more convincible ;)

Cipher

Xpand
17th June 2015, 04:13 PM
I honestly don't understand your question.
In that video it seems you already have the bounce physics working in some way. Are you using physics materials or are you using coded forces?

The hover/spring force is a must for these times of games, however small of an effect it has, there's no real point in trying to avoid using it. Using physics materials only goes so far, and when you want to make more customizeable physics it won't work as well as having the forces coded from scratch.
I'm stuck with final exams until july, but after that I can help you more directly if you want.

aybe
17th June 2015, 11:16 PM
Yes I'm still on it ! I did quite some work lately though not on aspects I wanted to enhance : hover and bounce :|. I guess @Xpand was right :P, you have to bend that thing but that introduces something : we bypass everything so we need our own physics layer.

The thing is that I'm pretty certain they did handle wall hits like I do now : applied force being normal of the wall, mystery being why sometimes the ship rolls instead in PSX. Anyway this is the most coherent approach I found and have no plans to improve it any further unless really necessary.

9525

But as @Xpand said constraints are needed, I can't get anything stable with OnCollision* methods as from what I understand, physics are applied no matter when these are called. Collisions are either occurring twice or making the ship slide downwards and hover comes in and screws everything. Also physic materials have no effect since I hover and add forces. If I let it touch of course materials are in action but in turn it's too realistic ...

First solution is OnTrigger*, problem : no contacts and so on but no problem as I do cast rays and it works well. It does work well but now ships passes through at times and OnTrigger should be even on the ground (did not yet try). Also, while current thing works well in AltimaVII, things go insane in ArridosIV for instance ...

I have 3 goals :
- see if I entirely drop OnCollision* (would like to try @tigrou hint of using ALCOL.PRM as collider)
- see if OnTrigger* and everything manually will do ... but lots of work like in AGR/BNG
- split concerns as the thing is getting cumbersome to manage (might have to do this 1st :blarg)

As day passes on, I do find that the original game is less and less realistic that I thought at first, to the point that it's entirely unrealistic hence bypassing Unity physics might be a good move though it will cost a lot. Finally the bouncing, I can't find any spring setting reacting like in the original game, unless physics are not realistic. I will see if I can get @Cipher and @Xpand hints to improve the current thing otherwise I'll attack the problem entirely from the roots :twisted

I expect my next video to show way more refined physics, hope I'll get to it soon :D

EDIT: @Xpand, yes help is really appreciated, take your time and good luck !

EDIT 2: a quick video that shows these issues

While some parts have improved, some have degraded as you will see; that gave me some hints though so I'll see if I can fix that stickiness before taking another approach.


https://www.youtube.com/watch?v=vlvjdDbuhNM

Xpand
18th June 2015, 11:23 AM
The ship rolling when it hits the wall in PSX is an animation and not a physics thing. They used center of mass physics for everything other than detecting collisions, so torque and other rigidbody rotation was impossible for them to do back then.

Also you're using discrete logic when calculating the AG force (On collision, On trigger, etc). That can create infinite derivatives in the velocity (fig. 1), which translates directly into infinite acceleration, which is most likely why it glitches out. This has to be a continuous thing. The AG force has to constantly be calculated and active to get the best results.
http://i.imgur.com/Gi4q7ej.jpg
Figure 1.

Cipher
18th June 2015, 04:23 PM
^That's a pretty good representation yes! ^^

Forces is most likely the way they went, because they probably didn't have fancy "physics materials", but also because they had to make it work on a console, which is very strict on resource management, especially back then, even if they had something like physics materials, there would be too much clutter code they don't need taking up performance, physics/ forces translated into gaming isn't so hard to grasp, should get a course on it if you're really interested, you'll learn a lot ^^

Cipher

aybe
18th June 2015, 10:54 PM
The ship rolling when it hits the wall in PSX is an animation and not a physics thing. They used center of mass physics for everything other than detecting collisions, so torque and other rigidbody rotation was impossible for them to do back then.

Also you're using discrete logic when calculating the AG force (On collision, On trigger, etc). That can create infinite derivatives in the velocity (fig. 1), which translates directly into infinite acceleration, which is most likely why it glitches out. This has to be a continuous thing. The AG force has to constantly be calculated and active to get the best results.
http://i.imgur.com/Gi4q7ej.jpg
Figure 1.

Sorry but I don't get what you mean with infinite derivatives ... for that weirdness I know the cause and I think I can fix it : hover expects a floor and there's none at this position, it starts falling down and suddenly hover recovers and make it jump as it's pushed away and retrieves the floor below it. I guess a plane representing each section floor will do or as laid out previously, a manual approach will obviously do.

EDIT: I think I do understand what you mean, but what is your suggestion then for having a continuous representation ?

- - - Updated - - -


^That's a pretty good representation yes! ^^

Forces is most likely the way they went, because they probably didn't have fancy "physics materials", but also because they had to make it work on a console, which is very strict on resource management, especially back then, even if they had something like physics materials, there would be too much clutter code they don't need taking up performance, physics/ forces translated into gaming isn't so hard to grasp, should get a course on it if you're really interested, you'll learn a lot ^^

Cipher

I'm too old for school, i.e. it's too late :blarg no but seriously, physics courses won't necessarily address translating this to programming which is a must; and honestly I'm not that much interested in maths/physics, like one does not need to know electronics to use a PC. I however understand that I will somewhat have to dive deep for this, I hope reasonably !

Cipher
18th June 2015, 11:55 PM
It's never too late to learn anything ;)
Translating it to code is rather easy, it's just vectors really :)

Cipher

aybe
24th June 2015, 04:34 PM
I can't really find any good resource on the web, would you suggest looking at books instead ?

Xpand
24th June 2015, 05:46 PM
You're going to have to code your own physics, there is no way around it. You can try searching for stuff on introduction to Classical Mechanics for the physics stuff. Technically you don't really need to look for books, although the only fault I find in them is their price. The real issue here is knowing what to look for, and to be honest the physics needed to simulate an AG ship require a bit of understanding on forces and gravity, stuff like that.

You can obviously go the hacker way and throw real physics out the window when you're coding, but you'll still need to know what's going on with the ship.

aybe
25th June 2015, 05:11 PM
While books are generally pricey, they take your hand from start to end; I personally really lifted my C# level years ago only after I did read a really good book on it. But I agree that they have downsides, there are many of them but I'd say that they are however most of the time better than those web tutorials ...

Back to the topic,

Do you think that I can still benefit from drag, angular drag, force and thrust from Unity's rigidbody, instead of coding my own ? I would however not use OnCollision* overrides which apply physics logic, but OnTrigger* overrides which only tell me who collided with who and leaves me free to code my collision logic.

The thing is as you said, one has to know these topics, which is not my case, hence why I'm trying to rely as much as possible on useful bits in Unity. I've left my code sleeping for a bit and to be honest, my new approach with OnTrigger* is not that bad as it's pretty much like the original so I guess this is the right route, those OnCollision* interferences are gone, but only time will tell.

Do you have a rough idea of how does physics work in the original game ?
What's your opinion on it, do you think they use some real physics concepts or is it all faked ?

thanks :D

BeRo
1st July 2015, 07:35 PM
Also Supraleiter has a side-project called Rewipeout which can load WipeOut 1 and 2097/XL asset data, where we (the Supraleiter team) can tweak the Supraleiter physics against the original WipeOut 1 and 2097/XL tracks. Rewipeout has a complete own codebase except the shared physics code from Supraleiter. And Rewipeout will be opensourced later (as base for a sort of "ScummVM" for the first two WipeOut titles), when Supraleiter is released.

The physics of Rewipeout and Supraleiter are, or better, will be a mixture of primarily the WipeOut Pulse physics and secondary of the two WipeOut PSX titles. You might ask yourself why WipEout Pulse primarily. The reason is simple, the WipeOut Pulse physics were very good described by a WipeOut developer in a game developer magazine from November 2005, so it is comparatively easy, to reimplement these physics as a start base for our own physics behaviour style.

And here finally is also a video to Rewipeout:


http://youtu.be/zdduMpnMRqc

And for more infos to Supraleiter itself see the Supraleiter thread http://www.wipeoutzone.com/forum/showthread.php?9723-Supraleiter-an-anti-gravity-futuristic-racing-indie-game&p=244039#post244039

aybe
3rd July 2015, 10:23 PM
thanks for the heads-up about the magazine !

seeing your video was a bit depressing for me :frown: a 1-man team with poor physics knowledge VS a team of 5 with strong physics knowledge is not likely to achieve any better; just started questioning myself whether it's worth I pursue this effort !

BeRo
3rd July 2015, 11:45 PM
thanks for the heads-up about the magazine !

seeing your video was a bit depressing for me :frown: a 1-man team with poor physics knowledge VS a team of 5 with strong physics knowledge is not likely to achieve any better; just started questioning myself whether it's worth I pursue this effort !

In this one team of 5 peoples I am the only one with the physics knowledge, the other guys in the team are mostly only content artists.

But the basic implementation details behind (at least) WipeOut Pulse style physics are really very simple:

What you do need as first, is a true aerodynamics linear velocity drag equation (a la http://physics.info/drag/ ), where the drags in the forward&side&up axes are not the one same common drag damping value, but rather, the forward-axis-drag should be the biggest, the drags for the side&up-axes should be lower, because the rest is then quite easy to implement and will come comparatively easy, specifically the previously difficult things with the previously most fake physics implementation approaches (I even had to learn that).

And instead springs, I'm using soft constraints for hovering with five hover world meshtriangle/plane distance constraints to the track floor down (four on the down ship convex hull edge points plus one on the center of mass), since these are more stable and more easy tweakable than springs. For more informations to soft constraints: https://github.com/erincatto/box2d/blob/master/Files/GDC2011/GDC2011_Catto_Erin_Soft_Constraints.pdf

So don't give up, try rather new physics implementation attempts :) Also I myself needed several tries before I got it reasonably, including several complete rewrites of the core general physics engine itself, not just at the game physics code implementation itself.

aybe
5th July 2015, 03:11 AM
thanks for all the tips !

I did read all the links you've provided and while I do understand why they are a better approach, I have no clue at all on how to 'code' these concepts.

The drag-related topic if I'm correct would require writing physics from scratch, right ? If yes then it is beyond my competence at all as I can't even get a simple formula to code :brickwall BTW why do suggest a different drag for forward, is it for coping with high speeds ?

For the soft constraints, I've read the whole 50 pages documents and again, while I do understand its benefits I'm completely left off as on translating this to code, for the very few samples I've seen unfortunately I couldn't find any hint on where I could start digging on and eventually get something up ... I guess that would solve stability of a multi-points hovering I previously experienced; for now I just stuck to the unique hover point (ship nose) approach, which works relatively well.

That lays out my physics programming abilities -> zero :g

Unfortunately when it comes out to applying concepts in code there is little resource on the web, or I missed it.

But I haven't abandoned !!! Up to now I've been able to overcome issues one by one though it takes quite some time so it's a bit heartening. I started splitting things up and refining things as much as possible, eventually over time an expert such as @Xpand might come in and give me a hand :D hope he succeeded in his exams :+

BeRo
5th July 2015, 08:16 AM
The drag-related topic if I'm correct would require writing physics from scratch, right ? If yes then it is beyond my competence at all as I can't even get a simple formula to code :brickwall


No you don't need to do it. You must set just the physics engine own drag to zero, and then for every time step as first step:


Get the current world space linear velocity of the current rigid body
Transform the world space linear velocity into local body space
Calculate the drag force vector with the drag equation formula Fd = 0.5 * p * u² * Cd * A on basis of this local body space linear velocity
Transform the local body space drag force vector into world space back
Apply the now world space drag force to the rigid body


For example, in my own physics engine called Kraft the code (where x is side, y is up, z is forward) looks like this:



const FluidMassDensity = 1.29; // Air density in kg/m³
DragCoefficient : TKraftVector3 = (x : 0.01; y : 0.005; z : 0.005);
ReferenceArea : TKraftVector3 = (x : 1.5; // Side area in m²
y : 1.5; // Top-view area in m²
z : 1.5); // Frontal area in m²

procedure DragEquation;
var LocalFlowVelocity, LocalFlowVelocitySignedSquared, DragForce : TKraftVector3;
begin
// Code for the drag equation formula: Fd = 0.5 * p * u² * Cd * A (is actually dimensionless, but it is applied dimension-axis-wise here in this case)
LocalFlowVelocity := Vector3TermMatrixMulTransposedBasis(PhysicsRigidBo dy.LinearVelocity, PhysicsRigidBody.WorldTransform);
LocalFlowVelocitySignedSquared.x := LocalFlowVelocity.x * abs(LocalFlowVelocity.x);
LocalFlowVelocitySignedSquared.y := LocalFlowVelocity.y * abs(LocalFlowVelocity.y);
LocalFlowVelocitySignedSquared.z := LocalFlowVelocity.z * abs(LocalFlowVelocity.z);
DragForce := Vector3ScalarMul(Vector3Mul(LocalFlowVelocitySigne dSquared, Vector3Mul(DragCoefficient, ReferenceArea)), -(0.5 * FluidMassDensity));
PhysicsRigidBody.AddBodyForce(DragForce, kfmAcceleration); // incl. back-transform from local body space into world space
// so it equals to: PhysicsRigidBody.AddWorldForce(Vector3TermMatrixMu lBasis(PhysicsRigidBody.LinearVelocity, PhysicsRigidBody.WorldTransform), kfmAcceleration);
end;

// Vector3TermMatrixMulBasis is a vector-matrix-multiplication of a 3D vector and the 3x3 sub-basis-matrix (rotation part) of a 4x4 matrix
// Vector3TermMatrixMulTransposedBasis is a vector-matrix-multiplication of a 3D vector and the transposed 3x3 sub-basis-matrix (rotation part) of a 4x4 matrix (faster than to inverse the matrix first, but it will work only for normalized orthogonal matrices without scaling (so rotation+translation only))




BTW why do suggest a different drag for forward, is it for coping with high speeds ?


Because the handling of the ship will be then more natural, especially the acceleration and braking, without affecting steering+rolling and pitch.

Xpand
5th July 2015, 10:21 AM
BTW why do suggest a different drag for forward, is it for coping with high speeds ?

Because aerodynamic drag changes with the cross section of your ship that the airflow sees. When you're moving straight you're presenting the most aerodynamic part of your ship to the wind, but when you turn/drift you start presenting a less aerodynamic section (the ship's side) and that increases the drag, reducing the ship's speed in that direction. That helps with handling as it stops your ship from drifting sideways a lot. Although you're going to have to exaggerate the effect of aerodynamic drag a bit to get noticeable effects in a short distance.
For example: A ship turning 90 degrees:
I only plotted one axis of the drag vector to understand how its components work. In reality the whole vector would be aligned opposite to the velocity vector.
http://i.imgur.com/t7FDNSI.jpg
And so on until the velocity vector is pointing completely to the left of the image, which then the red drag component pretty much disappears.

aybe
5th July 2015, 07:54 PM
@BeRo : thanks, I've been trying to apply your code but there are a couple of things I've encountered :

What is ReferenceArea supposed to be, the dimensions of the ship ?

When I apply this code right before moving my ship and with the default value of DragCoefficient, it acts like being in the vacuum of space; I guess this is correct since they are low values. However I've tried to apply the same amount of drag I used to have (1.0f) and things start to fly instantly ! I guess there's something I've missed or I'm mis-using ...

I've checked multiple times whether I'm calling the right functions in Unity (http://docs.unity3d.com/ScriptReference/Rigidbody.html) compared to your code and I guess I do but here is it anyway:



public Vector3 DragCoefficient = new Vector3(0.01f, 0.005f, 0.005f);

void UpdateDrag()
{
var rigidBody = GetComponent<Rigidbody>();
rigidBody.drag = 0;

var fluidMassDensity = 1.29f;
var dragCoefficient = DragCoefficient;
var referenceArea = new Vector3(1.5f, 1.5f, 1.5f);

var localVelocity = transform.InverseTransformDirection(rigidBody.velo city);
var localVelocitySignedSquared = new Vector3(
localVelocity.x * Mathf.Abs(localVelocity.x),
localVelocity.y * Mathf.Abs(localVelocity.y),
localVelocity.z * Mathf.Abs(localVelocity.z));
var dragForce =
Vector3.Scale(localVelocitySignedSquared,
Vector3.Scale(dragCoefficient, referenceArea))
* -(0.5f - fluidMassDensity);
rigidBody.AddRelativeForce(dragForce, ForceMode.Acceleration);
}


@Xpand thanks for the nice drawing, it makes things even more clear !

BeRo
5th July 2015, 08:36 PM
@BeRoWhat is ReferenceArea supposed to be, the dimensions of the ship ?

The reference area is in the most cases the to 2D projected area of a object to a axis view.

There are several ways to calculate the area per side (from top view, front view and side view) of your ship.


This first damn simple but not so exact way is to simply measure the projected 2D area height multiplied by the projected 2D area width and then take 85% of it. A = (width * height) * 0.85
A other still simple way is to overlay a grid over the projected 2D area, where you determine the area of one grid square cell by counting the number of grid square cells in a given measurement (height or width). Once you've determined the area of one grid square cell, you just need to count all the grid square cells touching the ship and keep track of whole and half grid square cells to get the total frontal area.
A other more exact way is to calculate the 2D polygon area of the to-2D-polygon-converted 2D projected area of a side of your ship. The to-2D-a-top/front/side-view-projected triangles can merged to 2D-polygons for example with http://www.angusj.com/delphi/clipper.php which exists also for C#, and then calculate the area of these 2D polygons...
... or you can do also just the more simple way (when you're lazy :-) ), where you calculate just the area of the 2D projected triangles itself and then sum these to a reference area value for a side/front/top-view, but this more lazy way is not more exact then, because of overlapped and intersected triangles.
and there are many more another ways....


So there isn’t just one way of doing it :-)

And you should play also with the DragCoefficient values with the trial-and-error method, since these are also not always universally for everywhere valid respectively suitable.

For more good informations you can read https://en.wikipedia.org/wiki/Drag_coefficient.

aybe
5th July 2015, 10:03 PM
Okay it's behaving properly now ! I was subtracting while you were multiplying the fluid mass density :clap

For the time being I'm using the coefficient of the Pac-car II (https://en.wikipedia.org/wiki/Pac-car_II) :g that is in https://en.wikipedia.org/wiki/Drag_coefficient ... unless I properly understand these 2 pages you've sent (hopefully soon). I understand the 'reference area' concept but I still need to compute it for my ship model.

The ship handling is effectively different now !

And what about angular drag, should the same formula be applied to it as well ? (I've left mine to 5.0f otherwise it never stops turning)

Also, regarding the soft constraint you were talking about, there is a spring joint (http://docs.unity3d.com/Manual/class-SpringJoint.html) which I've tried in Unity and while it roughly does the same task I couldn't find a way to move the anchor point in the track. So I had some 'free movement' but I was stuck to a certain position in the track. There is also a configurable joint (http://docs.unity3d.com/Manual/class-ConfigurableJoint.html) that might do the job but it's way more complex so not for today ...

thanks :D

aybe
6th July 2015, 01:58 AM
Can you confirm that this is (one of) the correct way to do it ?

Basically I get the percentage of white pixels for each side, then multiply according real mesh size, finally I scale down according my transform which is 1/1000th.

Top
9540

Front
9539

Side
9541



Top (X/Z)
image size : 396 * 903 (357588 pixels)
ship size : 169681 pixels
percentage : 0.47451536405024777117800373614327

Front (X/Y)
398 * 182 (72436)
12919
0.17835054392843337566955657407919

Side (Z/Y)
906 * 180 (163080)
65725 pixels
0.40302305616875153298994358597008

Mesh size (original units)
366, 166, 832

Results (original units)
Top = 144,495.62253766904929695627370046 = (366 * 832) * (169681 / 357588)
Front = 10,835.865646915898172179579214755
Side = 55,662.3203335786117243070885455

Results (my simulation is scaled to 1/1000th)
Reference Area:
144.49562253766904929695627370046
10.835865646915898172179579214755
55.6623203335786117243070885455


Note: for people interested in reusing this, all ships have the exact same mesh in WO1.

The feeling is as follows now, I can overcome some turns whereas previously I could not and I clearly gained some control for the torque. I guess this is the desired effect, right ?

thanks !!!

Xpand
6th July 2015, 07:21 AM
Also for added control you could multiply each of the areas by the cosine of the angle between their normals and the ship's velocity vector (Check vector dot product to find the angle). That way you'll take into account how much of the ship is facing the wind at any given angle.

BeRo
6th July 2015, 04:26 PM
And what about angular drag, should the same formula be applied to it as well ? (I've left mine to 5.0f otherwise it never stops turning)

This is my current research area :)

Because in the real world and in a perfect/better simulation the same drag equation applies indirectly also to the angular drag by AddForceAtPosition in the widest sense of the word, but to these force offset positions to calculate it in a reasonably correct way, there must first be an appropriate equation formula found, which at least I do not know (yet).

aybe
6th July 2015, 06:30 PM
@Xpand

It took me nearly 2 hours to figure out that the vector had to be normalized :g

Yet I'm not entirely sure,

Is it correct that components in 'reference area' should represent 'top', 'front' and 'side' ?
And that your formula should use 'right', 'up' and 'forward' like below ?



referenceArea = Vector3.Scale(referenceArea,
new Vector3(
Mathf.Cos(Vector3.Dot(localVelocity.normalized, Vector3.right)),
Mathf.Cos(Vector3.Dot(localVelocity.normalized, Vector3.up)),
Mathf.Cos(Vector3.Dot(localVelocity.normalized, Vector3.forward)))
);


I guess I implemented it properly because it's not going berserk as in my first trial, but honestly I can't really feel the difference. In what this formula is supposed to help in, get more control ?

EDIT: I do see some changes actually, previously I did lose some max. velocity and now it is back as usual !

thanks !

@BeRo

I can only wish you good luck, my searches on the topic haven't really brought anything that might be of interest to you:clap

thank you !

aybe
9th July 2015, 03:30 AM
Hi guys !

I would like to thank you for those 2 great tips,
few days have passed and it is clear that simulation just got better :+ :+ :+

I have a few questions if you could give me some hints :g :

Do you have some pseudo-code about soft-constraints for keeping ship on track ?

or did I miss something in your sayings ?

How do you detect the closest section to ship at any time ?

I used a naive method for finding it, it works most of the time. But when jumping, section below is seen as the next one while I'm expecting the one facing the ship.

I crafted 3 fixes which work well individually, I yet have to combine them to see whether it'll do:
- increase resolution sections' curve with more points and evenly spaced, everywhere
- detect next by accounting whether they are facing the ship, as the user naturally tries to face it
- do the detection again using the above 2 helpers

Picture of the problem:

9544

- magenta lines/spheres : original data
- yellow lines/cubes : refined data

But you might wonder why I'm doing this ? I do this mainly for knowing how to align my ship (cyan line)

How do you handle collisions with walls/ground ?

Current I use a wall normal rotated at 45 degrees (green line) to know the bump direction. It works really well though the impulse is a bit too intense.

9545

For the ground I do calculate the ship Y velocity, negate it and multiply it by 2.33, it works moderately well.

But is there a more appropriate way to handle them ?

How do you commonly apply acceleration/deceleration to a ship ?

Previously I tried method in AGR2280 but did not like it much in the sense that it 'removes' force when at max speed.

So I decided to sketch my own which doesn't do that, it works quite well but I was wondering whether there's a proper way in the same vein than your 2 former tips :D

Also, do you know what 'value' is the red meter in the original game, is it RPM of the ship and would this need to be modeled as well ?

Here's a video below showing the meter in question (at 49 seconds):


https://www.youtube.com/watch?v=ukOU1FpKTOM


thank you very much for your time :clap :clap :clap

BeRo
9th July 2015, 05:33 AM
Do you have some pseudo-code about soft-constraints for keeping ship on track ?

The used physics engine (PhysX in your case with Unity) must either support these already itself or have a "low-level" generic constraint type, where you can implement also the solver code parts of it yourself. But if you are interested in it anyway, how it looks as code, look into the Box2D source code, since the most of the Box2D joints/constraints are implemented as soft constraints, but there just in the 2D case.


How do you detect the closest section to ship at any time ?

I'm doing closest-line-segment-to-a-point-search (line segments from previous to next section points, also to next junction section points, and also from these back to the main route path section points) and closest-point-on-line-segment-to-point-calculation, so as a hint: avoid closest-point-to-point searching.


How do you handle collisions with walls/ground ?

I let it currently simply the (my own) physics engine itself do it, without any manual on-collision-event-hooks. But i'm adding, while loading, new invisible upright wall collision geometry with the ground track faces and the section points as reference input data (with best-boundary-edge-raytracing/raycasting) for the invisible upright walls.


How do you commonly apply acceleration/deceleration to a ship ?

I do:

At acceleration:


PhysicsRigidBody.AddForce(PhysicsRigidBody.Forward Vector * EngineAccelerationForce);

At brake:


PhysicsRigidBody.AddForce(PhysicsRigidBody.Forward Vector * (dot(PhysicsRigidBody.Velocity, PhysicsRigidBody.ForwardVector) > 0.0) ? EngineBrakeForce : 0.0));

without any maximal speed limiting, since the drag equation done the physically correct and natural maximal speed limiting already, when it is implemented correctly.

And deceleration do the drag equation already as free bonus, so don't write extra deceleration code for it.

My game physics code at rewipeout and Supraleiter is so far mostly completely free from hacks including hardcoded limits etc. I just implemented so far everything much as physically correctly as possible. At least for me, it has been easier than to use more hacky solutions, but that does not have apply to everyone, so try for yourself what is the best for themselves, is the best way anyway.


Also, do you know what 'value' is the red meter in the original game, is it RPM of the ship and would this need to be modeled as well ?

Nope, but it is on my long to-do list by dumping the RAM content from a modified PSX emulator from two frames for to calculating


FrameVelocity = NewShipPosition - LastShipPosition

but so far I had no time for to do it.

aybe
9th July 2015, 08:58 PM
you rock :+ :+ :+

going to code and post back my results ...

thanks !!!

EDIT:

about that red meter, I thought about RPM/acceleration because while testing AGR2280, their 'accel' var effectively does that, it raises quicker than velocity.

about the PSX emulator, I guess you already know psxjin (https://code.google.com/p/psxjin/) ? @tigrou suggested it earlier but unfortunately it's quite unstable and couldn't replicate his auto-pilot experiment (http://www.wipeoutzone.com/forum/showthread.php?9972-Wipeout-2097-autopilot-game) using TRS for WOXL.

aybe
17th July 2015, 01:14 AM
Hi guys !!!

Quick update + a video,


https://www.youtube.com/watch?v=R9vOg1y8KWM

@BeRo

Closest section algorithm: works really well, current section on the video is green, next is red. The magenta line is the closest point in current section segment to the ship, which I use for the constraint.

Constraint: it was not easy to get the ConfigurableJoint (http://docs.unity3d.com/Manual/class-ConfigurableJoint.html) configured for this particular scenario but it's promising as you can see on the video ! I still need to fine-tune it as well as enabling track collision but the substance is here :D Also it seems to cope well with that feedback-loop-feeding approach, basically the joint is on the track and attached to the ship; but the ship 'moves' the anchor in the track.

PS: I did some research on that red meter and sketched a relatively faithful one : I accelerate linearly a normalized value, then I ease it with an exponential ease with a value of 0.25, it's mostly that ...


@all

Do you guys have any extra tips regarding joints and this particular configuration ? or anything else :g

thanks :+ :+ :+

aybe
17th July 2015, 12:59 PM
Another video, with solid hovering now !


https://www.youtube.com/watch?v=gCpLWTgoYPk

The weird behavior has been fixed and the ship hovers properly as you'll see.

It's incredible how this constraints added realism and at the same time improved the gameplay :)

tigrou
17th July 2015, 08:10 PM
I think we start getting something interesting :clap I really like the way physics behaves now (while there is still room for improvement of course)

What still seems to be strange is how it handles jump, it looks like ship is attached to a spring (glued to the floor), rather than falling because of gravity.

Also : is collision against track disabled for debugging purposes only or because you totally bypass unity physics and need to implement it yourself (eg : by ray casting and such) ?

aybe
17th July 2015, 08:32 PM
Yes, I still need to address that stickiness issue ! Was looking for a convincing configuration before attacking the rest and I guess it's sufficient for now.

Collisions are disabled and I'm simply passing through. I still don't know which of OnCollision or OnTrigger to use, the 1st one is safe in the sense things never pass through BUT it does apply some physics, the second is simply an event so I'm free to do anything but up to now I've been getting the issue of force being applied in the wrong direction on subsequent call, i.e. object is swallowed by the wall instead of being pushed away.

EDIT : basically ray cast now is used only when detecting the first section and I do use all the physics of Unity except for the drag equation given by @BeRo.

I guess we'll know pretty soon by now, that constraint solved a lot of issues by itself so it's definitely a plus even though that issue you mentioned needs to be addressed now.

aybe
18th July 2015, 01:15 AM
I need your assistance, guys ! :g

I've been able to give room for ship's Y-axis by lowering the joint drive spring on that axis -> the ship effectively does not stick to section when on air now ! But, now the ships go below the hover point and over some (long) period of time it will reach again the hover position.

So I decided to enable collision again to try overcome this problem. I've tried OnCollision first but it completely breaks the physics, ship is stiff, looks to the top etc ... it's totally broken. Ok ... I then decided to use OnTrigger which simply notifies me of a collision and with that poor man's rebound :



var yVelocity = Mathf.Abs(transform.InverseTransformDirection(_shi pBody.velocity).y);
_shipBody.AddRelativeForce(_shipBody.transform.up * yVelocity * 2.333f, ForceMode.Impulse);


It is as unreliable as things can be :g, it will work on a flat surface though I have to lower that constant but not at all on the rest of the track. The ship will still go below the hover point but as soon as the constraint levels it up to the track, it is sent into space !:clap :clap :clap

To sum it up, OnCollision will detect and fix the collision but basically you have (pretty much) no control on it and it introduces undesired behavior; OnTrigger is a simple notification but I can't detect most (fast) collisions and my rebound approach is obviously flawed.

Do you know of an approach to overcome this problem ?

thank you :+ :+ :+

miljoneir
26th July 2015, 04:20 PM
Semi-off topic:

Why does the original wipeout have 15 track folders? One track folder per circuit for each race class?

aybe
26th July 2015, 06:43 PM
Hi !

I'm a bit lazy so I'll just post the code that infers track folders :g



public static string GetTrackFolderName(TrackNameWipeout name, TrackClassWipeout @class)
{
if (name == TrackNameWipeout.AltimaVII && @class == TrackClassWipeout.Venom) return "TRACK02";
if (name == TrackNameWipeout.AltimaVII && @class == TrackClassWipeout.Rapier) return "TRACK03";
if (name == TrackNameWipeout.KarbonisV && @class == TrackClassWipeout.Venom) return "TRACK04";
if (name == TrackNameWipeout.KarbonisV && @class == TrackClassWipeout.Rapier) return "TRACK05";
if (name == TrackNameWipeout.Terramax && @class == TrackClassWipeout.Venom) return "TRACK01";
if (name == TrackNameWipeout.Terramax && @class == TrackClassWipeout.Rapier) return "TRACK06";
if (name == TrackNameWipeout.Korodera && @class == TrackClassWipeout.Venom) return "TRACK12";
if (name == TrackNameWipeout.Korodera && @class == TrackClassWipeout.Rapier) return "TRACK07";
if (name == TrackNameWipeout.ArridosIV && @class == TrackClassWipeout.Venom) return "TRACK08";
if (name == TrackNameWipeout.ArridosIV && @class == TrackClassWipeout.Rapier) return "TRACK11";
if (name == TrackNameWipeout.Silverstream && @class == TrackClassWipeout.Venom) return "TRACK09";
if (name == TrackNameWipeout.Silverstream && @class == TrackClassWipeout.Rapier) return "TRACK13";
if (name == TrackNameWipeout.Firestar && @class == TrackClassWipeout.Venom) return "TRACK10";
if (name == TrackNameWipeout.Firestar && @class == TrackClassWipeout.Rapier) return "TRACK14";
if (name == TrackNameWipeout.Track15) return "TRACK15";
throw new ArgumentOutOfRangeException();
}


IIRC Track15 is the beta of Arridos or Terramax ...

aybe
1st August 2015, 09:12 PM
Hi guys, new video with updated physics :D


https://www.youtube.com/watch?v=SPn4LnSJY2o

See the website for the changelog, basically now the ship uses a ConfigurableJoint (http://docs.unity3d.com/Manual/class-ConfigurableJoint.html) and section tracking is much more robust (thanks @BeRo), things are much more realistic and we're getting a step closer :D

By the way, what do you think about the web site ? http://www.wxx-rebirth.com/

Thanks !

Xpand
1st August 2015, 10:41 PM
Wow that looks pretty close to the original without the ugly (but necessary) approximations they had to use!
You just need to make the ship actually collide with the track.

aybe
1st August 2015, 11:07 PM
Yes it surprisingly does,

Actually I've been trying a couple of things which didn't work until simply trying the following,

put the anchor above just like this :

9609

So basically my previous code was already good, just had to offset the thing a bit :D

For the collision, do you have a rough idea on what formula/concept to look at ? (main idea would be using a home version like for the drag)

Thanks !!!

Xpand
2nd August 2015, 11:21 AM
Just use the mesh collider in Unity. No point in complicating that one.

A more "in-house" way would be detecting which triangle of the track's mesh the ship is sitting on and then calculating the distance from the collider model vertices to the surface of that triangle.

To detect the triangle you would have to use barycentric coordinates, which are basically "where inside a triangle is a point". https://en.wikipedia.org/wiki/Barycentric_coordinate_system
Look at the calculation for the lambdas in that wikipedia page. That's how you'll find out if a vertex is inside a triangle. This only works in 2D (horizontal plane in our case), so overlapping track portions (bridges, jumps, etc) would need some sort of height condition to ignore the lower track section when the ship went over it.
Here are some pics from my physics engine doing exactly that:
http://i.imgur.com/EX6EjMN.png
http://i.imgur.com/61YFREK.png
http://i.imgur.com/lML1mmv.png

A point is inside a triangle when lambda1+lambda2<1 and lambda1>=0 and lambda2>=0
You make a loop to go through all of the TRACK's surface triangles and detect the one for which the condition above is true and break out of the loop. Then you can repeat that loop every frame or you can judge how much the ship moved and then find the new triangle using the loop, though faster it is more prone to bugs since you can easily misjudge the player's motion and fail to find the triangle correctly.

To calculate the height of the collider point above the triangle you'll need to calculate the plane equation of that detected triangle. Just look at how to calculate the plane equation from 3 vertices. http://tutorial.math.lamar.edu/Classes/CalcIII/EqnsOfPlanes.aspx

you'll get an equation like this: A*(x)+B*(y)+C*(z)=D
To get the height of the track in a (px,py) point just solve that equation for track_z= -[D-A*(px)-B*(py)]/C, where px and py are the collision point's coordinates on the horizontal plane (considering z axis as vertical)

Then your height is (pz-track_z)

If your height is zero or below, then you have a collision. There are also methods to improve your collision detection, called a posteriori and a priori collision detection.

This is also useful to align the ship with the track since the A,B,C constants are the components for the plane's (triangle) normal, although that stuff should already be included with the mesh data.

aybe
2nd August 2015, 01:51 PM
Yes, I'd rather use OnCollision since it's in Unity and features continuous collision, but ... I've been developing the thing using OnTrigger and now when I go back to OnCollision the ships abruptly looks down ... The old hovering alignment works if I make it 100 times more powerful but then the ship is incredibly stiff :cowboy

Anyway, it's obsolete so I must code something new. Been thinking and I guess I know the cause : joint orientation. I'll see if I can make it play nicely with user pitch up/down and the torque with .TargetRotation property. Hopefully if it works then the problem will be fixed at this point.

If not then, that was my first question regarding the formula for bouncing with OnTrigger, been using this cheap algo :g but it's really bad:


var yVelocity = Mathf.Abs(transform.InverseTransformDirection(_shi pBody.velocity).y);
_shipBody.AddRelativeForce(_shipBody.transform.up * yVelocity * 2.333f, ForceMode.Impulse);

Otherwise regarding your tips:
- barycenter : OK
- plane : OK
- triangle search : OK (I guess since I can track the ship's section quite well now)
- other things : I guess OK

So I'll definitely dig into this approach if all else fails.

Coming back to post my results !

Thanks :D

Xpand
2nd August 2015, 06:05 PM
For the correct bounce you can just invert the velocity component along the triangle's normal (you need to project your velocity vector onto the triangle's normal (https://en.wikipedia.org/wiki/Vector_projection)) (the triangle where the ship hit the ground).

https://upload.wikimedia.org/wikipedia/commons/9/98/Projection_and_rejection.png
In terms of projection, if "a" is your velocity vector and "b" your triangle normal, "a1" will be the velocity component along the triangle normal.

However, to simplify things you can just do what you're doing by just using the vertical component of your velocity (y in your case). Although in steep hills the ship will behave a bit odd.

You do like: velocity=-velocity*damp_factor. The damp factor is a number between 0 and 1, it defines the bounciness of the ship when it hits. A damp factor of 1 means the ship will bounce back up with the same velocity it hit the ground, 0 means it won't bounce, it'll just hit and stay there.

If you chooe to go with the projection method you then have to "move back" and rebuild the velocity vector with the new inverted component, you can do that by adding the modified component "a1" to the other component "a2".

aybe
2nd August 2015, 11:57 PM
Excellent, going to study that thoroughly :D

Thanks :+ :+ :+

aybe
24th September 2015, 12:54 AM
Hi guys ! It's been a while ... I haven't abandoned the project and plan to get back to work on it ASAP :p :p :p

How are you guys doing ? Xpand did you get your exam/graduation ?

Last status was :


https://www.youtube.com/watch?v=SPn4LnSJY2o

Basically the constraint needs to be wrote again as for the life of me I've never figured out why when switching from Trigger to Collider makes the ship invariably pitch up ... and surprisingly the old hover method is unaffected.

My plan:

- get this fixed
- get some AI and weapons up
- then the rest :D

tigrou
11th October 2015, 10:49 AM
@Aybe : it's better each iteration, although it does not really feel like the real game.

Have you considered asking help to a professional game developer ? I'm pretty sure the physics as it is now does not need a lot to become really good.
I would like to help but physics is not my cup of tea.

Or, you can put physics on aside and spent time on the rest (adding scene objects, skybox, weapons, ...)

This should not be too hard since all of this has already been documented and I'm confident it should not be a problem for you.

aybe
11th October 2015, 06:44 PM
Hi !

It is pretty close to the original feeling, look at how the ship behaves when jumping a section; it's pretty much the same :D. Remember, it's the 2 months old vid. here, so without any fixes such as collisions and fine tuning the constraint. I think it's the the right design (constraint on top) but it needs to be fine tuned quite a bit.

Regarding pro help I know nobody in the game industry for asking ... I guess I found the best out of web resources, best tips coming from this forum in fact :p. I've started working back on the project so expect cool news over the next 2 weeks, hopefully. Now I'm helping out bigsnake on Ballistic NG, an input manager that'll end on mine as well and looking to share my ship loading facility as per his request. I might very well get some help from him later at some point ! (haven't heard from BeRo (supraleiter) for quite a while btw)

What I'd like is to nail this thing down to the best I can, then proceed to AI/enemies (I do have the full track scene + skybox btw). I takes quite a bit to get back on feet when you haven't worked on the thing for 2 months, slowly getting back to it by helping BNG through the input mapper and code sharing is a good thing IMO. (what you're seeing consists of nearly +300 classes :bomb, it's definitely gonna take me a few days to be comfortable again with the code base :sonar)

Cipher
13th October 2015, 07:11 PM
Have you tried setting hard caps on the pitch calculator? if(m_Pitch < PI_DIV8 && m_Pitch > -PI_DIV8) { *pitch code here*}
Because honestly, you could never pitch that high even if you wanted to, nor that low, π divided by 8 might still be too much in fact the calculations should probably be based on last known collision normal as well so you don't have that weird angle with the track at certain parts

Unless that's what you meant with "constraint on top" :p

And hehe, i know what you mean with coming back to old code, it's always a "scratch your head"- kinda moment xD
Good luck!! Looks good though :)

Cipher

aybe
13th October 2015, 07:57 PM
Actually I have an 'angle' caps but it's pretty high for the sake of testing :p

I found it quite pleasant while playing even if it's a bit excessive; the real problem I do have in fact is that all this tightly intertwined : pitch, constraint, collision. Pitch is influenced by the old hover code as well as the constraint, but the former one does not play nice at all when enabling colliders for collision (which is the next route as basically I can't get a reliable homemade collision detection (Unity's one always works no matter the speed)).

So it needs a complete rewrite for which I'll have to split myself in two for it as there are multiple and interdependent parts to rewrite :bomb (still scared a bit by it to be honest :D)

And by constraint I mean that : http://www.wipeoutzone.com/forum/showthread.php?9959-Reverse-engineering-of-Wipeout&p=244479#post244479 this is how I'm keeping the ship in place. On the next video, I'll enable gizmos and you'll get a pretty good picture of how that (magic) constraint works (thanks to BeRo) with all the debug geometry.

Thanks :+

Cipher
13th October 2015, 08:25 PM
I understand the constraint on top now and it's an interesting approach i must admit ^^

I think you should go with raycasting for manually overriding unity's collision with your current purpose, as it relies on just vectors and matrices which are exactly what you're dealing with
Do you want me to shoot you over 2 documents on collision in games and their formulas? (they're a bit schematically represented, but i think they should be readable if you have enough math knowledge)

I'm actually surprised you have no troubles with the default unity collisions, back when our team made a unity platformer we encountered a couple of bugs in unity itself (with collision), we mailed them about it and they confirmed it saying they would patch it, but we couldn't wait for that because of our deadline and had to write our own collision :p (they did eventually patch it though XD)

Cipher

aybe
14th October 2015, 06:19 AM
Well, anything that can be helpful is really welcome ! So yes, feel free to post them :+

For the homemade collision detection, the problem I have is that at (even not so) high speeds, the ship passes through the track. Now there's a thing I haven't yet tried but others suggested : to put a thick and invisible floor under the track to alleviate that problem. Up to now my philosophy is as follows : to try as much as possible to use OOB features of Unity and if only really needed work out my own.

Regarding your collision issue, from memory I haven't used 'defaults' as they are not foolproof. Rather I've used this suggestion (http://docs.unity3d.com/ScriptReference/Rigidbody-collisionDetectionMode.html) and it made things inpenetrable. Also it's very possible that I've already benefited of that bug fix since I did it relatively recently ...

Cipher
14th October 2015, 10:23 AM
Check your PMs ;)

There's 2 ways to solve collision problems due to update interval, 1 is to thicken the collision walls, the other is to increase the physics update interval (you can do that in unity as well) and well, there's kind of another way, which is to separate collision from physics, but that's rarely done :p
And yes, the problem had to do with RigidBody collisions IIRC, it's been a while ^^

Cipher

aybe
15th October 2015, 07:54 AM
Very cool, going to try digest these very interesting docs :pirate

Thanks :+:+:+

aybe
11th November 2015, 10:04 PM
Hi! Here are the latest discoveries from game files :pirate

9790

9791

9792

9793

about a dozen new polygons have been discovered, more details here:

https://github.com/phoboslab/wipeout/issues/21
https://github.com/phoboslab/wipeout/issues/23
https://github.com/phoboslab/wipeout/issues/24
https://github.com/phoboslab/wipeout/issues/25

do you guys know where in the game the 3rd model can be seen ?

Xpand
15th November 2015, 11:41 AM
What do you mean by camera paths? Is it the animation of the rescue drones around the track, or the game's camera motion, because I'm pretty sure the game camera's motion is calculated in real time.

vincoof
15th November 2015, 09:40 PM
I don’t remember if WO1 used those, but sometimes you have a camera lurking around the map before the race starts. Had I to guess, I’d say the camera path is meant for this. It’s been a long time tho (20 years more or less :p) so I may imagine things.

bigsnake
18th November 2015, 11:01 AM
I wonder if those paths are even used at all, like Xpand said the camera for chasing the ship is most likely calculated at runtime.

WO1 doesn't have an overview camera for the tracks, the game dumps you straight into the very start of the race. Maybe that was to be a feature though. Aybe, have you tried rendering the path with the track? Maybe that will help make what they are used for more apparent.

aybe
20th December 2015, 05:49 AM
Hi !

Sorry for the late reply, been pretty busy and forgot actually.

For the paths there's a strong possibility these are the roads the rescue ships are wandering in, we'll know for sure once they're rendered !

Other than that ...

I advanced somewhat on WXX-Rebirth (though not as much as I wanted). I should soon be done with that level editor and after that, scenes should magically appear: tracks with animated scenery/billboards, illuminated objects in the various menus etc ... Basically it's a custom editor window in Unity where I build scenes, add behaviors and so on, then the resulting content is produced as an XML file that gets consumed by the game :blarg

:rock

It seems that we have reached the point where all of the game models are readable by now, since every PRM asset used in the game are now loading and rendering properly, including previously undecipherable models such as classes logos. Discovered nearly a dozen new polygons -> https://github.com/phoboslab/wipeout/issues/25 (the colors are indeed correct, shots are too bright because Unity lighting is enabled)

I also made significant progress on the installer part which will not only install the game but also pre-process many things such as videos, audio files, and billboards which by now has become mandatory and couldn't be done entirely in Unity as invoking some external libs somehow randomly crashes/hangs it.

Actually I've been pretty busy with reading files directly from the CDROM actually, including special files in a XA Mode2 Form2 (videos).

C++ has now joined the party since a couple of libs are only available in this language and I do not wish nor have the time to re-invent the wheel using C# :paperbag

In short, the final form of the game will be really user-friendly : insert your Wipeout CDs and wait for installation and voila !

Sooner or later I will ask the mods whether I can open a dedicated thread for WXX-Rebirth :hyper

( and I'll try to post regular updates by then :D )

wirehang
23rd December 2015, 11:01 AM
Awesome work! Found my old login just so I could to say that :)

aybe
23rd December 2015, 09:48 PM
Thanks :p

Varsh
26th December 2015, 10:19 PM
This is amazing stuff! All of the programming discussion has gone right over my head. :lol:

Are you going to be continuing this? It would be interesting to try out completely different tracks with your physics. :)

aybe
27th December 2015, 05:27 AM
I am actively working on it, right now :pirate

Your suggestion is something that I do have on schedule, though it's not likely to happen soon. Currently the game strictly works against Wipeout and Wipeout XL file formats (which are identical), but since I do plan to attack Wipeout 3 file formats once I'm done; the representation of a track/scene will have to become generic which in turn will allow to throw any valid level at it. This is not really difficult per se but not a priority for now.

And while I'm on it, here's a quick update of what's been done since my last post:

The reading of the CDROM content, (lost an arm in the process btw :brickwall)

I was previously using 'libcdio' which is a well known library but simply couldn't afford it anymore : lots of time wasted in the C++ to C# bridge along all its peculiarities.

So I've just decided to do everything by myself, which means :

talking directly to a CDROM drive using IOCTL and SCSI MMC commands (this method will always work as previous method would work only against real drives, not Daemon Tools and such which I heavily use and guess many users do as well)
implementation of the CD-ROM XA and ISO9660 standards, i.e. getting from the bits in a CDROM to concrete files : regular files as well XA files (MDEC movies)


Needless to say that it was painful to go through the standards ECMA 119/130 and SCSI MMC-3, nearly 1000 pages but it's finally here ! I'm about to be finished as I'm in the polishing phase.

Right after that I'll resume the work on the level editor and after that the next update you should get from me will be a video showing every levels of the game with all the features (animated scenery, billboards, lighting etc ...) I am really eager to work on this part as that low-level CD stuff was painful though it's quite interesting. Truth is I really want to put the emphasis on 'easy access' as I said before: run the installer, insert your Wipeout CD and press Next, wait a few seconds and you are ready to get your Wipeout fix !

I started that project in April 2015, we are now reaching 8 months of work, I expect this to not last longer than 12 months, or 1 year if you prefer (hopefully) => should be ready for spring season :D

EDIT

Bit of clarification, while some might underestimate this part, it actually became a necessity over time. While the reading of regular files from a CDROM as well as CDDA tracks is easily done, it is not the case for XA files as Windows will grant you with an Incorrect Function error. Also, there are certainly differences between editions of Wipeout in regards to the layout of files/tracks, but this won't be a problem with the current approach. Note that as I'm not that 'sadomasochist', the actual decoding part of MDEC movies to a format usable with Unity will be done with two great pieces of software: jPSXdec (https://kenai.com/projects/jpsxdec/pages/Home) and FFmpeg (https://www.ffmpeg.org/), the interpretation/transformation alone of an MDEC movie to Ogg Theora video from scratch would have taken centuries ...

Varsh
27th December 2015, 05:28 PM
Great to see that you're moving alongn with this quickly then. I saw your site and it looked like it hadn't been updated for ages so I thought that y ou might have stopped working on it, but I guess that there wasn't really anything to show as it was all just decoding stuff. :)

What format does Unity read model files, is it OBJ, FBX?

aybe
28th December 2015, 07:33 AM
Yes, the thing is I'd love to post some news but for what, as you said ? In the end people are waiting for real stuff ... so it looks like there isn't going to be much news released in between, there's definitely going to be a video as I said before, showing the whole game assets, then the next news will be a download link :D I will definitely make an HD introductory video when it's done and I'll look for some Wipeout guru for this one !

For Unity I guess it reads FBX, thing is I've never used that part at all for the project -> we cannot ship game data therefore transforming game data to models which implies shipping them is forbidden. Not sure it might have been easier though, actually there are few 'pros' in not using models but there are few 'cons' as well :p

While I'm on it here's a quick update:

I guess the CD stuff is hmm ... working well by now, need to test the whole procedure against Wipeout/Wipeout XL CDs. It turns out that while being XA-compliant, PSX CDs do not entirely follow the specs, what's supposed to be in a certain form is in another.

I guess that within the next 2 days I'll be able to resume work on the level editor ! :guitar

Varsh
29th December 2015, 03:49 PM
I've just downloaded and installed Unity, so I'm going to give the engine a bash and see how it works. Never used it before so it's going to feel really weird after being used to UDK and UE4 for many years. :dizzy

aybe
29th December 2015, 05:35 PM
It is pretty solid, maybe not as fully featured as UE but still good ... Actually been looking at UE and it's pretty intimidating with those blueprints and c++ :sonar

Other than that I'm finally done with that CD-related work for WXX-Rebirth !!! Everything works well, tested against real Wipeout CDs and got 100% success. It was tough to get to this but it's done now ! :cake

Probably gonna take a little break and refuel my batteries before resuming the work on the game itself :p

Varsh
29th December 2015, 06:45 PM
Sweet, great to hear! I don't blame you needing to recharge after all of that work, it was a lot. :D

wipetuga
17th April 2017, 10:55 AM
I created a post because I did not know this post.
My original post:

Http://www.wipeoutzone.com/forum/showthread.php?10324-Wipeout-1-and-2-models-needed-or-extractor-tools&p=250082#post250082

Is there a tool that extracts and exports the models and textures from wipeout 1 and 2?
I'm looking for original wipeout models 1 and 2.