#Dark Messiah of Might and Magic

1 messages ยท Page 2 of 1

wild valve
#

1000

lucid bridge
#

Is the pinned post still the most up to date way of getting this running? Seems there's been a lot of activity since the wiltostech guide was updated last August

lament jacinth
#

Will get that done when I get home later

lucid bridge
#

Ah wonderful, thanks a lot!

lament jacinth
#

Took the time to rework the lighting in the levels a bit

#

NORMAL

#

Original Dark Messiah

#

You can see the issue there

#

so REWORKED

#

babam!

lament jacinth
#

still working on the textures for the second pic but wanted to show off the lighting as it interacts with fire

sleek sparrow
#

bringing back the dark in dark messiah

#

very sexy

#

i need to see Sareth's mannequin lookin ass raytraced

brittle steppe
#

Alright, we experimented further, and have something working based on your work.
May you commit a modification to dxvk_imgui_about.cpp with your name?

The thing is that we can delay the sky-DrawCallState to later, until we know both sky and main camera position, then we wouldn't need approximate sky / main scale translation

lament jacinth
#

Is that available for me to try out somewhere

#

I think the VTMB team would also need to try it as they have a unique situation where their cams just start flickering unusually

#

There should still be some fixed setting imo

brittle steppe
brittle steppe
lament jacinth
#

No problem, let me know when it's up

#

Excited for a better way to do it especially if it has instance handling

placid hedge
#

Oooh keep us posted sounds helpful!

lament jacinth
#

The message reminded me, @brittle steppe did it get pushed in yet?

brittle steppe
lament jacinth
#

Darn

#

And you can't give a brother a peak to see what's going wrong dope

brittle steppe
#

Well, it's mostly about a compatibility with other games and the toolkit pipeline, since 3D sky would be a part of main scene, they should be repalceable ๐Ÿ™‚

brittle steppe
#

@lament jacinth Sky is merged. Let's see if it works

modern zealot
lament jacinth
modern zealot
#

ive tried a guard npc , and some static objects .

#

i modified them in 3ds max

#

and ingested the usd models

lament jacinth
#

make sure you are not changing your graphics settings

lament jacinth
#

Alright so firstly, it worked

#

and it's amazing how well it worked

#

but in situations where the skybox is still visible, it looks like it overlaps and does this

#

this may be just an issue with the way we are handling the visleafs

#

but amazing so far

#

I gotta look at the code to see if its still not on the shared buffer

#

this issue has come back

#

Ahh no

#

this is just because the auto detect has the wrong scale

#

Yeah okay

lament jacinth
#

The root issue @brittle steppe is that the auto detection for the scale is wrong

#

This should work fine for the VTMB people since their scale is always 16

#

but DM has variable scales, and some other maps in Garry's Mod do as well

#

Where can I find the code for how the scale is determined?

#

Also there are these weird motions here

placid hedge
lament jacinth
#

@fathom bolt

#

As requested moving this here

#

So yeah basically kralich was letting me know I may need to define bones manually for skinned meshes in the USDA

#

What's the process for that ?

fathom bolt
#

So, in if the mesh you import is bound to a skeleton that exactly matches the captured skeleton (in terms of bone order), then the skinning should work.

The problem is that most tools feel free to re-arrange the bones as long as the names are preserved, but Remix doesn't have access to those names.

lament jacinth
#

It's matching everything but refused to bind for some reason

fathom bolt
#

is it matching the captured skeleton, or the original game's skeleton?

fathom bolt
#

yeah - the original game's skeleton is often not the same as the skeleton the game actually sends to the GPU, which is all Remix can capture.

lament jacinth
#

Alright I'll look into that, I assume it's just in the capture

#

Does it match the hash name in the toolkit?

fathom bolt
#

First check if the captured skeleton actually has the same number of bones as the replacement. Then check if each captured bone is (roughly) in the centroid of all of the vertices it effects.

lament jacinth
#

Mesh_zxxx

fathom bolt
#

yeah, the skeleton hash is the same as the mesh hash.

#

Note that we also don't have access to the original bone positions, so when we capture we just put the bone in the average position for all the vertices it skins - so the elbow joint is usually in the middle of the forearm, instead of actually being at the elbow

#

Still, I'd expect that even if you got the bone order slightly wrong, you would still see skinning being applied when you run the game - just horrifically warped as bones apply to the wrong vertex.

#

Also not that when you actually do the replacement, your mod.usda entry will need to look something like this:


over "mesh_26382C5B4AB82E20" (
    references = @../../captures/skeletons/skel_26382C5B4AB82E20.usd@
)
{
    def Xform "child" (
        references = @./skinned/rocket_sentry.usd@
    )
    {
        over "rocket_sentry_qc_skeleton"
        {
            over "Scene_Root0"
            {
                over "RocketSentry_01"
                {
                    rel skel:skeleton = </RootNode/meshes/mesh_26382C5B4AB82E20/skel>
                }
            }
        }
    }
}

where RocketSentry_01 is the actual mesh.

#

oh, and also note that skinning may work fine at runtime but fail to apply in omniverse or the toolkit, so be sure to test that too. Sometimes USD has some issue with the way skeleton bindings are inherited

lament jacinth
#

I'll try all this out

#

Thanks Mark!

placid hedge
#

One thing I noticed on vampire is that it captures in like pairs of isolated bones and the mesh is split into chunks depending on its weighting to said bones

#

Like the skeleton for a single character at least it appears to me... Seems split into many different skeletons with only one or two bones each

#

Are you seeing that with dark Messiah?

#

Would be cool to get a printed list of one of the skeleton bone lists so I can try and emulate and do some tests but I'm not sure where I can see that info

lament jacinth
#

@fathom bolt do you know where I'd fine the skeletons? I thought it'd be in the skeleton folder of the capture

#

but no dice

#

The mesh itself has no skeleton data

#

Unless I'm smooth braining this and I need to set an option to capture the skelly

fathom bolt
#

maybe look through the engine docs for gpu skinning or hardware skinning?

lament jacinth
#

It's SUPPOSED to be using it, the shield for example is recongizing having HW bones

#

it's just the characters

#

I'll take a look

#

example from the sword

fathom bolt
#

not sure how much of that applies to Dark Messiah

#

it is on source engine though, right? just some strange early version of it?

#

but yeah, if your captured mesh doesn't have bones, then skinned mesh replacement wont work - so you'll have to fix that game side

lament jacinth
#

Based on what you're saying it's probably recognizing the HW side, but enforcing SW

#

so I'll just flip that switch back

fathom bolt
#

yeah, it's probably one of those cases where if you can find the switch and fix it, it'll suddenly work.

lament jacinth
#

Will do that now

#

well hopefully

#

hah

fathom bolt
#

I think I remember that it may be using vertex shaders for the bones, but if you set the shader model to 0 it may fall back to fixed function bones?

lament jacinth
#

shader model is already set to 0 here

fathom bolt
#

well so much for that idea

lament jacinth
#

It's just gotta be something dumb with the studiomdl properties there

#

in the model file there is a switch that acts like this

#

but this config can still be overwritten elsewhere, which is likely where it is messing with this

fathom bolt
#

or just set bSoftwareSkin to false in the first part of that if statement and see what happens ๐Ÿ˜›

lament jacinth
#

Precisely what was tried, alas it confirms it is being handled elsewhere

#

there are a few pre-assembly type functions that flag whether a mesh or stripgroup is HW or SW compat

#

GOnna have to find them โ˜ ๏ธ

lament jacinth
#

got him!

#

wow that's blurry

fathom bolt
#

nice! what's it look like in a capture?

#

note - I expect the mesh hash will have changed for that character

#

I also give it about a 10% chance that the skeleton will actually line up, but now you should at least see it moving as the character moves.

lament jacinth
#

back to searching

#

disabling hardware rendering in source stops the model from rendering so I have no idea what's going on

placid hedge
#

Interesting on vtmb it's spitting out partial skeletons. In the debug view through skinned meshes are split into patches, and they are... Mostly? Stable ish

lament jacinth
#

Also what shadermodel do you have set

placid hedge
#

I think our launch args are forcing it to 8

#

I'm not sure how to find out shader model, how could I get that?

lament jacinth
#

"-dxlevel 80", "+mat_dxlevel 80"

#

These boys right?

lament jacinth
placid hedge
#

Oh I did not. Let me look into what it's set at correctly for you

#

actually i think we are forcing it down to 7

#

-game Unofficial_Patch -dxlevel 70 +mat_dxlevel 70 -window

lament jacinth
#

Yep okay

placid hedge
#

looking at dxvk now

lament jacinth
#

That's how I have it set

placid hedge
#

anything higher than that and nothing runs

lament jacinth
#

I just tried dx8 thougfh, and still no skeletons

#

means there's TRICKERY afoot!

placid hedge
#

haha damn mysteries

#

i did find a way in the console to force software skinning or whatever

lament jacinth
#

mat_softwareskin or somet

placid hedge
#

and the hashes become completely unstable and insane

#

yeah

lament jacinth
#

yep

#

hah

#

That's about right

#

if you do r_drawmodelstatsoverlay 1

#

or something like that

#

you should see text

#

you may have to also do developer 1

#

what text do you see on the NPC models?

lament jacinth
placid hedge
#

hmm im not seeing a dxvk.conf for vampire

#

i see a vampire.dxvk-cache

#

r_drawmodelstatsoverlay 1 isn't a valid command in vampire :/

lament jacinth
#

I love our same-but-different source engine versions!

placid hedge
#

Haha yeah... I hope our problems are same enough that we can help each other solve them lol

lament jacinth
#

Right now I Just have to fish out what is forcing this to render in SW mode

placid hedge
#

I had done some poking around about that and saw some people having issues with old half life 2 also forcing software mode in general

#

I don't think there was a resolution for that 17 year old thread though

lament jacinth
#

Helps to know the solution will be stupid and obfuscated then!

placid hedge
#

i think this old thread had some oddities in it

#

this guy was stuck in software +dx9

#

also this is when i debug geo hash on character

#

many parts are unstable and flashing

#

if i set it to software

#

everything shifts and becomes more unstable

#

character flashes all over

#

in hardware only some parts flash

#

weirdest part

#

these palm trees are skinned meshes

#

and have ultra stable hashes in hardware

#

characters and view models do not have very stable hashes

#

but portions of the character are nice and stable like her mid back (bright teal turqoise) and center upper back, NEVER change

#

some parts on her legs NEVER change either

lament jacinth
#

I'm about to hop on and check this stuff now

fathom bolt
placid hedge
#

The player character on screen actually does not have blend shapes as far as I known. Almost every other character in the game does though

#

They look roughly the same as this

placid hedge
#

so its very possible they store blend shape info on the entire body just due to inexperience or bad process or deliberate choice D:

#

i wanted to renderdoc vampire but renderdoc only works on dx9 and up applications so i wasn't able to pull that apart

fathom bolt
#

