Skip to content
View in the app

A better way to browse. Learn more.

ResHax

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
Help us keep the site running.

Colin McRae Rally 3 .STAG and .TAG model files

Featured Replies

  • Localization

I know there's been (hard-to-find) tools for .p3d and other formats but those were made for later games in the series. I need to get models from this game for a mod I am planning to make.

I've attached sample files for both characters and car model files, if it helps.

Auspod.7z Cars.7z

Solved by shak-otay

  • Supporter

Getting uvs from puma.tag is easy, the mesh looks a little bit strange. Need to check that...

edit: from rear, front and bottom it looks good, from the other 3 sides it's a mess. Maybe the destruction mesh. Single parts follow.

 

puma-tag.png

Edited by shak-otay

  • Author
  • Localization
31 minutes ago, shak-otay said:

Don't be too greedy.:classic_blink: Let's finish one thing first.

Hex2obj0.25b-Puma-fst_Sub_mesh.png

Sorry about that one mate, take your time.

  • Supporter

Do you think you can get the next sub mesh part using the car's top as a reference?

(As you may know I mostly feel finished somehow as soon as the first sub mesh parameters have been found.)

  • Author
  • Localization
19 minutes ago, shak-otay said:

Do you think you can get the next sub mesh part using the car's top as a reference?

(As you may know I mostly feel finished somehow as soon as the first sub mesh parameters have been found.)

I ought to have some experience with reading model formats tho.

Is it alright to see how the Colin and Nicky meshes stack up?

  • Supporter
23 minutes ago, huckleberrypie said:

Is it alright to see how the Colin and Nicky meshes stack up?

(? Can you rephrase that?)

The next vertex block is from 0x39ae0 to 0x3c990, results in

Hex2obj0.25b-puma_sub_mesh_2.png

  • Author
  • Localization
19 minutes ago, shak-otay said:

(? Can you rephrase that?)

The next vertex block is from 0x39ae0 to 0x3c990, results in

Hex2obj0.25b-puma_sub_mesh_2.png

I meant with the .STAG files in Auspod.zip.

  • Author
  • Localization
1 hour ago, shak-otay said:

x_h_nicky2.STAG is missing some faces.

Hex2obj0.25b-nicky.png

Wonder why tho.

  • Supporter
  • Solution

I fear we're all alone here - so you may bump as much as you want.:classic_blink:

You should ask specific question(s) if you want some progress.

Btw, the format is rather low poly thus the general interest is low, too, I guess.

  • Author
  • Localization
2 hours ago, shak-otay said:

I fear we're all alone here - so you may bump as much as you want.:classic_blink:

You should ask specific question(s) if you want some progress.

Btw, the format is rather low poly thus the general interest is low, too, I guess.

Sorry about that. I did get the model to show up using your tools tho so no worries.

Screenshot (741).png

Screenshot (742).png

OK, based on what you dug up with the file, faces are stored as tristrips in 16-bit words. Verts are the usual floats.

0x10 is apparently the submesh count, 0x9C is the face/index count and 0x80 is the vertex count. The lines I highlighted in offset 0x90 hold the addresses for both vertex and index buffers. I guess this should be straightforward enough for a Noesis script?

Screenshot (746).png

Screenshot (747).png

Edited by huckleberrypie

  • Supporter
8 hours ago, huckleberrypie said:

The lines I highlighted in offset 0x90 hold the addresses for both vertex and index buffers. I guess this should be straightforward enough for a Noesis script?

I wouldn't know why not. Just replace the constant values in the script, for example using

vertexCount = bs.readUInt()

in the correct place. Ignore the lines commented out by #.

#sample class
from inc_noesis import *

#indOffsArr = [0x1C00, 0x5100, 0x10100, 0x1B280, 0x26800, 0x31B00, 0x3CE80, 0x42280, 0x4DC00, 0x59800, 0x5D400, 0x69280, 0x74280]
matName = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]

def registerNoesisTypes():
   handle = noesis.register("CMR_Rally3", ".stag")
   noesis.setHandlerTypeCheck(handle, binModCheckType)
   noesis.setHandlerLoadModel(handle, binModLoadModel)
   #noesis.logPopup()

   return 1


def binModCheckType(data):
   td = NoeBitStream(data)
   return 1

