#Dark Messiah of Might and Magic
1 messages ยท Page 2 of 1
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
Fuckin hell I spent so much time working on the dxvk I forgot to update the wiki to the remix 0.5 version
Will get that done when I get home later
Ah wonderful, thanks a lot!
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!
still working on the textures for the second pic but wanted to show off the lighting as it interacts with fire
bringing back the dark in dark messiah
very sexy
i need to see Sareth's mannequin lookin ass raytraced
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
Hurrah! I believe I added my name in the latest commit
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
Well, sending raw d3d9.dll from our side is kinda tricky.. So we would push it to main, then you will be able to set your feedback on it
Ah, yes, I see, I will transfer some of the commits to the internal branch for testing
No problem, let me know when it's up
Excited for a better way to do it especially if it has instance handling
Oooh keep us posted sounds helpful!
The message reminded me, @brittle steppe did it get pushed in yet?
Not yet, sadly. There are quite tricky corner cases, which are being resolved
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 ๐
@lament jacinth Sky is merged. Let's see if it works
Will check it out when home from work
I'm trying to replace the originals meshes , with some i modified , but when I replace them or add new references , the imported meshes dont load , and the original meshes disappear , how did you manage to import models , without them bugging out?
WHich mesh are you trying to replace
ive tried a guard npc , and some static objects .
i modified them in 3ds max
and ingested the usd models
make sure you are not changing your graphics settings
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
Scratch this
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
forever and always 16 in VTMB, I've been through every map now and can confirm it works in every one of them
@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 ?
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.
It's matching everything but refused to bind for some reason
is it matching the captured skeleton, or the original game's skeleton?
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.
Alright I'll look into that, I assume it's just in the capture
Does it match the hash name in the toolkit?
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.
Mesh_zxxx
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
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
@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
erm - if the meshes have no attached skeleton in the captures, then the game probably isn't using GPU skinning.
I believe in source engine that's a config variable somewhere...
maybe look through the engine docs for gpu skinning or hardware skinning?
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
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
Yeah it's old as hell so the commands that SHOULD exist don't, but I do know where it'll land in the code
Based on what you're saying it's probably recognizing the HW side, but enforcing SW
so I'll just flip that switch back
yeah, it's probably one of those cases where if you can find the switch and fix it, it'll suddenly work.
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?
shader model is already set to 0 here
well so much for that idea
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
or just set bSoftwareSkin to false in the first part of that if statement and see what happens ๐
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 โ ๏ธ
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.
Unfortunately the capture still isn't spitting out skeletons
back to searching
disabling hardware rendering in source stops the model from rendering so I have no idea what's going on
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
Is VTMB running on DX8?
Also what shadermodel do you have set
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?
In the DXVK.conf file, if you changed it there
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
Yep okay
looking at dxvk now
That's how I have it set
anything higher than that and nothing runs
haha damn mysteries
i did find a way in the console to force software skinning or whatever
mat_softwareskin or somet
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?
It may be tucked at origin but this is what you'd expect
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 :/
I love our same-but-different source engine versions!
Haha yeah... I hope our problems are same enough that we can help each other solve them lol
Right now I Just have to fish out what is forcing this to render in SW mode
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
Helps to know the solution will be stupid and obfuscated then!
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
I'm about to hop on and check this stuff now
Are the characters using blend shapes or something like that? HL2 and Portal split the blend shapes up to only be for the face, and use regular skinning for the bodies.
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
sorry was driving earlier, another oddity about vampire compared to say dark messiah is that we have no earthly idea what they did with blend shapes, they diverged from hl2's source engine and released in 2004 on the same day as hl2, so they made some internal changes to how blendshapes work and we have as of yet as a community not reverse engineered that
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
Anything that dynamically changes vertex positions on the CPU will invalidate geometry hashes (and will prevent skinned replacements from working)
Definitely feels like regardless if software skinning is on, things are still being moved on the cpu
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
Rtx remix bug?
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
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
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
very interesting stuff
Yeah that part is messing everything up, since you can't really rig a character in 52 chunks to several 2 to 3 bone groups and have it actually be usable or make sense haha
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.
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
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
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
I wonder if its a bug with remix, or maybe remix just sucks at capturing bones
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?
Performance, model limits, etc
I've actually not been able to get it to capture more than two incoherent bones myself
Vtmb I mean
@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
This is expected actually - I believe source engine only sends down the bones that have vertices actually bound to them, and it does that as an array of flattened root->bone transforms, so when Remix captures each bone it comes out as an immediate child of the root.
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
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!
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
...
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
right, so 15 bones in that specific order.
qc doesn't have something like $definebone?
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
Do you know how many bones show up in the remix capture?
2 bones for an entire character? thats... unexpected. sounds more like that's a rigid bind or something
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?
Erm, none of that is what I was expecting to see ๐ฆ
Are these bones all in one mesh_HASH prim?
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?
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:
you'd have to check the autocfg file in portal RTX, I don't remember the settings myself.
i'll take a look now
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
yeah, it's real weird, @lament jacinth does this happen on dark messiah?
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
Dude I can't even get that whole rig done, I only have three bones at most being captured. Root, joint1, joint2
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
whoa
I'm sure dark Messiah is just incredibly stupid, especially because I had to work around just getting the things to skin with hardware
Yeah, that's nothing like what Portal or HL2 do. The skeleton is finalized when the draw call happens
I figured as much hah
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
Now you see why I asked where in remix this occurs, I need to understand what Dark Messiah is actually sending it ๐ญ
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
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
well, geo hash will be one color per draw call, so if different parts of the mesh are different colors, that's different calls
Let me check that out right now
I'd expect your character to look somewhat like this
#1098843924602306601 message
not sure if this helps
but some hashes are ultra stable on characters
and some are not
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
what does it look like when you open up the capture USD and select the body mesh?
One second
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
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?
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
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)
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
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
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.
The compiler for Dark Messiah is so scuffed it spits out warnings for commands THAT ONLY WORK IN THEIR OWN COMPILER
Lol jesus
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
that sounds fun 
Let us know if you need any testing or info hunting from us etc.
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
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
I have a huge need for this as well and a backlog of assets that need it so I'll be able to test for sure
๐ 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.
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
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
Gotcha. I'll be ready to go when you need it. I've got some stuff I can test with
Art wise I mean
Is it possible to have that for Garry's mod?
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
@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
studio render? not sure what that is
There's already a Remix API that exposes all of the RtxOptions - and there's a PR up to expose all of those through the bridge, although when we went to integrate that we found some issues that are taking time to work through.
A module in the source engine in charge of processing the strips and constructingthe mesh basically
All right hopefully you guys figure it out
I would basically need to modify that config value live
It's been a few different people, but I think we were mostly making changes to the whole visleaf culling system, not to the actual mesh rendering
I see some custom stuff regarding how the models are actually ingested, and additionally how dynamic meshes are past through
you should chat with xoxor4d about his PR then
https://github.com/NVIDIAGameWorks/bridge-remix/pull/12
I know a couple games are already using that to change remix config values from game scripts
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
I think it's likely more a problem of memory, but I'll ask around internally
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
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
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
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
Yep this aligns with the R_StudioBuildMeshStrips changes
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?
I suspect it's more a matter of time - those changes were from years ago, and the guy who made them is spread thin working on.
I just went back and looked at some of the commits, and it looks like a big part is just getting the bone transforms to be in model space, instead of world space.
I'll get right on that. I got everything else set up from what Icould understand so that's definitely the last step
If i get far enough along this weekend I'll paste my code here and you can give it your opinion ๐
@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
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)
The description you gave helps and I appreciate it a lot. Honestly am having a hard time finding clear documentation for how the source engine references some of the d3d9 stuff.
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
yeah, the source engine was mostly written before the industry had settled on standard terms for a lot of that stuff
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
@fathom bolt would you mind just fact checking this while I fix my inversion
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
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?
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
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
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]
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
that's the modelToWorld matrix
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
Ahh so I'm assuming it's the m_rgflCoordinateFrame?
Yeah I'm unsure why, but it looks like after the change it unsticks the "max bone weight of 1" for DX7
I think one of them does unrestrict the bone matrix though
like the amount you can load in for reference
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
erm, dunno. In DrawModelArray it's pInstanceData[i].modelToWorld
not sure where else DrawModel is called from, and I don't have the ability to search this code
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
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
True
I'll retrace the steps
Also old source doesn't use DrawModelArray, but I see what you're saying about the arg
this is a lot more code than we had to write - I'm pretty sure you can just do Concat transforms with (WorldToModel, bone[i], bone[i]), instead of making a new bone array and copying over to it
Yeah the unoptimized version is just for me to be able to debug
and we had to build an exception when there's only 1 bone, to set the bone's matrix to the identity
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
what file is R_StudioCreateSingleMesh in?
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
so... at least the code I'm looking at doesn't use special anywhere in the file
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
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
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
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
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
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
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)
I'm not sure about BoneStateChangeHeader_t* bstate = pMeshGroup->m_pStripData[i].pBoneStateChange(j);.
if I had to guess it looks more like unsigned char* pBoneStateChange = (unsigned char*)pMeshGroup->m_pStripData + boneStateChangeOffset;
yep
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
sure, just that pBoneStateChange(j) looks like a function call, where that's a pointer in the code I'm looking at
Yeah that's an inline call decomposed to (BoneStateChangeHeader_t *)(((byte *)this) + boneStateChangeOffset) + i;
this being the stripdata
makes sense
Alright next questionable area is in CStudioRender::DrawModel
This one might be in studiorender.cpp
yeah, looking at that already
Yeah this is where you were taking the modeltoWorld transform, Inverse, and apply to all the m_pBoneToWorld I presume
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
right before the compute
I think they end up getting skinned as hardware regardless due to the SpecialStrip generator thing, but I have the benefit of detouring so I can do a custom path for > 1 bones
The part that is confusing me with this load model is that ordinarily i have pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->PushMatrix(); pRenderContext->LoadIdentity(); alone
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
But you guys seem to have some additional ``` pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PushMatrix();
Alright that's good to know
yeah, I don't actually know what the matrixMode thing is about
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 )
mayber - that XXX is the matrix that we're keeping around as a backup for SW skinning, from the comments
Ahhhh okay
actually we keep two oef those, a world matrix and a view matrix
Yep was about to say, the condition where numbones != 0 uses some other variable which looked like the modelToWorld xform you mentioned
yep.
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
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
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
yep, there are a few small changes in there
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
Not sure, but I see some code used to exist to shrink the numbones, and that got removed
oh, and yeah we had to change the maxBlendMatrixIndices. this link may be useful
https://learn.microsoft.com/en-us/windows/win32/api/d3d9caps/ns-d3d9caps-d3dcaps9
specifically the MaxVertexBlendMatrixIndex section
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
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
That is a BIG one
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?
it's in vertexdecl.cpp
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
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)
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
shaderapidx9.cpp what folder is that in? I don't see any changes in materialsystem/shaderapidx9/shaderapidx9.vpc, and the only place I can find an UpdateFixedFunctionMatrix is in shaderapidx8.cpp... and it basically matches the code you posted
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'
Yeah the setSkinningMatrices for me calls SetFixedFunctionStateSkinningMatrices
That may be it! Though I was afraid of that answer. The array I have is clamped at a size of 11
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?
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
It seems like I could definitely just pass it along manually in my own loop and avoid my restricted array
I'll give that a try later
It may be a change to NUM_MATRIX_MODES and NUM_MODEL_TRANSFORMS enums
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
That one is actually in materialsystem/imaterialsystem.h
would be under the MaterialMatrixMode_t enum
hmm, I don't have a materialsystem/imaterialsystem.h file
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
ah
well "hopefully" work fine
ah, yeah, we just have it defined as material_model + 256
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
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.
Got it
Thank you again for doing all this inspection
Lots of actionable work now
๐ got a bunch of meetings now, so I'm not sure when I'll next be able to reply
Alright so I rewrote the transform loading state through detour but it still isn't all the working. Both counts are at 256 as well. Now I have a question: In source these transforms are attached to a ID3DXMatrixStack. Do I have to push the transforms onto that respective stack so that the D3D9 gets them, or is it enough to call SetTransform like this
{
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!
That could be something wrong with your matrix inversion and conversion. maybe you're multiplying the matrices in the wrong order or something
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
@fathom bolt yep I'm clueless here
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
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
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.
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
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
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
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
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?
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
colors for convenience
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
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)
Yeah sorry about that hah trying to make it clear what I HAVE I believe
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.
So basically I'm looking for this part
you've got the world space delta, you need the model space delta
..... 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
All that helps a lot and I apologize for my ignorance here
no need for apologies, we all have to learn this stuff at some point
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
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
Can we do it to Garry's mod aswell
Dude hell yeah. You have been absolutely hammering his problem. Congrats for real on the breakthrough.
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
It is possible, it'll take some work but I think it would be more worthwhile to make the request directly to rubat. I'll make a feature request and we'll work from there
Thank you! YOU'RE NEXT
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?
I will test with you any way I can. I have some stuff that's low hanging fruit that doesn't need blendshapes/visemes
or your patched version have a way for me to hook a function on launch?
How do you do that normally on your end?
Thanks to Mark I have a full understanding of what we're doing so the hardest part will just be verifying the offsets
Right now, I have my own mod launcher I've developed for the community, but I would just need a way to have the game load some DLL at which I can create hooks / detours
The simplest way is to take the .exe file, and instead of loading launcher.dll, load some wos_vtmb.dll
We've got this set up but remix thinks the skeletons are.. lights hah
^ For note this isn't blocking, just found it funny. In the process of making the index table in the mesh prim
Those are just how omniverse renders bones by default, I believe.
So I remapped the skeleton in the ingested USDA file
Is there some additional thing needed or is this just the toolkit making it look ugly
let me test it in game
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.
Mark hello! I was not expecting you to answer
I was actually curious about this so that helps. Do I stil follow the method you linked in general about going to the ingested USDA and editing the skel:Joints there?
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
yes, I believe so
Alright so I do it both in the layer, and the USDA
though just to be sure - does your captured skeleton have a different number of joints from the skeleton in the asset you're ingesting?
Nope we've matched it all up to exact LOD it uses
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
erm, then you shouldn't need to set that manually at all
The names are different
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
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
what's the warning?
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']
ah. what happens if you don't set the joints array on you mesh at all? I think it'd be fine.
Let's see
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
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
then yeah, the auto joint remapping that happens when you assign a replacement shouldn't matter.
that looks promising
Apparently I was BUSTING it by modifying the skel:joints
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
And it's your hard work that got all this put together dude, don't give me the credit.
agree to disagree, so we'll split it down the middle and say your patience and help + my programming ๐
Still gotta fix some stuff but
we're MOVING
lets gooooo
No RTX on/off yet, just enhanced assets
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 ๐
Amazing, nicely done, I knew you could do it 
delicious
@lament jacinth Congrats on the huge breakthrough for the source engine games. I hope @placid hedge's project gets that kind of facelift too.
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
Yeah I've been following your project as well. Great stuff.
Characters are the big blocker, so you know I've been watching this thread like a hawk ๐
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)
Hahaha yes been actively lurking in the project threads and there are problems that you've been stressing about a lot.
hopefully this will alleviate some of that stress ๐
Wishing you the best @placid hedge
Yeah like Safe said my intent here is to get it working with VTMB, which is considerably easy, but tedious because I have to find the addresses that need the hooks
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.
he shmoovin'!
anyone know what I dicked up here. new mesh and texture seems to work when the stage lights I forgot in the level are hitting it and disappears otherwise. VtMB but figured someone lurking here may know.
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. ๐
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?
The constant scale is a mappers choice not a games choice, so without recompiling the maps, probably not
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?
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
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
I'll try to bring a discussion internally about dynamic skybox size / map naming
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.
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
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
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
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
I went through the 2007 leak myself and just tried to identify it
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
I'll give you a better idea hwere it is in dark messiah later today
maybe it somehow laigns
aligns*
@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
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
Would always love some co-op testers! And yes let me know what happens
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
hey everyone
what's the progress on this game?
There was a methodology shift by Hetman on the assets that are yielding some good results that I should be able to show at a larger scale soon!
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...
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!
The improved RTX compatability patch is also here: https://www.moddb.com/mods/dark-messiah-rtx/downloads/wos-dmrtx-compatibility-patch-a1-0212
Big news! Very awesome stuff!
@lament jacinth 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
@lament jacinth any chance you could release the (unfinished) enhanced assets?
Hello guys, any advice to mitigate frequent crashes?
when i'm lucky it works for 2-3 minutes then it crash
The enhanced assets are going to be the last of the stuff released. There are still the compatibility versions of the original assets
Be careful playing in full screen
Also make sure you're on the steam release
If you send me the mdmp files I can check it out
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
This is correct, I'll check your crash dumps this weekend
when you have time to check update me, thanks in advance!
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
update with in game shot
This game has got real atmosphere to it
Love these pics
I thought those torches were white?
yes, they are
but white really does not sit right with me
Hah it's a magical fire!!
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
I'm just doing it for my own pleasure for now
second corner done ๐ฅณ