Anything that dynamically changes vertex positions on the CPU will invalidate geometry hashes (and will prevent skinned replacements from working)

placid hedge
#

Definitely feels like regardless if software skinning is on, things are still being moved on the cpu

lament jacinth
#

I've done so much digging here

#

It genuinely seems like it's rendering with hardware

#

but it's still not outputting bones

#

At least, it is on hardware "mode"

#

The software skin command is set to 0 and it never seems to get to dynamic meshes

#

which would be when it decides to do software skinning

serene gale
lament jacinth
#

Is there a debug view to see if it's actually coming in as "hardware" ?

#

See it definitely is flashing as if it's software, or at least that the hash is entirely unstable

#

Alright

#

I found the reason why it wasn't doing it

#

I'll need to pay some attention to make it safe

#

but i DID get a skeleton

#

problem is because I fudged it to validate it from all the other st uff

#

lmao

#

this guy right here, it's built into one of the fallback shaders to require software skinning

#

For my case it's the VertexLitGeneric_DX6 / DX7

placid hedge
#

Oh shiii

#

Do you think that could be overridden in a vmt file?

lament jacinth
#

Nah this is a shader specific issue

#

I'm trying some alternatives now that I understand what the blocker is

#

Ok got an even better method

#

TL;DR

#

Change nothing on the software hierarchy

#

Because it needs to do the software calculations

#

just pass the software calcs into the hardware group funcs instead

#

Since animated models are dynamic mesh type stuff

#

I was able to basically enforce the first one in these type of statements

#

Now I need to fix the unstable hash

#

but at the least, we can make these skins while I do that

lament jacinth
#

I am definitely seeing what you mentioned @placid hedge about the bones being "segmented" almost

#

My understanding is that the bonestatechange triggers may be activating in pieces

#

OR

#

we are looking at the strip groups

tardy heart
#

very interesting stuff

placid hedge
wise oriole
#

Not quite the same, but this reminds me of an issue I've been running into with trying to replace some sections of world geometry with better meshes. Surfaces that are contiguous and share a texture are inexplicably being split into multiple meshes.

lament jacinth
#

Seems like there just needs to be some additional info being sent to the api

#

Would help a lot of we had code access to these games

#

But alas

placid hedge
#

Yeah that's the big stopper

#

Two of my leadership at my sister company used to both run Activision at some point. One of them during the release of vtmb

#

Maybe I should reach out and see if he can move a mountain

lament jacinth
#

It's unfortunate, while I was able to get SOME bones sent to the hardware side, it seems like I can't get them all the way correct. I thought it was splitting each bone when in reality it's just picking up a bone in the origin, and one at the actual position apparently

serene gale
lament jacinth
#

I honestly can't tell because it took a bunch of hacks just getting it to appear in dark messiah as a "hardware" bone

#

VTMB is able to get their bones at least coherent.. mine are literatlly just two nonsensical ones

#

Guess I'll go down the spoofing route of making a model replacement then beefing up the textures through remix

#

Hands are tied without rewriting the entire skinning system within the studiomdl renderer and that's more work than it's worth without access to whatever the game is doing

#

I'm also not really sure the advantage of using remix to perform the skinning instead of just upgrading the model itself

#

I guess performance?

serene gale
placid hedge
#

Vtmb I mean

lament jacinth
#

@fathom bolt or @brittle steppe would either of you know where in the DXVK-remix code the bone "capturing" stuff is? Like where does it receive said bone data

#

I'd just be interested in probing what the source engine is actually sending

fathom bolt
#

I believe most of the skinning code is in RtxGeometryUtils::dispatchSkinning, though the stuff to write that out to USD is in another file

#

The d3d9 fixed function skinning API just takes a flattened list of transforms, not an actual hierarchy. So the captured bones are always 1 root and every other bone as a direct child (which makes it near impossible to skin them reasonably). The workflow we've generally followed is to skin them to the original skeleton, then just remap the bone indices based on which bone in the original skeleton maps to the same flattened bone in the captured skeleton.

Also note that we don't get origins for those captured bones - we place them in the average position for the vertices they influence

placid hedge
#

I had seen you mention this technique before @fathom bolt but I definitely am missing some understanding of certain steps. I was able to one time get it to give me a big readout of all the bones for a certain character, but I was struggling to sort of understand what went where from that list.

I think some intermediate steps to me are a bit unknown.