class binFile:
         
   def __init__(self, bs):
      self.bs = bs

      self.texList  = []
      self.matList  = []
      self.boneList = []
      self.boneMap  = []
      self.offsetList = []
      self.meshOffsets = []
      self.materials = []

   def loadAll(self, bs):
      indexOffset = 0x1e084

      for j in range(0, 1):
        self.materials.append(j)
        #indexOffset = indOffsArr[j]
        #vertCount = bs.readUShort()
        #indexCount =  bs.readUShort()

        #bs.seek(8, NOESEEK_REL)
        bs.seek(indexOffset, NOESEEK_ABS)
        indexCount = 3910
        indBuff = bs.readBytes(indexCount*2)

        vertexOffset = 0x7bc0
        #vertexOffset = indexOffset + indexSize
        bs.seek(vertexOffset, NOESEEK_ABS)
        vertCount = 1522
        vSize = 60
        vertBuff = bs.readBytes(vSize * vertCount)
        rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, vSize, 0)

        #uvsOffset = vertexOffset + vertCount * 16
        #bs.seek(uvsOffset, NOESEEK_ABS)
        #UVBuff = bs.readBytes(vertCount * 6)
        #UVBuff = rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_HALFFLOAT, vSize, 12)
        rapi.rpgCommitTriangles(indBuff, noesis.RPGEODATA_USHORT, indexCount, noesis.RPGEO_TRIANGLE_STRIP)
        rapi.rpgSetMaterial(matName[j])
        print("indCnt: %d vertCnt: %d" %(indexCount, vertCount))
        #print("indexOff: 0x%x, cnt: %d, size: 0x%x,  vertOff: 0x%x, cnt: %d, uvsOff: 0x%x" %(indexOffset, indexCount, indexSize, vertexOffset, vertCount, uvsOffset))


def binModLoadModel(data, mdlList):
   ctx = rapi.rpgCreateContext()
   bin = binFile(NoeBitStream(data, NOE_LITTLEENDIAN))
   bin.loadAll(bin.bs)
   try:
      mdl = rapi.rpgConstructModel()
   except:
      mdl = NoeModel()
   mdl.setModelMaterials(NoeModelMaterials(bin.texList, bin.matList))
   mdlList.append(mdl); mdl.setBones(bin.boneList)   
   return 1

 

nicky2-stag.png

Edited by shak-otay

  • Author
  • Localization

Thanks mate, that's very much appreciated.

EDIT: Am I right to assume that the values in the hex offsets are three bytes each?

EDIT 2: Strange, the girl models don't seem to have the proper header values at the usual offsets lmao:

 

Screenshot (760).png

Edited by huckleberrypie

  • Supporter
6 hours ago, huckleberrypie said:

Thanks mate, that's very much appreciated.

EDIT: Am I right to assume that the values in the hex offsets are three bytes each?

Puh, you mean because of indexOffset = 0x1e084? That's meant to be 0x0001e084, so 4 bytes. But leading zeroes can be ignored in code. (The 0x stands for hexadecimal, btw.)

A "3 bytes" data type is against the "digital rules", I guess, everything is based on power 2 types in intel's universe at least, afaik.

edit: maybe I misunderstood because I see you had highlighted 4 bytes in one of your previous pictures.

Quote

EDIT 2: Strange, the girl models don't seem to have the proper header values at the usual offsets lmao:

As you may know I'm not a fan of deep data analysation. Almost everything I do depends on pure guesswork.:classic_blink:

There may be different types in this format. Is there other models that have a header similar to the girl's one?

Edited by shak-otay

  • Author
  • Localization
1 minute ago, shak-otay said:

Puh, you mean because of indexOffset = 0x1e084? That's meant to be 0x0001e084, so 4 bytes. But leading zeroes can be ignored in code. (The 0x stands for hexadecimal, btw.)

A "3 bytes" data type is against the "digital rules", I guess, everything is based on power 2 types in intel's universe at least, afaik.

As you may know I'm not a fan of deep data analysation. Almost everything I do depends on pure guesswork.:classic_blink:

There may be different types in this format. Is there other models that have a header similar to the girl's one?

Understandable.

And I've attached the race girls meshes in question too.

racegirls.zip

  • Supporter

0x5CD8 vertices start, 0x19028 start of face indices which can be found at file offsets 0x98 and 0x9C

When you look at offset 0x70 there's 0x74 for nick2 and 0x78 for girl1. Adding 0x20 to it you get the offset you need.

  • Author
  • Localization
36 minutes ago, shak-otay said:

0x5CD8 vertices start, 0x19028 start of face indices which can be found at file offsets 0x98 and 0x9C

When you look at offset 0x70 there's 0x74 for nick2 and 0x78 for girl1. Adding 0x20 to it you get the offset you need.

So how do I programmatically determine it in Noesis then?

Create an account or sign in to comment

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.