On VTMB at least (which I'm sure could apply to messiah) I have access to all original skeletons from the game, so remodeling characters and re rigging them is super super trivial on my end. It's the steps where I identify the bones, then am able to understand which bones in the og skeleton to remap that's giving me the confusion. Wondering if there's additional clarity there that I could get directed to!

fathom bolt
# placid hedge I had seen you mention this technique before <@617500777191047168> but I definit...

The toolkit team has a task to make a decent workflow for this, without that it's... complicated, and a bit of a guessing game.

The original game skeleton is something like

root
  spine
    spine2
      Rshoulder
        Rlbow
          ...
      LShoulder
        LElbow

The bones that the game sends to the GPU is just

worldToRoot
worldToSpine
worldToSpine2
worldToRShoulder
...

We know that all the bones are children of the root, so we can at least reparent them and get that tiny part of the heirarchy back - but we don't really know how to reconstruct the rest of that heirarchy. Fortunately, we also don't need it for actual rendering.

The only important bits of information we need is the array of bone transforms, and the array of vertex skinning weights (which bones each vertex is attached to).

The remaining problem is that those arrays need the indices of the bones to match up - i.e. the data will say "Vertex 234 is 50% from bone 12, 25% from bone 13, and 25% from bone 14".

So the game will send us a list of 20 bones, but the original asset's skeleton might have 25 bones. When you bind your replacement mesh to the original skeleton with 25 bones, the indices won't match up to the indices of those 20 bones the game actually sends us.

In the toolkit, there's actually a way to update all those bone weights to use different indices, but it requires manually adding a property to the post-ingestion version of the mesh USDA, and I don't remember precisely how that's controlled...

#

BTW - for source engine games, the skeleton is in the .qc file. I think the reduced skeletons are also in there as the $lod sections

#

not entirely sure, but I do remember that the full skeleton and the reduced skeleton are both defined somewhere in the decompiled source assets.

#

I'll see if I can dig up the details for the manual proces... I really need to post a write up of that to #1096847508002590760

#

oh, also a note -
Valve will sometimes define bones in orders that blender / FBX can't support, and they'll automatically re-order them on import. Which breaks everything again.

I generally see this where Valve will do

...
finger1_root
finger2_root
finger3_root
finger4_root
finger1_mid
finger2_mid
finger3_mid
...

blender will auto resort that to

finger1_root
  finger1_mid
    finger1_tip
finger2_root
...
placid hedge
#

In the decompiles I've been able to make of VTMB I get things that include joint constraints and phys bone defs, but if I look in the actual SMD files in notepad++ I end up with stuff like:

#

nodes
0 "Bip01" -1
1 "Bip01 Pelvis" 0
2 "Bip01 Spine" 1
3 "Bip01 L Thigh" 1
4 "Bip01 L Calf" 3
5 "Bip01 L Foot" 4
6 "Bip01 R Thigh" 1
7 "Bip01 R Calf" 6
8 "Bip01 R Foot" 7
9 "Bip01 Spine1" 2
10 "Bip01 Spine2" 9
11 "Bip01 Neck" 10
12 "Bip01 Head" 11
13 "Bip01 Ponytail2" 12
14 "Bip01 Ponytail1" 12

#

so i can definitely see how the skeleton is definied in the smd, qc seems not to have that info in there

fathom bolt
#

right, so 15 bones in that specific order.
qc doesn't have something like $definebone?

placid hedge
#

It does not. But it's possible that it's because its hacked together toolsets since it was a reverse engineered sdk using other later sdk releases

#

which might be similar to messiah's situation as well

fathom bolt
#

Do you know how many bones show up in the remix capture?

placid hedge
#

in a remix capture it tends to only be 2 bones

#

let me get a shot

fathom bolt
#

2 bones for an entire character? thats... unexpected. sounds more like that's a rigid bind or something

placid hedge
#

Works great when I need to rig something like the mailbox or the refrigerator...

#

i have a good example im tracking down right now hopefully

#

and yeah for a character i tend to see few bones

#

and the characters are split into many patches

#

i suspect they are patches that share bone weights?

#

or weights to a specific bone

#

actually this capture is jank let me capture it again i think i can get it to give the result im describing

#

Ok so now when I capture bones aren't showing up for some reason

#

Trying a few things :/

#

usually i get skeletons right now I'm not

#

ok so on one of the characters i actually did get pretty much a whole skeleton!

#

still trying to repro only getting a couple bones

#

here is the level i was getting 2 bones in before:

#

captured all characters skeletons well

#

importing into usd is when the problem occurs

#

these rigs are split up into skeletons with 1 root and 1 joint

#

@fathom bolt is this what you would expect to see as well?

fathom bolt
#

Erm, none of that is what I was expecting to see ๐Ÿ˜ฆ

fathom bolt
#

It kinda looks like the character is being captured as a few dozen separate meshes, basically one for each bone?

#

or each combination of bones?

placid hedge
#

i think that's exactly what is happening

#

each mesh is split based on what bone it is primarily influenced by i think?

#

reposting the debug shot from above

#

this happens on almost all skinned meshes, except some, like the palm trees outside which are also skinned meshes

#

they are totally stable and fine, but its most likely because they are full weighted to single bones

#

what are some of the commands you guys used for portal that made them behave the way you wanted?
they may not exist here since this is a pre hl2 source engine D:

fathom bolt
placid hedge
#

i'll take a look now

fathom bolt
# placid hedge

this is very different from the result in Portal or HL2. Mixing the bones from a bunch of different draw calls and applying them to a single replacement skeleton... would be an entirely new, complicated feature.

#

not even sure if we can do that reliably, especially when characters get close to other characters

#

I have no idea why they would split a character up into so many separate draw calls - really doesn't make sense to me

placid hedge
#

yeah, it's real weird, @lament jacinth does this happen on dark messiah?

lament jacinth
# fathom bolt I have no idea why they would split a character up into so many separate draw ca...

The bones are separated by bone controllers from what I understand, and each controller is what signals the hardware of the change. It seems to me that not every bone at ONCE can be signaled to have a change, and that's why I was interested in finding out where that information is coming from, because it's possible that at the point of capture there is only maybe one or two bones that are actually being transmitted for skinning, or at least those that are bound to a specific triangle strip as you've mentioned

lament jacinth
#

And they do not have any rhyme or reason like yours do

#

When I talk about the origin, I'm talking about the origin of the map

#

So there will be one gigantic bone who's start point at origin, and end point at the real position

#

And then the next bone is the same, origin of map, real position of bone

#

You get these HUMUNGOUS guys

#

But the actual Skeleton file produced is only one hash

placid hedge
#

whoa

lament jacinth
#

I'm sure dark Messiah is just incredibly stupid, especially because I had to work around just getting the things to skin with hardware

fathom bolt
lament jacinth
#

I figured as much hah

fathom bolt
#

If you're getting 1 or 2 bones per draw call, that means the character is sent as manay separate draw calls? whereas in portal it's 1 call for the face and 1 call for everything else

lament jacinth
#

Now you see why I asked where in remix this occurs, I need to understand what Dark Messiah is actually sending it ๐Ÿ˜ญ

fathom bolt
#

yep. I believe that geometryUtils class I linked is where we actually handle the skinning.

#

capture just writes the bone array that uses out to USD

#

although D3D9Rtx::processSkinning in d3d9_rtx.cpp is also good to look at if you're trying to understand the d3d9 calls

lament jacinth
#

Within remix, is there any debug tagging I can do to visualize the process so I can maybe see if they are being singled out?

#

Or see if for example some of the triangle strips are not in the same draw call I guess

fathom bolt
#

well, geo hash will be one color per draw call, so if different parts of the mesh are different colors, that's different calls

lament jacinth
#

Let me check that out right now

fathom bolt
#

I'd expect your character to look somewhat like this
#1098843924602306601 message

placid hedge
#

not sure if this helps

#

but some hashes are ultra stable on characters

#

and some are not

lament jacinth
#

uhhh

#

So the man is all in one piece?

#

let me make sure I have my settings correct

#

Yep they are, and they developed skeleton entries

#

Me: Gigabone isn't real

#

GIgabone:

#

The reason this one is particular big is because it's far from the level origin

fathom bolt
#

what does it look like when you open up the capture USD and select the body mesh?

lament jacinth
#

One second

lament jacinth
#

The longet second you've ever seen

#

I had some issue where my game stopped producing skeletons

#

turns out it was because the object caps had changed when I was trying to solve colo correction stuff

#

๐Ÿ˜Š

#

here's your body mesh

#

That big white thing behind him is his bone

#

i had to go inside of it so i can show him off

placid hedge
#

meant to follow up on this, but, what was your process to get one contiguous mesh like this?

#

were you ever seeing the patchy results that i'm seeing in vtmb?

#

or was this just how it came in for you when you got it working period?

lament jacinth
#

The problem is one continuous mesh like this is incorrect, I'm getting one skeleton with two bones when I do it like this

#

Even though the game is registering as a total of 59 hardware bonus

#

Bones

placid hedge
#

Ahh gotcha

#

And just for data of you turn software skinning on does it spit out a different result? (Obvi not a solution just curious if it does split the mesh)

lament jacinth
#

I'll get no more skeletons

#

so it is consistent

#

I think the problem is that Dark messiah is also partly a console game

#

and MAYBE there was just some stuff axed in compile

wise oriole
#

Remaking one of the characters would be heaps fun. We might have our hands tied a bit atm though

#

If you need a character artist to make one in the future though

#

Assuming it can work as it should

placid hedge
# lament jacinth and MAYBE there was just some stuff axed in compile

Interesting. When I decompile vtmb characters with the $definebone commands it still won't spit out bones into the qc file. So I'm guessing they have some internal differences as well. The bones are defined in the physics and vta and files so try definitely exist in some format. As far as when pulling the bones from remix I'm definitely seeing the two pair bone chains but they are all positioned and sized correctly. If I could get it to capture contiguously that would be a huge step.

lament jacinth
#

The compiler for Dark Messiah is so scuffed it spits out warnings for commands THAT ONLY WORK IN THEIR OWN COMPILER

placid hedge
#

Lol jesus

lament jacinth
#

Gotten to the point where I'm going to compile my own source 2007 mod JUST TO SEE how it handles the pipeline and what the "possible fix" to get it out is

#

so I can reverse engineer that part out and put it in our SDK

#

It's so weird

tardy heart
#

that sounds fun shrek

placid hedge
tardy heart
#

I did buy a copy of Dark Messiah on steam, so let me know too if there's anything I can help test too

#

can't believe I slept on this amazing game

lament jacinth
#

Yeah thank you guys for the help before, once I get a handle on how to fix the skeletal stuff, thats when the real testing shall begin

placid hedge
marsh bramble
#

๐Ÿ’š Hello Project Leads! ๐Ÿ’š
Are you leading a Remix Mod Project? I'm eager to hear all about it! Please feel free to send me a direct message so we can discuss your project in more detail.

lament jacinth
#

WendyGram-Gram received

lament jacinth
#

Alright @placid hedge there are some changes that need to be implemented

#

it would prevent having to recompile your models

#

but you will need to ship a module like I do for RTX

#

Reason is that on investigation, the way the RTX version of studiorender is handling models, it actually seems to produce bone controllers based on the vert/bone themselves

#

Rather than the compiled version

#

and then, there is a modification in the way dynamic meshes are rendering

#

It basically loads a material model matrix mode onto the render stack, loads some matrix, then pushes a view matrix mode onto the stack, and pushes another matrix + the rest of the strip data

#

So I have to reverse the Portal RTX renderer -> bring it back to our version

#

my original idea of modifying the compiler to output fixed function data DOES WORK

#

but it is still segmented

#

though you at least get the entire skeleton

#

lol

#

Going to run this for Dark Messiah first, and then I will implement the same in your Studiorender

#

the beauty is that our offsets are pretty much identical

#

since our formats are close together

placid hedge
#

Awesome

#

Let me know when I can tag in and test

lament jacinth
#

Yeah I need the week for sure

#

the reverse engineering has doubled since it;s unclear what the EXACT change (or changes) nvidia has done to portal rtx

#

so I can only implement this in pieces, and walk through the pipe until I have everything

placid hedge
#

Gotcha. I'll be ready to go when you need it. I've got some stuff I can test with

#

Art wise I mean

serene gale
lament jacinth
#

I'm pretty sure you can already "sort of" do this through lua minus the model processing thing

#

gmod is more complicated because with updates, comes instability

#

but it's something I will keep in mind

#

I'll try to design this just generic enough that a module can go in as easy as possible

lament jacinth
#

@fathom bolt two questions: firstly, for portal RTX, is there a specific person at Nvidia that worked on changing up the studio render stuff? If so, possible to know who that is to probe them with questions?

#

Second question: is it against the "standards" for remix to start opening up some of the internal options like skybox scale to an API?

#

With my automatic detection gone I realized that I can just feed my scale directly to the config option but I need to open up a function for that

#

And I don't know whether that's something worth a PR

fathom bolt
#

studio render? not sure what that is

fathom bolt
lament jacinth
lament jacinth
#

I would basically need to modify that config value live

fathom bolt
lament jacinth
fathom bolt
lament jacinth
#

They could have been from Portal I'm not sure, but it's clear there were some changes there

#

What I say models ingested I mean literally the way that it processes the strip data when it reads the model and VTX file

#

I've already replicated some of it but without understanding the reasoning or even more useful seeing the actual lines of code rather than the assembly, it's pushing a boulder up a hill

#

So I'd want to ask them

#

I could send them the exact functions I'm interested in, if it was a few people, and then whoever knows may answer? Just need to know who the starting point of that is

#

For example dynamic meshes have both a model matrix and a view matrix mode pushed through, and it also pushes some mystery matrix I'm not sure of

#

I don't know if that's unique to Portal

#

Or if you guys change that for instance

fathom bolt
#

I think it's likely more a problem of memory, but I'll ask around internally

lament jacinth
#

The way the strip data is done instead of creating the bone controllers from the hardware meshes it actually produces them based on the total number of bones on the studio model as well, it's not something I've seen in any of the leaks even up to the 2018 one

#

Like there's a fair few, I'll ping you with a list when I get home from work and maybe you can use that then internally

#

But the importance of why I'm asking is to speed up what I'm doing, but also to make it so that the source engine games that cannot use the portal modules because of their interface difference can at least have an equivalent processing

fathom bolt
#

I get it, and it'd be nice if we could have just shared the code for our changes, but IP is hairy. The people I can think of that were probably touching that code are pretty busy, so it may take a bit to get a response

lament jacinth
#

Alright. I'm pretty sure that whatever code I'm asking for you guys generated, but Lord knows it probably took some work to get the access to make those changes so I get it too. This is why just picking someone's brain would be enough for me because I know what I need to do in terms of the functions but I don't know how it is done to make it work, at least it blindly. Here are two off the top of my head: R_StudioBuildMeshStrips R_StudioDrawGroupSWSkin

#

The second pushes double matrices in different modes with some baseline matrix which I'm not sure of and the first is what is used to process the model and vertex data, which is where I found that it sets the flag for hardware meshes on any mesh that has bones greater than one and then it has some custom processing for the strip headers so that it produces bone controllers on those bones

#

I can only assume there's some intermediary functions done to the pose matrices so that it can get applied properly to

fathom bolt
#

Have you read up on how d3d9 vertex blending is supposed to be specified?

Apparently most of the work was in disabling the software skinning and binding the bone matrices to that d3d9 API instead

lament jacinth
#

I'm aware of the way it's supposed to be sent

#

but if this is where the work went

#

that's a good hint. Will it be a problem on what SPECIFICALLY was changed even if you guys don't point to code? Is that NVIDIA proprietary change at this point?

fathom bolt
lament jacinth
#

If i get far enough along this weekend I'll paste my code here and you can give it your opinion ๐Ÿ˜‰

lament jacinth
#

@fathom bolt so I'm able to get the actual world position, and I have the posetobone transform available

#

When you say converting it to model space, I'm assuming you're talking about the new bone positions, but local to the model right?

#

Not the bind pose positions

fathom bolt
#

yeah. Do you understand the d3d9 fixed function skinning spec?

Basically, the object has some transform - which can basically just be the world to the root bone transform.

Then each bone's transform is relative to that root, instead of being relative to the world. If you have a list of bone transforms, you need to multiply all of them by the worldToObject transform (which is the inverse of the objectToWorld transform)

lament jacinth
#

Like the source engine has a very specific way of calling in referencing the stuff, which makes it difficult to Google search and find the equivalent in the docs

#

Like for example the matrix type stuff (Model, View, Projection) took a little bit to find

fathom bolt
#

yeah, the source engine was mostly written before the industry had settled on standard terms for a lot of that stuff

lament jacinth
#

Oh yeah definitely doing something wrong lmfao

#

That's the origin of the map

#

So here's my logic now:

#
1) Get m_PoseToWorld of bone 0 (root)
2) Invert that to get the WorldToPose
3) Loop through all bones, do poseToBone[i] * WorldToPose[0]
4) Set render matrix mode to MODEL
5) Set vert number of bones to that in the mesh
6) Load bone matricies coordinated bone X to poseToBone[X]
7) Draw Mesh
#

Oh I see, I was getting the transpose instead of the inverse

#

time for math fixes

lament jacinth
lament jacinth
#

Nah I'm still having the issue even with the rest of the inverse process being added

#

Definitely when you get the chance let me know if the way I'm handling it is correct

fathom bolt
#

you're forcing the game to use the fixed function pipeline, not software or vertex shader skinning, right?

#

If you take a capture, is there a skeleton included in the capture?

lament jacinth
#

It starts getting a skeleton yes, but then crashes

#

probably because the bones are just MESSED up lol

#

And by crash I mean the bridge crashes

#

Game runs fine even with this monstrosity

#

also yep 100% using fixed function

#

I have almost fully replicated what you guys did with the portal binary

#

We have hardware bone controllers, and it passes through the "hardware" skinng path

#

which requires it to load the bone matricies

#

otherwise it will just make a tpose of the base mesh

#

The only two avenues are that my math or process is wrong above, or that the matricies I have are not what they seem to be

#

THat's why I'm asking if the process looks correct to you, since that seems the fastest as easier way to confirm

#

poseToWorld of specific bones is a product of the world matrix of the model being multiplied by the poseToBone matrix of a bone

#

For the root, this is just a flat copy

lament jacinth
#

Alright I found out why it was bad, the matrix I was using for my root was not correct

#

so I replicated most of it

#

almost there I guess, at least it's in the right place lol

#

The part that's screwing me is that in the drawmodel I can see the matrix type being set to a view matrix

#

and then when the hardware draws it just holds that for the xforms

#

I've replicated that too but I have to assume something in that matrix type push is where this monster is coming from

lament jacinth
#

Alright yeah, looking at what I could reverse, you guys are transposing some matrix in CStudioRender::DrawModel and then applying it to all of the m_pBoneToWorld before ComputePoseToWorld

#

I thought it was an inverse but it's just a transpose

#

@fathom bolt if you could take a look at that draw model function, what is the argument before matrix3x4_t *pBoneToWorld

#

Is it the origin of the entity itself?

#

Additionally maybe you can give me more info on why you guys are pushing the view matrix type

#

Like from a logistics standpoint

#

By default the render chooses MATERIAL_MODEL and loads an identity

#

but you guys have that additional MATERIAL_VIEW followed by what I think is a MultMatrix of that mystery argument mentioned above

#

That';s the last potential matrix fuck up I have and I just have no idea

#

You were saying earlier it is the worldToObject transform but I thought that was just pBoneToWorld[0]

lament jacinth
#

slowly but surely figuring out the problem, the D3D9 caps were modified on the Portal RTX module to support up to 256 indicies, which is why my bones were verts were only listening to one bone

#

SOmething is still messed up but, he begins to take form!

#

these settings

#

in portal RTX modules both of thes are at 256

fathom bolt
# lament jacinth

huh, I'm pretty sure on the capture and replacement side we're only supporting 4 bones per vertex, not sure what that number would need to be raised to 256. Maybe the engine misuses it somewhere

lament jacinth
lament jacinth
#

I think one of them does unrestrict the bone matrix though

#

like the amount you can load in for reference

lament jacinth
#
MatrixInverseTR(modelToWorld, m_pWorldToBone);

matrix3x4_t new_BoneToWorld[256];
matrix3x4_t new_PoseToWorld[256];
for (int i = 0; i < pStudioHdr->numbones; i++)
{
  ConcatTransforms(m_pWorldToBone, m_pBoneToWorld[i], new_BoneToWorld[i]);
}

for (int i = 0; i < pStudioHdr->numbones; i++)
{
  mstudiobone_t* bdata = pStudioHdr->pBone(i);
  ConcatTransforms(new_BoneToWorld[i], bdata->poseToBone, new_PoseToWorld[i]);
}

for (int i = 0; i < pGroup->m_NumStrips; i++)
{
  StripHeader_t* pStrip = &pGroup->m_pStripData[i];
  render->SetNumBoneWeights( pStrip->numBones );

  for (int j = 0; j < pStrip->numBoneStateChanges; j++)
  {
    BoneStateChangeHeader_t* m_StateChange = pStrip->pBoneStateChange(j);
    if (m_StateChange->newBoneID < 0)
      break;
    render->LoadBoneMatrix(m_StateChange->hardwareID, new_PoseToWorld[m_StateChange->newBoneID]);
  }
  mesh->SetPrimitiveType( m_Flags )
  mesh->Draw( pStrip->indexOffset, pStrip->numIndices )
}
#

@fathom bolt what am I missing from this runthrough?

#
    // Specifies the entity-to-world transform
    matrix3x4_t                        m_rgflCoordinateFrame;```
#

So I take the m_rgflCoordinateFrame of the entity, invert it to get the worldToBone (worldToModel) matrix

#

Apply that to the base bone transforms on m_pBoneToWorld

#

Now on that adjusted BoneToWorld, reapply the bone poseToBone matrix

#

something is just refusing something

fathom bolt
#

not sure where else DrawModel is called from, and I don't have the ability to search this code

lament jacinth
#

Let me check my end

#

Right now it just seems like none of the bones are influencing anything

#

despite loading in the bonecontrollers and such

#

The only thing I could think was that the vertex doesn't have bone weight data

#

or the mesh wasn't adding it

#

but neither of those make sense, it is registered as a hardware model and it is going through all the channels. If this was software skinned it would read those weights so it must have it

fathom bolt
#

I wouldnt' make assumptions about the hardware path working out of the box, the entire point of these changes was that the path had suffered from code rot and we had to get it back to functionality

lament jacinth
#

True

#

I'll retrace the steps

#

Also old source doesn't use DrawModelArray, but I see what you're saying about the arg

fathom bolt
lament jacinth
fathom bolt
#

and we had to build an exception when there's only 1 bone, to set the bone's matrix to the identity

lament jacinth
#

Since I'm detouring I just default to the regular rendering if there's 1 bone, I have not had any issues with skinning and such there

#

So in R_StudioCreateSingleMesh you guys have this type of switch that activates if the numbones>0 and it hasn't been registered with hardware strips

#

I assume because of the .sw.vtx type files are the default used for dxlevel < 80, so you need to restore bone state

#

In that special built strip function, I am PRETTY sure it looks like this

#
void __fastcall R_SpecialBuildMeshStrips(void* This, void* _EDX, studiomeshgroup_t* pMeshGroup, StripGroupHeader_t *pStripGroup)
{
    void* memalloc_vtable = **(void***)(*g_pMemAlloc);
    F_malloc malloc = *(F_malloc*)( (int)memalloc_vtable + 4 );
    int stripDataSize = ( 8 * bone_count + sizeof(StripHeader_t) ) * ( pStripGroup->numStrips );

    pMeshGroup->m_pStripData = (StripHeader_t*)malloc(*g_pMemAlloc, _EDX, stripDataSize);

    int max_bone_count_in_strip = 0;
    for (int i = 0; i < pStripGroup->numStrips; i++)
    {
        StripHeader_t* testThing = pStripGroup->pStrip(i);
        if (max_bone_count_in_strip <= testThing->numBones)
            max_bone_count_in_strip = testThing->numBones;
    }


    int boneStateChangeOffset = pStripGroup->numStrips * 27;
    for (int i = 0; i < pStripGroup->numStrips; i++)
    {
        memcpy(&pMeshGroup->m_pStripData[i], pStripGroup->pStrip(i), sizeof(StripHeader_t)); //sizeof(StripHeader_t) is 0x18.. supposedly

        // Fixup the bone state change offset, since we have it right after the strip data
        pMeshGroup->m_pStripData[i].boneStateChangeOffset = boneStateChangeOffset -
            i * sizeof(StripHeader_t); // 27 is supposed to be sizeof strip header, again

        pMeshGroup->m_pStripData[i].numBoneStateChanges = bone_count;
        pMeshGroup->m_pStripData[i].numBones = max_bone_count_in_strip;

        for (int j = 0; j < bone_count; j++)
        {
            BoneStateChangeHeader_t* bstate = pMeshGroup->m_pStripData[i].pBoneStateChange(j); /*pStripGroup->pStrip(i)->pBoneStateChange(j);*/
            bstate->hardwareID = j;
            bstate->newBoneID = j;
        };

        boneStateChangeOffset += sizeof(BoneStateChangeHeader_t) * bone_count;

    }

    pMeshGroup->m_NumStrips = pStripGroup->numStrips;
}```
#

Comments are my insanity

#

The difference is you guys have an extra argument for the bone count that I can't get, so the bone_count here is pulled from an external var

#

And additionally, you guys also set models with bone_count > 0 to have MESHGROUP_IS_HWSKINNED

#

I don't see anything special being done when the static mesh is being generated

fathom bolt
#

what file is R_StudioCreateSingleMesh in?

lament jacinth
#

Should be

#
        if ( pStripGroup->flags & OptimizedModel::STRIPGROUP_IS_HWSKINNED || pStudioHdr->numbones > 0 )
        {
            pMeshGroup->m_Flags |= MESHGROUP_IS_HWSKINNED;
                        hw_skinned = True;
        }
#

SOmething like this

#

and then the if statement checks if pStripGroup->flags & OptimizedModel::STRIPGROUP_IS_HWSKINNED || !hw_skinned DoNormalOne else DoSpecialOne

fathom bolt
#

so... at least the code I'm looking at doesn't use special anywhere in the file

lament jacinth
#

Well the name of the function is something I've called it

#

realistically it is some modified version of the R_StudioBuildMeshStrips

#

Since the default state of R_StudioBuildMeshStrips will use the pBoneControllers state changes built into the model, your custom version is generating the state changes based on the amount of bones it has

#

It would be two different functions, R_StudioBuildMeshStrips is the "normal" one

fathom bolt
#

We have a few short changes in there, but no new functions as far as I can tell

#

most of the changes there are porting fixes from the maya plugin, and are wrapped in #ifdefs...

#

nothign to do with skinning

lament jacinth
#

I see.. what I'm having could be the way the disassembler is interpretting it then

#

I am skeptical there isn't a major change occurring right there though

#

In one of those functions you are probably passing pStudioHdr->numbones

#

The block usually goes something like

#
 R_StudioBuildMeshGroup
 R_StudioBuildMeshStrips
R_StudioBuildMorph
#

the contention is at R_StudioBuildMeshStrips where maybe there's an overload but that function never accepts a third argument let alone pStudioHdr->numbones

fathom bolt
#

As far as I can tell The only changes we made to this file while working on Remix were to add the objectToWorld matrices when calling DrawModel. We inherited some changes that were made years before Remix started, but those all seem to be about porting in support for Maya

#

I can see what just look like normal if blocks, not entirely separate functions. so maybe the compiler is just branching into entirely separate code instead of only branching the if block

lament jacinth
#

If you guys didn't have a hand in that then maybe that was just the changes between the last leak I can reference and when you guys started working on it

#

i appreciate you digging in there for me

fathom bolt
#

ahh... I just got pointed at a different folder that we actually used, the folder I was looking at was old :/

There is indeed a lot of changes to that file, including a function that builds strip data to include bone change indices

lament jacinth
#

I consider that great news, because I was about to throw in the towel instead of fighting 20 years of source engine changes upstream

#

So for starters, that new function, did I "do it right" above there?

#

That's the first check to ensure I am actually generating the correct state changes

#

The bone change indicies should just be linearly incrementing from the bone count since that's how the software mesh is going to read them usually (rather than a hardware bone proxy ID that >= 80 use)

fathom bolt
#

I'm not sure about BoneStateChangeHeader_t* bstate = pMeshGroup->m_pStripData[i].pBoneStateChange(j);.

lament jacinth
#

if I had to guess it looks more like unsigned char* pBoneStateChange = (unsigned char*)pMeshGroup->m_pStripData + boneStateChangeOffset;

fathom bolt
#

yep

lament jacinth
#

Yeah I think mine would be effectively the same, since I am just treating it as the actual struct at that point. It's probably then directly referencing

*pBoneStateChange = j
*( pBoneStateChange + 4 ) = j

where j is the current bone incrementing up to the total bone count. Or it's a memcpy of some kind

#

But that's good, at least I got that somewhat down

#

I know you can't paste code here so a stinky eyebrow means I'll fix it

fathom bolt
#

sure, just that pBoneStateChange(j) looks like a function call, where that's a pointer in the code I'm looking at

lament jacinth
#

Yeah that's an inline call decomposed to (BoneStateChangeHeader_t *)(((byte *)this) + boneStateChangeOffset) + i;

#

this being the stripdata

fathom bolt
#

makes sense

lament jacinth
#

Alright next questionable area is in CStudioRender::DrawModel

#

This one might be in studiorender.cpp

fathom bolt
#

yeah, looking at that already

lament jacinth
#

Yeah this is where you were taking the modeltoWorld transform, Inverse, and apply to all the m_pBoneToWorld I presume

fathom bolt
#

I think your approach of just making 1 bone assets go the software route might actually be a lot simpler than what we wound up doing

lament jacinth
#

right before the compute

lament jacinth
lament jacinth
fathom bolt
#

still, you're focusing on multi bones right now. The path for that doesn't look much different, although this code retains the original modelToWorld as a backup for SW Skinning

lament jacinth
#

But you guys seem to have some additional ``` pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PushMatrix();

lament jacinth
fathom bolt
#

yeah, I don't actually know what the matrixMode thing is about

lament jacinth
#

Hah that's encouraging

#

Maybe it's because of Portal?

#

Since you guys got the raytracing to go through the portal, it probably projects the draw from the relative view

#

It would certainly make sense, I do see y ou guys doing some pRenderContext->GetMatrix( MATERIAL_VIEW , XXX )

fathom bolt
#

mayber - that XXX is the matrix that we're keeping around as a backup for SW skinning, from the comments

lament jacinth
#

Ahhhh okay

fathom bolt
#

actually we keep two oef those, a world matrix and a view matrix

lament jacinth
#

Yep was about to say, the condition where numbones != 0 uses some other variable which looked like the modelToWorld xform you mentioned

fathom bolt
#

yep.

lament jacinth
#

Alright

#

So I've gotten all that correct so far

#

and I probably don't need to project the view

#

and I guess we should just confirm the R_StudioDrawGroupHWSkin

#

I doubt anything has drastically changed there

#

That one may be in an r_studiodraw.cpp

#

    int numTrianglesRendered = 0;

    if ( m_pStudioHdr->numbones == 1 )
    {
                if( dxlevel >= 80 )
                {
            pRenderContext->MatrixMode( MATERIAL_MODEL );
            pRenderContext->LoadMatrix( m_PoseToWorld[0] );
                }
        // a single bone means all verts rigidly assigned
        // any bonestatechange would needlessly re-load the same matrix
        // xbox can skip further hw skinning, seems ok for pc too
        pRenderContext->SetNumBoneWeights( 0 );
    }

    if ( pColorMeshInfo )
        pMesh->SetColorMesh( pColorMeshInfo->m_pMesh, pColorMeshInfo->m_nVertOffsetInBytes );
    else
        pMesh->SetColorMesh( NULL, 0 );

    for (int j = 0; j < pGroup->m_NumStrips; ++j)
    {
        OptimizedModel::StripHeader_t* pStrip = &pGroup->m_pStripData[j];

        if ( m_pStudioHdr->numbones > 1 )
        {
            // Reset bone state if we're hardware skinning
            pRenderContext->SetNumBoneWeights( pStrip->numBones );

            for (int k = 0; k < pStrip->numBoneStateChanges; ++k)
            {
                OptimizedModel::BoneStateChangeHeader_t* pStateChange = pStrip->pBoneStateChange(k);
                if ( pStateChange->newBoneID < 0 )
                    break;

                pRenderContext->LoadBoneMatrix( pStateChange->hardwareID, m_PoseToWorld[pStateChange->newBoneID] );
            }
        }

        pMesh->SetPrimitiveType( pStrip->flags & OptimizedModel::STRIP_IS_TRISTRIP ? 
            MATERIAL_TRIANGLE_STRIP : MATERIAL_TRIANGLES );

        pMesh->Draw( pStrip->indexOffset, pStrip->numIndices );
        numTrianglesRendered += pGroup->m_pUniqueTris[j];
    }
    pMesh->SetColorMesh( NULL, 0 );

    return numTrianglesRendered```
#

It's probably just that

fathom bolt
#

erm, HWSkin function just has a change to a condition inside of a numBones == 1 block, so it should be identical

#

SWSkin has some changes to load those two matrices

lament jacinth
#

Yep okay, that stuff I did clock, right now I am completely ignoring the swskinning path since we want hw skinning on the characters

#

So far it seems like all the studiorender stuff was tracked properly, that only leaves changes to the actual shaderapidx9 module which is where all these rendercontext stuff is being processed

#

If you're saying you had to fix the things so they actually worked with the hw skinning, I assume you have some changes to shaderapidx8 or meshdx8

#

I guess that's where my investigation will go next

fathom bolt
#

yep, there are a few small changes in there

lament jacinth
#

Alright, here's hoping they're easy to find hah

#

The concern i have is if you guys changed the size of any of the arrays

#

namely m_boneMatrix on CShaderAPIDx8

#

I think by default that matrix array only goes up to 50

#

but it'll get appended for every bone

fathom bolt
#

Not sure, but I see some code used to exist to shrink the numbones, and that got removed

#

specifically the MaxVertexBlendMatrixIndex section

lament jacinth
#

Yep was about to say, I was reading on this yesterday when I made that post about them changing to 256

#

Seems that MaxVertexBlendMatrices is in charge of basically the # of bone matricies applied to a vert

#

and MaxVertexBlendMatrixIndex is the total number of permissable bone matricies in the cache for the verts to reference

fathom bolt
#

it's 256 for SoftwareVertexProcessing, and a corrected value from the d3d9 driver for hardware

#

there's also a change from using D3DDECLTYPE_D3DCOLOR to D3DDECLTYPE_UBYTE4 when it comes to declaring bone indices in the vertex data

lament jacinth
#

I've solved MaxVertexBlendMatrixIndex by just recompiling the dxvk module to up the cap through there, will probably make a PR to have that be a d3d9.MaxVertexBlendMatrixIndex conf option later

#

but struct differences, I will see if I can find the right places to make the change

#

ComputeVertexSpec around there right?

#

That's the only spec change?

fathom bolt
#

it's in vertexdecl.cpp

lament jacinth
#

Yep okay, that'll be the right place

#

Now I have to find that through IDA lol

#

But at least it's a trivial change, a 4 to a 5

lament jacinth
#

Well I did find it and changed it, no luck on it. Seems like it's only listening to the first few bones entering because the ROOT works fine but every other bone is basically pinned to the "origin"

#

that's why my the belt shows up properly in that image, it's weighed only to the root bone and one other bone IIRC

#

Changing MaxVertexBlendMatrices crashes the game which is somewhat expected, I don't need that higher than 3 realistically

#

and I think source clamps it at 2 anyway because "the others are implicit"

#

alright what's left is something is stupidly still restricting the number of index matricies outside of MaxVertexBlendMatrixIndex

#

so I am just gonna hunt that odwn

#

because I tried loading other bones in place of index 0-2 and it DOES move the mesh properly

#

(The root uses 0-2)

lament jacinth
#

Completely stumped

#

Everything is assigned correctly, no clamp

#

yet it seems like only the few bones gets through

#

Doesn't help I can't fully see whats' going on for the fixed pipeline stuff

#

Loading the bone matrix drops it into a m_boneMatrix at the bone index slot

#

However that matrix is never referenced anywhere but in the SetVertexShaderStateSkinningMatrices and UpdateVertexShaderMatrix

#

which never get activated if I'm in hardware mode

#
{
    int matrix = MATERIAL_MODEL + iMatrix;
    if (FixedFunctionTransformChanged( matrix ))
    {
        m_pD3DDevice->SetTransform( D3DTS_WORLDMATRIX(iMatrix), &GetTransform(matrix) );
        m_DynamicState.m_TransformChanged[matrix] &= ~STATE_CHANGED_FIXED_FUNCTION;
    }
}```
#

@fathom bolt is this something similar in your function? This is in shaderapidx9.cpp

#

It's the only trace of pushing a transform into D3D9 from the SetFixedFunctionStateSkinningMatrices

#

Alternatively that SetFixedFunctionStateSkinningMatrices I currently have for( int i=1; i < MaxBlendMatrices(); i++ ) UpdateFixedFunctionMatrix( i );

#

I'll admit I don't fully understand what transform to push to d3d9 to fix this so it recognizes it as one of the BONE matricies

fathom bolt
#

there's a setSkinningMatrices not too far below that tho

#

Hmm, don't you have max blend matrices set to 4 or something? that function is only updating that many matrices per mesh, but I thought max blend matrices was per vertex.

you may need to set max blend matrices up to 256

#

since it's apparently being used as 'number of bones per mesh', not 'number of bones per vertex'

lament jacinth
lament jacinth
#

so if I increase that, it'll crash my game

#

that's why I was wondering what D3D9 functions I have to call to "load them in"

#

Did you guys modify the size of m_pMatrixStack?

#

also how does the D3D9 know what the "bone matricies" are if pushed?

#

I ask because since my problem is strictly with the array being too small

#

I COULD just push m_pD3DDevice->SetTransform( D3DTS_WORLDMATRIX(iMatrix), &GetTransform(matrix) ); manually

#

Is this the correct logic: int matrix = MATERIAL_MODEL + iMatrix;

#

basically any matrix pushed after the standard 10 is consider the first index of a bone?

fathom bolt
#

Well, when it comes to processing the matrices in Remix, we just grab:

const uint32_t startBoneTransform = GetTransformIndex(D3DTS_WORLDMATRIX(0));
memcpy(boneMatrices, d3d9State().transforms.data() + startBoneTransform, sizeof(Matrix4)*(maxBone + 1));
#

I don't see m_pmatrixstack mentioned anywhere in the commits we made

lament jacinth
#

I'll give that a try later

lament jacinth
#

For me // Total number of matrices NUM_MATRIX_MODES = MATERIAL_MODEL+1, which comes out to 11

#

Funny enough I also have const int NUM_MODEL_TRANSFORMS = 53; const int MATERIAL_MODEL_MAX = MATERIAL_MODEL + NUM_MODEL_TRANSFORMS; but it neveru ses the max material models, just the matrix mode one

fathom bolt
#

where is MATERIAL_MODEL defined?

#

or really where is NUM_MATRIX_MODES defined

lament jacinth
#

That one is actually in materialsystem/imaterialsystem.h

#

would be under the MaterialMatrixMode_t enum

fathom bolt
#

hmm, I don't have a materialsystem/imaterialsystem.h file

lament jacinth
#

maybe it's nested in public/materailsystem/imaterialsystem.h?

#

In any case I think if I just push the bone matricies onto the D3D9 stack without trying to load it from the array

#

it should work fine

fathom bolt
#

ah

lament jacinth
#

well "hopefully" work fine

fathom bolt
#

ah, yeah, we just have it defined as material_model + 256

lament jacinth
#

Yep that sounds right

#

It'd be the only possible way to pull it off

#

Well good news, it is tedious but clear how to fix it!

#

Did you guys manipulate NUM_MODEL_TRANSFORMS as well? I assume not if the matrix mode is the only one controling the bone indicies

fathom bolt
#

I think that needs to stay at 53. they're packing in a bunch of stuff, including those, in a space that's limited to only 256 entries.

lament jacinth
#

Got it

#

Thank you again for doing all this inspection

#

Lots of actionable work now

fathom bolt
#

๐Ÿ‘ got a bunch of meetings now, so I'm not sure when I'll next be able to reply

lament jacinth
#
    {
        D3DMATRIX* transform_matrix = (D3DMATRIX*)&IDENTITY_MATRIX;
        if (g_BONEDATA.bone_count > i)
        {
            transform_matrix = (D3DMATRIX*)&(g_BONEDATA.bone_matricies[i]);
        }

        m_pD3DDevice->SetTransform(D3DTS_WORLDMATRIX(i), transform_matrix);
    }```
#

Also in the above the tweak is that I am loading in identity matricies for the indicies > bone_count of that mesh

#

he still comes out as this ugly dude

#

Actually I DO see he's reacting to animations now, maybe my matricies are just fudged

#

Will give it a go

#

Yeah this is 100% progress, before every vert was static now i am getting an animation out of them, just transformed incorrectly

#

meaning I probably just have to fix the xforms!

fathom bolt
#

That could be something wrong with your matrix inversion and conversion. maybe you're multiplying the matrices in the wrong order or something

lament jacinth
#

Yeah I'm gonna just go from the bottom up again with the matrix stuff, considering they are now actually listening

#

As usual appreciate all the help with this

lament jacinth
#

I haven't offset anything towards the origin yet, so far i am just testing pushing transforms directly

#

The push code is as easy as

#
for (int i = 0; i < g_BONEDATA.bone_count; i++)
    {
        m_pD3DDevice->SetTransform(D3DTS_WORLDMATRIX(i), &g_BONEDATA.bone_matricies[i] ); // Is a (D3DMATRIX*)
    }```
#

And the matrix conversion is

#
    matrix3x4_t m_pWorldToBone;
    MatrixInverseTR(modelToWorld, m_pWorldToBone);

    matrix3x4_t new_BoneToWorld[512];
    for (int i = 0; i < pStudioHdr->numbones; i++)
    {
        ConcatTransforms(m_pWorldToBone, m_pBoneToWorld[i], new_BoneToWorld[i]);
    }

    matrix3x4_t new_PoseToWorld[512];
    for (int i = 0; i < pStudioHdr->numbones; i++)
    {
        mstudiobone_t* bdata = pStudioHdr->pBone(i);
        ConcatTransforms(new_BoneToWorld[i], bdata->poseToBone, new_PoseToWorld[i]);
    }
#

Where modelToWorld is confirmed to be the flat transformation of the players world position/angles

#

m_pBoneToWorld is the exact BONE WORLD POSITION

#

and bdata->poseToBone is the pose to bone transform

#

The process here is similar to that in CStudioRender::DrawModel

#

Take modeltoWorld, invert, apply to all of the BASE WORLD BONE POSITIONS, then ComputePoseToWorld

#

Which produces, in that file, m_PoseToWorld property

#

All I am doing is taking the final g_BONEDATA.bone_matricies[i] = ToVMatrix( new_PoseToWorld[bone] )

#

Where ToVMatrix simply turns a 3x4 matrix to a 4x4 matrix by adding a final scale row of 0 0 0 1

#

And that VMatrix is now aligned with the D3DMATRIX struct

lament jacinth
#

I checked the render state and it is correctly setting the vertex blending to the right weights depending on the mesh group's num bones

#

In that video you can see me crouching and kicking, you can see when I crouch there is a split up as you'd expect between my legs

fathom bolt
#

your naming is kinda confusing here, so I'm not really sure what I'm looking at - but I'm pretty sure you only need 1 concatTransforms per bone.

you can think of the starting matrix per bone like this:

world -> model -> bone.

but you want it to be

model -> bone.

So you need to extract world->model from each bone's matrix.

you also need to add that world->model matrix somewhere else.

You already have modelToWorld. inverting it will create worldToModel

So then you just need to call ConcatTransforms(worldToModel, m_pBoneToWorld[i], m_pBoneToWorld[i]) for each bone.

We also set the matrix mode to MATERIAL_VIEW and call pRenderContext->MultMatrixLocal(modelToWorld);. I believe that's adding the worldToModel matrix there.

Looking at your code, the first concatTransforms seems to be what I wrong... but you're writing it to a new location, which you then also concat some other transform to... and then I don't know what you do with that new bone array.

lament jacinth
#
matrix3x4_t new_PoseToWorld[512];
    for (int i = 0; i < pStudioHdr->numbones; i++)
    {
        mstudiobone_t* bdata = pStudioHdr->pBone(i);
        ConcatTransforms(new_BoneToWorld[i], bdata->poseToBone, new_PoseToWorld[i]);
    }```
#

For this concat here

#

This occurs after you do the previous concats and inversions

#

This is effectively the ComputePoseToWorld concat, except I am ignoring the bone mask since the entirety of the bones are in use for the model

#

From what I was seeing in IDA it doesn't look like that function got changed at all

#

It probably looks like this

#
    {
        // by definition, these always have an identity poseToBone transform
        MatrixCopy( pBoneToWorld[ 0 ], pPoseToWorld[ 0 ] );
        return;
    }

    if ( !pStudioHdr->pLinearBones() )
    {
        // convert bone to world transformations into pose to world transformations
        for (int i = 0; i < pStudioHdr->numbones; i++)
        {
            mstudiobone_t *pCurBone = pStudioHdr->pBone( i );
            if ( !(pCurBone->flags & boneMask) )
                continue;

            ConcatTransforms( pBoneToWorld[ i ], pCurBone->poseToBone, pPoseToWorld[ i ] );
        }
    }
    else
    {
        mstudiolinearbone_t *pLinearBones = pStudioHdr->pLinearBones();

        // convert bone to world transformations into pose to world transformations
        for (int i = 0; i < pStudioHdr->numbones; i++)
        {
            if ( !(pLinearBones->flags(i) & boneMask) )
                continue;

            ConcatTransforms( pBoneToWorld[ i ], pLinearBones->poseToBone(i), pPoseToWorld[ i ] );
        }
    }```
#

Dark Messiah doesn't have linear bones, so my version simplifies to just

#
        {
            mstudiobone_t *pCurBone = pStudioHdr->pBone( i );
            if ( !(pCurBone->flags & boneMask) )
                continue;

            ConcatTransforms( pBoneToWorld[ i ], pCurBone->poseToBone, pPoseToWorld[ i ] );
        }```
#

and of course, cut out the bone mask

#
        {
            mstudiobone_t *pCurBone = pStudioHdr->pBone( i );
            ConcatTransforms( pBoneToWorld[ i ], pCurBone->poseToBone, pPoseToWorld[ i ] );
        }```
#

What's left is the contents of pBoneToWorld and pPoseToWorld

#

In your comment you have ConcatTransforms(worldToModel, m_pBoneToWorld[i], m_pBoneToWorld[i])

#

In my case, the product of the transform goes to new_BoneToWorld

#

and my pPoseToWorld is just new_PoseToWorld

#

Seems the transforms are all aligned there

#

The only thing left is pRenderContext->MultMatrixLocal(modelToWorld);

#

which I can give a try

#

Although I'm just not sure, if you check when I'm crouching, my legs are clearly split, but there is still a hard anchor point for some verts

#

I'll try when I get home from work but that's what makes me confused about this whole process. It feels like at the least, I shouldn't have any of the verts anchored to the origin there

#

But this is all frankly a great learning opportunity for how the renderer works so maybe it does make that big of a difference

fathom bolt
#

The changes I'm looking at are just in CStudioRender::DrawModel, and I don't see anything about linear bones at all

#

The vertices going to 0 like that do make me think they're being multiplied by matrices with a 0 scale, which implies the matrices just aren't set at all

#

It may be useful to just print out the entire bone matrix list on the Remix side of things, to see what Source is actually sending down to dxvk. I wouldn't be surprised if some of your bone matrices are just all 0's

lament jacinth
#

That's a great idea. First time I tried that I didn't have all the bones entering, but now that I do I can actually look at the matrices

#

Will certainly be a fun night

lament jacinth
#

Looking at the debug makes me equally confused, because I DO see the scale is correct there

#

Firstly, I noticed the root bone in the source engine will enter and transpose itself before getting pushed

#
[07:04:55.610] info:  Set Transform [10]
[07:04:55.610] info:  Vector4(0.0572054, -0.998362, -0, 0)
[07:04:55.610] info:  Vector4(0.998362, 0.0572054, 0, 0)
[07:04:55.610] info:  Vector4(0, -0, 1, 0)
[07:04:55.610] info:  Vector4(112, 0, -255.969, 1)
#

This is a sample of the root bone matrix xform

#

Now here is the next bone up from there (bone 1)

#
**Raw Entry**
[07:00:59.891] info:  Set Transform [11]
[07:00:59.891] info:  Vector4(-0.340171, -0.765264, -0.546494, 23.5057)
[07:00:59.891] info:  Vector4(0.800827, -0.540374, 0.258211, -10.8099)
[07:00:59.891] info:  Vector4(-0.49291, -0.349811, 0.796663, 6.35701)
[07:00:59.891] info:  Vector4(0, 0, 0, 1)

**Transposed**
[07:04:55.610] info:  Set Transform [11]
[07:04:55.610] info:  Vector4(0.00206385, 0.999989, 0.00422093, 0)
[07:04:55.610] info:  Vector4(-0.999524, 0.00219274, -0.0307731, 0)
[07:04:55.610] info:  Vector4(-0.030782, -0.00415536, 0.999517, 0)
[07:04:55.610] info:  Vector4(2.16521, 0.184448, -1.69306, 1)
#

I've tried sending it in both as transpose and regular

#

So for the root bone [idx=10] that one is looking like the absolute world position and angle

#

and all other bones [idx=11,12,13,etc] are relative to the root

#

Does that look correct? 112, 0, -255.969 is the player's spawn position

#

this is what it looks like with the above type matricies. The correct position in the world but the stretch is to the origin still

#

pic of origin stretch

#

When I apply this last part pRenderContext->MultMatrixLocal(modelToWorld); it brings that big mess over to my position, but it doesn't fix what was wrong in the first place

#

When using that mult matrix stuff I also needed to change the root bone matrix to an identity

#

otherwise it WOULD use the absolute coordinates regardless

fathom bolt
#

Well, I don't see anything in particular wrong with that 1st matrix - it's roughly a 90 degree rotation and a small translation. What about the last matrix that should be set though, or the ones in the middle? Are you still only getting a small number of valid matrices then bad data?

fathom bolt
# lament jacinth and all other bones [idx=11,12,13,etc] are relative to the root

erm, actually now that I think about it, I'm not sure if this is right -every bone should be the transform from object space to that bone's position. When you capture to USD with Remix we transform them to be children of the root, but when the bones are sent to d3d9 I don't think any of the bone matrices should depend on any other bone matrix

#

you can look at RtxGeometryUtils::dispatchSkinning in remix's src\dxvk\rtx_render\rtx_geometry_utils.cpp to see how we actually handle the skinning - including a path that just does it on the CPU, which makes it easier to understand

#

and the bones are copied from d3d9 matrices here:
src\d3d9\d3d9_rtx.cpp D3D9Rtx::processSkinning

lament jacinth
#

Left is the bind pose of the model, right is the actual pose in the world

#

So if D3D9 needs the modelToBone transform, does it need the equivalent light green transform there?

#

world space origin -> world space position transform which would end up just being some offset, for example, Vector( 0, 0, 20) for a bone that is 20 units above the world space origin (his crotch :P)

#

I didn't include angles to keep it simple

fathom bolt
#

yeesh, bringing bind pose into this makes it even more complicated to think about.

#

I believe the specific matrix you need is:

the transform from the bind pose of the matrix to the animation pose, in model space.

#

I believe that the matrices source was sending was

the transform from the bind pose of the matrix to the animation pose, in world space.

#

Though I'm not sure if the root pose needed special handling

#

The actual transform from the root to the bone doesn't matter - that's actually pre-baked into the vertex positions.

(that relative transform does matter when animating a skeleton, but just to apply the skeleton to the vertices you only care about the deltas)

lament jacinth
fathom bolt
#

yeah... my understanding is that the matrices are already the correct values, just in the wrong space. so you shouldn't need to be thinking about bind poses, relative transforms, heirarchy, or anything like that.

lament jacinth
fathom bolt
#

you've got the world space delta, you need the model space delta

lament jacinth
#

So THIS one

fathom bolt
#

..... no. Do you understand what I mean when I say "delta in world space" vs "delta in model space"?

#

they're both the same transform:

#

but if the model space has a scale of 0.1, then the same transform could be +10 y in model space, or +1 y in world space

#

they're both "the wrist move up by a certain distance", but depending on the model's transform, "up" could be a different axis, and "certain distance" can change based on the scale

#

i.e. if the person lays down, the world space movement suddenly becomes +x, but the model space is still +y

lament jacinth
#

All that helps a lot and I apologize for my ignorance here

fathom bolt
#

no need for apologies, we all have to learn this stuff at some point

lament jacinth
#

HIS ASS IS FAT

#

BUT THIS IS PROGRESS

#

Seems there may have been some D3D flags that are not set

#

I added m_pD3DDevice->SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, TRUE);

#

and we got this far

#

I'm gonna try to find some docs

lament jacinth
#

Now there is still a unique problem to Dark Messiah here about batches that needs to be solved. Player models are split up into multiple LODs because they are literally what allows the full body presence to activate / deactivate

#

However the hashes are STABLE

#

I know it's the weekend but I'm gonna ping you anyway to tell you how much I appreciate the support and patience with me here @fathom bolt . Above and beyond, and an honor to have your time

#

All of the matrix math we did was correct, was literally the flag and the extra hidden step of transposing the matrix before it gets entered into D3D9, which is actually done by Source automatically but I missed it in my detour when I remade the function (it's one level up in Dark Messiah instead of same place)

#

Yeah this is a regular enemy model, the necro mage. Works perfectly

serene gale
placid hedge
fathom bolt
#

Glad to see you've figured it out!

As a workflow note - we've generally found it a lot easier for modelers and riggers to use the original source engine skeleton, rather than the captured skeleton. Though you may have to do a bit of remapping when importing that into Remix to get the bone indices to match up, it's much easier than trying to actually skin using a flat list of bones

lament jacinth
lament jacinth
#

Before I do the above feature request, the transferrence between our games is much easier, so I'll see what I can find ๐Ÿ™‚

#

Does VTMB support launching mod binaries?

placid hedge
#

I will test with you any way I can. I have some stuff that's low hanging fruit that doesn't need blendshapes/visemes

lament jacinth
#

or your patched version have a way for me to hook a function on launch?

placid hedge
#

How do you do that normally on your end?

lament jacinth
lament jacinth
#

The simplest way is to take the .exe file, and instead of loading launcher.dll, load some wos_vtmb.dll

lament jacinth
lament jacinth
#

^ For note this isn't blocking, just found it funny. In the process of making the index table in the mesh prim

fathom bolt
#

Those are just how omniverse renders bones by default, I believe.

lament jacinth
#

Is there some additional thing needed or is this just the toolkit making it look ugly

#

let me test it in game

fathom bolt
#

So for one, test it in game - I had problems sometimes where the toolkit didn't update the pose after changing the skeleton

#

2, in your mod.usda (or a layer therein), you want the skel:skeleton binding to be to the one in the capture, not the skeleton in the asset.

lament jacinth
#

Mark hello! I was not expecting you to answer

lament jacinth
fathom bolt
#

Also, big disclaimer that I haven't actually done this in about a year, and I'm away from my work computer so I can't actually check stuff right now

lament jacinth
#

Alright so I do it both in the layer, and the USDA

fathom bolt
#

though just to be sure - does your captured skeleton have a different number of joints from the skeleton in the asset you're ingesting?

lament jacinth
#

uniform token[] skel:joints = ["root", "root/joint1", "root/joint2", "root/joint3", "root/joint4", "root/joint5", "root/joint6", "root/joint7", "root/joint8", "root/joint9", "root/joint10", "root/joint11", "root/joint12", "root/joint13", "root/joint14", "root/joint15", "root/joint16", "root/joint17", "root/joint18", "root/joint19", "root/joint20", "root/joint21", "root/joint22", "root/joint23", "root/joint24", "root/joint25", "root/joint26", "root/joint27", "root/joint28", "root/joint29", "root/joint30", "root/joint31", "root/joint32", "root/joint33", "root/joint34", "root/joint35", "root/joint36", "root/joint37", "root/joint38", "root/joint39", "root/joint40", "root/joint41", "root/joint42", "root/joint43", "root/joint44", "root/joint45", "root/joint46", "root/joint47", "root/joint48", "root/joint49", "root/joint50", "root/joint51", "root/joint52", "root/joint53", "root/joint54", "root/joint55", "root/joint56", "root/joint57", "root/joint58"] would be my jints

#

a root bone + 58 seperate joints

fathom bolt
lament jacinth
#

The names are different

fathom bolt
#

setting the joints array is for when the asset skeleton and the capture skeleton doesn't line up. names don't matter, only the joint indices

lament jacinth
#

It has the same number, but the names are not exactly the same

#

Ahhh

#

Okay

#

It gives me a warning every time I tried to ingest so

#

wasn;t sure

fathom bolt
#

what's the warning?

lament jacinth
#

I said ingest, I meant "apply" but sec

#
 - Contains joint names that are not in the captured skeleton.  The joints will need to be manually remapped.
 - Skeleton: ['root', 'joint1', 'joint2', 'joint3', 'joint4', 'joint5', 'joint6', 'joint7', 'joint8', 'joint9', 'joint10', 'joint11', 'joint12', 'joint13', 'joint14', 'joint15', 'joint16', 'joint17', 'joint18', 'joint19', 'joint20', 'joint21', 'joint22', 'joint23', 'joint24', 'joint25', 'joint26', 'joint27', 'joint28', 'joint29', 'joint30', 'joint31', 'joint32', 'joint33', 'joint34', 'joint35', 'joint36', 'joint37', 'joint38', 'joint39', 'joint40', 'joint41', 'joint42', 'joint43', 'joint44', 'joint45', 'joint46', 'joint47', 'joint48', 'joint49', 'joint50', 'joint51', 'joint52', 'joint53', 'joint54', 'joint55', 'joint56', 'joint57', 'joint58']
 - Mesh: ['SK_Root', 'SK_Spine_1', 'SK_Spine_2', 'SK_Spine_3', 'SK_Spine_4', 'SK_L_Collarbone', 'SK_L_Shoulder', 'SK_L_Elbow', 'SK_L_Forearm', 'SK_L_Wrist', 'SK_L_Hand', 'SK_L_Finger_B1', 'SK_L_Finger_B2', 'SK_L_Finger_B3', 'SK_L_Finger_C1', 'SK_L_Finger_C2', 'SK_L_Finger_C3', 'SK_L_Finger_A1', 'SK_L_Finger_A2', 'SK_L_Finger_A3', 'SK_L_Thumb_1', 'SK_L_Thumb_2', 'SK_L_Thumb_3', 'SK_L_Finger_D1', 'SK_L_Finger_D2', 'SK_L_Finger_D3', 'SK_R_Collarbone', 'SK_R_Shoulder', 'SK_R_Elbow', 'SK_R_Forearm', 'SK_R_Wrist', 'SK_R_Hand', 'SK_R_Finger_B1', 'SK_R_Finger_B2', 'SK_R_Finger_B3', 'SK_R_Finger_C1', 'SK_R_Finger_C2', 'SK_R_Finger_C3', 'SK_R_Finger_A1', 'SK_R_Finger_A2', 'SK_R_Finger_A3', 'Sk_R_Thumb_1', 'SK_R_Thumb_2', 'Sk_R_Thumb_3', 'SK_Finger_D1', 'SK_Finger_D2', 'SK_Finger_D3', 'SK_Neck', 'SK_Head', 'SK_L_Leg', 'SK_L_Knee', 'SK_L_Ankle', 'SK_L_Heel', 'SK_L_Toe', 'SK_R_Leg', 'SK_R_Knee', 'SK_R_Ankle', 'SK_R_Heel', 'SK_R_Toe']
fathom bolt
#

ah. what happens if you don't set the joints array on you mesh at all? I think it'd be fine.

lament jacinth
#

Let's see

fathom bolt
#

the automatic remapping is just regenerating the bone indices array for when the bone order doesn't match, so it shouldn't be needed in your case. (tho just to check - did you also check that the bones in the capture are in the same order as the ones in your asset? I know some source engine skeletons do silly things like "right knee, left knee, right ankle, left ankle", and then blender auto re-orders those when you import them

lament jacinth
#

Yep everything is in the exact same orer it should be, had a translation table and we went through each one piece by piece

#

launching up the game now

fathom bolt
#

then yeah, the auto joint remapping that happens when you assign a replacement shouldn't matter.

lament jacinth
#

mark you genius

fathom bolt
#

that looks promising

lament jacinth
#

Apparently I was BUSTING it by modifying the skel:joints

fathom bolt
#

yeah, always try without first, when the joints are in the same order it just works - though the toolkit may not show it properly unless you reopen the scene or something

#

omniverse gets confused when one mesh is bound to different skeletons at different points in the composition arc

fathom bolt
lament jacinth
#

Still gotta fix some stuff but

#

we're MOVING

placid hedge
#

lets gooooo

lament jacinth
#

No RTX on/off yet, just enhanced assets

lament jacinth
#

one more couple

#

There is still some rigging that needs to be solved, if you check the knee/finger they going crazy

#

But overall, very happy that he's gotten his facelift

#

I can't ping my character artist since he isn't in this discord but kudos to Lerd ๐Ÿ™‚

tardy heart
#

Amazing, nicely done, I knew you could do it OK

sleek sparrow
#

delicious

hushed finch
#

@lament jacinth Congrats on the huge breakthrough for the source engine games. I hope @placid hedge's project gets that kind of facelift too.

placid hedge
#

We are going to test some stuff soon @hushed finch !

#

We have very similar issues since we are both on source, so we have some tests in the works :3

hushed finch
#

Yeah I've been following your project as well. Great stuff.

placid hedge
#

Characters are the big blocker, so you know I've been watching this thread like a hawk ๐Ÿ˜‰

hushed finch
#

Characters and other entity?

#

Like the fridge

placid hedge
#

anything skinned, so the fridge, the view models, third person weapons etc!

#

also you've very clearly watched my descent into madness on the fridge lol

#

dark messiah is one of my fav games so I'm excited for this project, but also greatful that @lament jacinth has been plugging away on things that have been plauging the VTMB community for years (skinned meshes)

hushed finch
#

Hahaha yes been actively lurking in the project threads and there are problems that you've been stressing about a lot.

placid hedge
#

hopefully this will alleviate some of that stress ๐Ÿ˜„

hushed finch
#

Wishing you the best @placid hedge

lament jacinth
hushed finch
#

Yeah it's wizardry to me when looking at assembly language and you have done quite a lot from the sky or sun detection problem up untill the skinning part from what I can remember.

#

Good luck on your future endeavours. Looking forward on the things you do.

placid hedge
#

he shmoovin'!

loud pawn
lament jacinth
#

You should ask the VTMB people

#

Also video is not loading for me for some reason

loud pawn
#

I posted there too, no one online at the moment I don't think. Thought it may just be a simple something I dicked up. ๐Ÿ‘

brittle steppe
#

Hey @lament jacinth , about this 3d sky pull request :

Do you know if there's a way in Dark Messiah to make the scale constant across all levels? E.g. in HL2 it's a constant 16.0, and wonder if it's possible to fix DM's variable sky scale on the game side, not in Remix DLL, as even the base 3d sky is tricky to maintain.

DM is on Source, so is it possible to compile client.dll / server.dll, or the Dark Messiah SDK is not open source?

lament jacinth
#

And while that may be particularly possible in DM, that is not a real solution for every source engine game because for example Garry's mod has a plethora of maps, many of which people go out of their way NOT TO give the source to

#

And additional info would be no to the SDK. There are also many closed source source engine games in a similar manner. VTMB, DM, and blade symphony, SIN Episodes, etc

#

The "fix" is to have remix change the scale by calculating it dynamically or by receiving information for the game

#

I pushed the first because that's something that requires no programming knowledge by a remixer. Second one is more reliable, but will require reverse engineering to get the engine structures

#

A more worthwhile option if you don't want to go the dynamic route is to have remix be able to store a table of scales per level

#

But then we have to talk about remix identifying what a level is hah

#

It may be possible with hashing the brush geo by positions?

brittle steppe
#

Yeah, would be nice to identify maps in Remix (as you said, e.g. by hash), that would give control over map-specific params like color correction

lament jacinth
#

Color correction isnt actually map specific EXACTLY. It is activated by an entity, so it's also trigger based

#

That's a whole other beast

brittle steppe
#

I'll try to bring a discussion internally about dynamic skybox size / map naming

placid hedge
#

Not sure if it helps or if my opinion carries a lot of weight here, but David's implementation is the only one that has actually definitively solved sky boxes for vampire.

#

I was able to test and experiment with his implementation for a little while and that period of time vtm skyboxes were implemented perfectly. Switching back to the latest broke them again immediately in strange ways. So it would be really nice to have much of what he's doing under the hood back on the main line because it solves a lot of other problems too.

lament jacinth
#

I think map naming/identifying is definitely the way to go as it's more inline with what you expect remixers to do : tailor settings, anchors, etc. The automatic route is convenient but if consistency or performance is needed, then it's a reasonable compromise

#

But if you go that route either those settings need to be something specified via USDA instead of conf, or configs need to be compoundable

brittle steppe
#

Solid reasons, and a great implementation for dynamic skybox size.

I'll try to figure out a way to merge internally / bring to discussion a map naming-identification

lament jacinth
#

Good luck! And I appreciate the work on the sky box stuff in general

#

It really does elevate the game to see that part of levels be path traced

#

Helps so much with the scale and immersion

deep nexus
#

Hey @lament jacinth , would love to pick your brain on how you applied the world backface culling fix. Trying to do the same for SiN Episodes and I'm getting stumped following SourceRTXTweak's github notes. I believe our Source Engine versions are pretty similar, I'm probably just getting lost in Ghidra and its right under my nose lol, sorry for the ping

lament jacinth
#

I couldn't rely on the RTX tweak stuff

#

Find the function it would be "near" and work with that

#

In my case I had two different bools that needed to be flipped

lament jacinth
#

I'll give you a better idea hwere it is in dark messiah later today

#

maybe it somehow laigns

#

aligns*

lament jacinth
#

@deep nexus alright

#

so I got a couple of notes here for my fixes

#

firstly, r_forcenovis

#

i have two bools for that

#

secondly, my leaf node cull check was REVERSED

#

It looks to INCLUDE, not exclude

#

I don't know the value of giving you specific offsets

#

but

#
Node cull: (engine)0x0BF8EA
Frustrum culls: (engine)0x0FD6C0, (client)0x0AD1C0
Leaf Cull: (engine)0x0BF785
World Cull: (engine)0x0BF8EA
Novis: (client)0x10781D
#

The novis lived in CViewRender::Render

#

you might be able to find a profile budget landmark to guide you

#

Some of the frustrum stuff I was able to lead to using the Client shadow manager

#

basically go backwards until you can find some landmark to start

#

and then hunt for a pattern of stuff

deep nexus
# lament jacinth and then hunt for a pattern of stuff

So far i've managed to find some references to r_frustrum and a couple functions that look promising but otherwise I'm still very nooby to any work inside Ghidra or other dll tools, most of my RE knowledge comes from Cheat Engine. Better than nothing but still lol. Thanks for the notes, I'll report back if I make any progress. I love your work with Dark Messiah btw, let me know if you ever need help or any testers, definitely something all the Source veterans will love

lament jacinth
#

I have a thread on knockout that doesn't get as much attention anymore, but documented a lot of the early reverse engineering process

#

I used to use ghidra, switched to IDA imo much better

#

The first few pages I specifically go in depth on landmarks and comparing the "shapes" of code

#

it is something I just do second nature now

fast sable
#

hey everyone

what's the progress on this game?

lament jacinth
lament jacinth
#

Explore the free city of Stonehelm and all that lurks within its shadows in this community remastered world! Use it with any of your favorite mods or maps, including the Restoration or Co-op mod!

The team is currently looking for members to help us make this dream a reality. If you're interested please visit our site and apply: https://www.wilt...

โ–ถ Play video
#

This is also part of a larger article if you care about Dark Messiah stuff, but it's big because with help from NVIDIA I'll be heading to Ubisoft's HQ to help get through code and SDK development

#

You can read about that here!

placid hedge
#

Big news! Very awesome stuff!

old halo
#

@lament jacinth you want any of this pinned?

lament jacinth
# old halo <@247936900466212864> you want any of this pinned?

Yes please! All of the future RTX compatibility patches for the game will be on the Dark Messiah RTX mod page. You'll need the Mod Launcher which is linked in the description. It is recommended to use Github (also in the descriptions) so I can keep tagging / fixing textures. But a stable release will always be dropped here

Link to DMRTX Page: https://www.moddb.com/mods/dark-messiah-rtx/downloads/
Link to Github Page: https://github.com/KingDavidW/DarkMessiah-RTX-Mod-Files

GitHub

Dark Messiah of Might and Magic gets the remix treatment! - KingDavidW/DarkMessiah-RTX-Mod-Files

unkempt mulch
#

@lament jacinth any chance you could release the (unfinished) enhanced assets?

fervent meteor
#

Hello guys, any advice to mitigate frequent crashes?

#

when i'm lucky it works for 2-3 minutes then it crash

lament jacinth
lament jacinth
#

Also make sure you're on the steam release

lament jacinth
#

If you send me the mdmp files I can check it out

fervent meteor
#

oh ok now i try to play again and i send the file

#

just to know, the only 2 mods you suggest are these 2 correct?

#

because i have seen some screenshot around with Restoration mod, but i didn't find it and i do not know if is necessary to improve the experience

lament jacinth
fervent meteor
fluid osprey
#

God, I love that game

#

and upscaling is pretty fun, albeit, it's pretty convoluted if you care about quality, it's not exactly one-click-go

fluid osprey
#

update with in game shot

fluid osprey
#

love the RTX displacement

lament jacinth
#

Love these pics

#

I thought those torches were white?

fluid osprey
#

but white really does not sit right with me

lament jacinth
#

Hah it's a magical fire!!

fluid osprey
deep nexus
# fluid osprey

Good stuff, this is probably how my 9 year old brain saw it when I played the demo for the first time. Are y'all working together on the mod or is this your own mod? Looks pretty dang good either way

fluid osprey
fluid osprey
#

second corner done ๐Ÿฅณ