#bevy_trenchbroom

1 messages · Page 3 of 1

foggy glade
#

maybe bevy_trenchbroom is exporting geomtries with some kind of offset by mistake which makes geometries intersect?

#

just separating them by 0.125 (the minimum trenchbroom grid value) the issued is fixed

#

so it indeed screams to me like an overlap problem

urban zealot
#

@foggy glade just a heads up, Discord doesn't tell me when people post messages in here, so you should ping me in cases like this
If you make a minimal example and look in/send the map file, we should be able to see if a half-space-defining triangle is slightly offset like 0.0001
If nothing looks wrong there, quake-util and BTB imports geometry at double-precision, but by default Avian will convert to single-precision. If you aren't already, try setting Avian to use f64s with the features ["parry-f64", "f64"]

#

Also if you don't know #[*_class] implies #[derive(Component, Reflect)], but if you're doing that to be able to more easily tell that the type is a component at a glance I understand that

#

Also also you could just scale down all physics objects by a very small amount on spawn as a workaround

foggy glade
#

so that you can take a look into it, but I've been fiddling with more kinds of towers and it just doesn't happen

#

so idk, maybe it was a really weird edgecase

foggy glade
#

@urban zealot I don't know if I've got bad or good news:
It's not happening anymore, so now I'm not sure what was the cause. 🥲

#

I saved the .map file where the error happened but opening it now everything is stable

#

However while experimenting yesterday I coded something that you might be interested in implementing into bevy_trenchbroom

#

While trying to get stacks of rigidbodies to behave nicely Jondolf told me that cuboids might work better than convexhulls (don't really know why, I guess because of the simplicity) so I coded the edge-case so that if an imported solid_class is made up of a single brush that is also a cuboid, instead of generating a convex hull it creates a cuboid collider with its dimensions.

#

These towers have been generated by bevy_trenchbroom, no convex hulls 🙂

urban zealot
#

I should be able to put in the convex_hulls compound collider so cuboid colliders can exist in the same entity as convex as well!

dim warren
urban zealot
#

@foggy glade Give main a try
I also see you're adding the colliders afterward through an observer, you should be doing this through a spawn hook (hooks(SpawnHooks::new().convex_collider()) or set TrenchBroomConfig::default_solid_spawn_hooks) as it has direct access to the double-precision brush data. It's also where I implemented your idea

foggy glade
#

well at least I gave you the idea

#

hahaha

#

hope you had fun doing it 🙂

#

this was my version

#

chatgpt was of great help lol

#

and then I just grab the brush info and hand it over, which is a bit verbose but tidy

#

now it will probably be much much easier hahah

foggy glade
#

because I can add the convex hull with the spawnhook, but I cannot add arbitrary components

#

with arbitrary logic

#

maybe I should be using another mechanism instead of observers? Can I invoke a system with spawnhooks?

#

besides, is there any chance you might add a parameter that allows for scaling down the colliders just a tiny lil bit? in order for them to not touch/overlap when put next to each other.
Something opt-in ofc

#

although it works perfectly (thanks for the quick response ❤️) I really need this "margin/threshold" thing for it to work with avian...
the thing is that if the colliders are touching they won't be put to sleep, so I need them to be just a tiny bit separate

dim warren
#

Since brushes are supposed to be static geometry, this should not be an issue, right?

urban zealot
#

It does have the limitation that all components added in there must have #[reflect(Component)] so they can be spawned with the scene, I feel like either Avian or Rapier had trouble with that and rigid bodies, but I forget which

urban zealot
# foggy glade

Ah, I didn't even think about solving for rotation, my implementation only works for axis-aligned cuboids

#

I probably won't worry about it for now

foggy glade
#

I'm probably going to use a mix of:

  • brushes for generating the static "base" of the level
  • brushes for generating the interactive/destructible parts of the level
  • point classes for "props" or basically pregenerated meshes
#

at least that's the plan for now

foggy glade
foggy glade
#

not loving the idea of having multiple types of spawners, so for now I think I'll stick with the observer pattern and just resource to spawnhooks whenever I need something trenchbroom specific

urban zealot
urban zealot
dim warren
#

Textures can now be sent to the navmesh editor 🙂

#

This is a TrenchBroom test scene. Making sure at every step that it plays well with BTB!

#

I now have serialized versions of Mesh, Image, and StandardMaterial. Dunno if any of that may be of use to you too

urban zealot
dim warren
#

I could have made it part of that, but I would prefer it to be usable right now with pre-existing level design tools like BTB, so I made it work with remote inspection

#

Which is not yet part of the prototype

#

But I hope I can upstream this editor too, as a dev tool, until it becomes part of the editor prototype

dim warren
#

They asked me to detail what a brush-based workflow in the editor would look like and are on board with adding that at some point 🙂

#

@urban zealot if you feel like it, I believe you could share a lot of knowledge in this regard 🙂

rapid turtle
#

BTB?

dim warren
rapid turtle
#

Ah

urban zealot
urban zealot
dim warren
urban zealot
dim warren
dim warren
#

wow, that must have been an engineering challenge

#

But yeah as long as you can draw geometry quickly and see it in action, I'm also not attached to BSPs and brushes

dim warren
urban zealot
#

(am realizing i just woke up and conversation is hard, i'll come back later if i can formulate my thoughts better)

tidal galleon
#

I think something voxel based is the future where you can just sculpt right there.

Many people say "just use Blender" but navigating in that app with the camera sucks, same with every other 3D modeling software.

Unreal is trying to phase out their BSPs too but tbh I think I disagree on it.

I think a brush based workflow is great and I think they will find it is a mistake to phase out.

#

But it just needs to be modernized. Basically what I said, you draw a wall, then you can sculpt it

#

Then convert it to Nanite/Meshlet

#

And i say voxel because I should be able to just start punching holes in it without having to think about topology.

I want to be able to place down a pillar and start carving chunks out of it to weather it.

Voxels are also easier to work with programmatically. For example you could just procedurally weather things.

And then ya like I said you have a baking process in the end that converts it all to actual meshes, ideally high res ones like a Nanite/Meshlet system allows.

#

For what it's worth, Unreal is phasing out BSP but it's being replaced by in-editor modeling tools, so I guess it's the same philosophy just more modern.

#

Please keep me in the loop with this discussion, have lots of opinions!

#

For the voxels im thinking something very high resolution BTW, not Minecraft lmao.

Substance 3D Modeler is a good example of the workflow I am thinking. It's basically doing all the meshing on the GPU, so it's highly performant. But when you export it, it's converting it to a proper mesh with options to decimate it and stuff.

#

Then youre not bound to just making walls. You can make terrain, and not just heightmap bound terrain but caves, cliffs, hoodoos, whatever!

#

The real caveat is that it means larger files. But my mentality with that is, if you need the detail your files will be large, if youre just making Quake-like geometry then the meshing process would be efficient and thus the files would be small.

dim warren
#

Since all in this channel are interested in a brush-based or brush-adjacent solution landing in Bevy and the editor folks are broadly on board

#

We could add some of our thought to an issue so it’s easier to reference in the future

tidal galleon
#

honestly even if it's just basic basic stuff, being able to make stuff in-editor without jumping around between programs is important at the very least for early level design

#

but ya like I said I think it can be taken further with the intent that you can make a full detailed level all within the editor

tidal galleon
#

If we actually did go a sculpting capability route, could look at baby_shark for that.

It has a bunch of meshing algorithms, decimation, voxel remeshing etc.

There's also the csgrs crate

#

Ive dipped my toes in this area in the past and personally I want high poly capabilities, but thats when you need to start doing work on the GPU which I think likely complicates things

#

But ya there's plenty of arguments to make that if you need such detail just use Blender.

Im biased, I think I value doing everything in editor more than most

rapid turtle
#

Like they have all 3 of the major methods

tidal galleon
#

They all suck imo

#

Actually, the walking is cook

#

Cool*

#

But like have you actually tried to build a full map in Blender?

#

Although now that I think of it you could probably script what you need

rapid turtle
tidal galleon
#

Ah. Yeah its not good for it. Very good for making individual props and what not though

dim warren
rapid turtle
#

There's definetly improvements to be made but blender does have everything needed to make levels

#

Ive used far worse

#

Godot and the Creation kit both have far weaker scene creation tools yet people love em (well not CK.. People hate CK.. But amazing stuff in it)

dim warren
#

It's just not something I personally want to go back to since I've started using TrenchBroom

#

Definitely a question of taste as well

rapid turtle
#

I'll have to take a look at trench broom some point

dim warren
#

I can imagine people who work in Blender all day anyways really disliking the idea of switching programs for level design when they can do everything in one program

#

Which is totally valid

#

There's an elegance to not having the friction of exporting and importing models around the place 🙂

dim warren
dim warren
#

@urban zealot I just migrated to the newest BTB and wow! You improved the API a lot! Really good work, you should be proud of yourself 😄

urban zealot
dim warren
urban zealot
# tidal galleon I think something voxel based is the future where you can just sculpt right ther...

This is an interesting concept
With the different behavior based on degrees of axis-alignment, I'm assuming things wouldn't be on the same grid; a diagonal wall would be a different voxel volume than an axis-aligned one, kinda like how it's done in Teardown.
If that's the case, assuming we're going to be meshing (probably before an optimization pass) with a technique like duel contouring, since we would have to generate an SDF for the voxel grid anyway, we could expand it to be an SDF modeler with a voxel volume as just a possible SDF
I'm not too knowledgeable on the pros and cons SDF modelers though, all I know is that they exist and are cool

#

One thing I've always wanted in both brush and mesh modeling is the ability to be able to say, just place a doorway prefab in a wall, it'll automatically make a hole, and moving/removing it automatically moves/removes said hole
This would work really nicely with the composability of SDFs

dim warren
#

SDFs mentioned @granite hollow

granite hollow
#

SDFs?!

tidal galleon
#

I was looking at crater-rs today to see how easy if doable at all it is to get working with Bevy. TL;DR is it generates the marching cubes on the GPU with webgpu, vulkan, metal support. And then you can extract it on the CPU.

Might be an uber fast way to generate these things and then possibly run them thru some kind of mesh decimator.

Definitely some unanswered questions in this area

#

Have only read stuff tho, havent coded it

dim warren
tidal galleon
#

Hey, we like making maps. Hoorah

granite hollow
#

Is the goal to have a non-destructive workflow, or just use the additive properties you normally see with voxels?

urban zealot
granite hollow
#

Hmmm, yea want to keep a tree of operations around then rather than actual voxel values ... Then ideally have that be calculatable on the GPU

#

I remember there being some funny tricks to contain every part involved in the CSG to only the area it has influence over which could speed things up too

#

(+partial rebuilds of the mesh maybe?)

tidal galleon
#

ya make sense

#

although I think being able to rasterize is important too but should not be the expected workflow

granite hollow
#

I mean you could always rasterize it later and give up the non-destructive properties

tidal galleon
#

still learning, been reading up on it a lot today

dim warren
#

Hehe, BTB 0.9.2 with the optimized cuboids uncovered a bug in rerecast

#

had to do a new breaking release

#

Great that it happened on that specific PR and I was able to diagnose the problem! Would have been annoying to randomly run into this one day in some random project 🙂

rapid turtle
dim warren
#

brush-based workflows are not inherently better, they just offer a different set of tradeoffs compared to prefab-based editors or modelling software 🙂

#

In particular, they allow you to prototype things extremely quickly, if that workflow vibes with you

#

Sec

#

This is for example how you create a fairly simple corner in TrenchBroom

#

there's a lot more that you can do, but that's the basics

#

for example, this scene in Foxtrot was made with TrenchBroom

#

Note how the brushes here are polyhedra, e.g. the bevels here

#

You of course don't need a brush based editor for this. You could also create this in a modelling editor like Blender and then import it as a prefab. Or your prefab editor offers modelling capabilities

#

But a brush-based editor will make this specific workflow of simply drawing your level out of convex polyhedra extremely easy, which is great for prototyping. I can whip something up for grayboxing in seconds. If I don't like it, I can change it in seconds again, all hot-reloaded (no need to e.g. reexport stuff from Blender)

#

Again, you can have this with a prefab-based editor too, it's just a different set of tradeoffs 🙂

#

And for some people like me, these tradeoffs play right into the kinds of levels we wish to make, enabling us to create things really quickly

#

Here's for example the developer of Blood Thief talking about how he uses TrenchBroom: https://www.youtube.com/watch?v=DMJ7i4nuMVA&t=297s

In this Devlog I talk about how I'm using Godot and Trenchbroom to make levels inspired by games like Quake!

➤ WISHLIST BLOODTHIEF ON STEAM: https://store.steampowered.com/app/2533600/Bloodthief/
➤ JOIN THE DISCORD: https://discord.gg/aU5naj2fgY

Welcome to the latest video for Bloodthief: My Retro first person melee action game made wit...

▶ Play video
#

Note how he uses it to quickly draw little zones and areas that trigger things 🙂

#

And at the risk of repeating myself, this is not something unique to TrenchBroom, just something that is really frictionless to do in that editor.

rapid turtle
#

note im not using any shortcuts in that

rapid turtle
#

I already had that in my features wish list lol

digital heath
#

trenchbroom does feel way nicer than blender for this sort of blocky design ime

dim warren
#

Again, you can certainly set your Blender up to emulate all of these

#

But I kinda want to just work on my level instead 😄

rapid turtle
#

mhm
blender's out of box experince doesnt focus on that
but it does have most of that if you set it up

#

but safe to say we can def have brush tooling

dim warren
dim warren
rapid turtle
#

mhm and we could improve on this... the texture map adjustments couldve been a simple shortcut + mouse grab/scroll to resize and move

#

not just copy the workflow but accelerate it.

dim warren
#

The cut tool works pretty much like in Blender, with the catch that it also is always grid-snapped

#

One cool thing to note at the end is how I cal alt-click the texture to align them with another

#

Note how in the last few seconds, the wooden board texture aligns across faces

#

That is a pretty widely-used feature in brush-based

rapid turtle
#

what determines it? as you manip the mesh it just starts auto moving to the mesh
is it based off the texture? assuming direction is right side up oriented

dim warren
#

Then alt-click on another face to make sure it aligns with that reference

rapid turtle
#

hmmm

dim warren
#

But that's less important

rapid turtle
#

hmm i see

covert heron
#

holy crap that embed failed

dim warren
dim warren
dim warren
#

@rare chasm you mentioned something about bevy_trenchbroom's scene hierarchy

#

Did I understand you correctly in that you suggest adding a child entity to the scene that itself contains the rest of the entities?

rare chasm
# dim warren Did I understand you correctly in that you suggest adding a child entity to the ...

my idea was basically to allow scenes to setup relationships with the "owning" parent of the scene.
so a scene would be Scene {world: World, parent_id: Entity } and when spawned into the main world, the entity mapper would map all references to parent_id to the parent under which the scene is spawned.
then a scene loader like gltf could internally set up all the entities with AnimationPlayers with an AnimationPlayerOf(parent_id) and when spawned, an AnimationPlayers([...]) would automatically be inserted into the parent entity. this means "spilling" some parts of the scene out, which might be weird/bad, but I think as long as it's just relationships and not arbitrary components, that's fine.

dim warren
rare chasm
#

I don't think my idea will work with bsn scenes currently

#

so it's probably not the right solution

dim warren
#

Could BTB also implicitly load the scene from the .map and .bsp files?

urban zealot
dim warren
#

@urban zealot you may like this!

#

I managed to implement path corners using relations 🙂

#

every target you set on an NPC results in a Target(Entity) relationship

#

And that target may be a path corner

#

path corners themselves can have a NextPathCorner(Entity) relationship to the next one

#

Nothing fit for upstreaming since it requires calling .observe(link_a_bunch_of_stuff) on your scene

#

though maybe that observer could check if it was called on a trenchbroom scene specifically?

#

Since it needs to run after all path corners have been spawned

urban zealot
dim warren
#

it's all regular target and targetname from TB's perspective

urban zealot
#

Oh well

dim warren
#

But I thought target could only be a single entity in TB?

urban zealot
dim warren
#

yeah then n:m is necessary hmm

#

Some people have done workarounds for that, but I'm out of the loop what exactly

dim warren
#

@urban zealot what's the state on 0.17 RC?

#

Do you need help?

#

Dunno if you've seen it, but we have auto type registration now, so we can remove that from our instructions 🙂

urban zealot
#

Even if I'm not adding major features, I try to keep it as up-to-date as fast as possible :)

tight crow
#

Does bevy_trenchbroom uses gltf custom properties to export bevy components ?

alpine glen
#

I tried setting up bevy_trenchbroom and the files that got written out using the default plugin configuration and information in the readme seem totally disconnected from the map file. There's also no information in the readme that describes how to fix the connection or how to "select" the files that get written out by the plugin.

dim warren
#

Then, when you create a new map, you can select your game from the list

alpine glen
#

(also yes that is what I named my project lol)

dim warren
alpine glen
dim warren
#

And just to make sure, there weren’t any write errors?

alpine glen
#

and there doesn't seem to be any settings that will like "correct" that one a "generic" game is created

#

no errors that I can see, everything is logging success

#
2025-09-15T20:42:33.631303Z  INFO bevy_trenchbroom::config::writing: Successfully wrote TrenchBroom game config to /Users/chris/Library/Application Support/TrenchBroom/games/skein_trenchbroom_yay
2025-09-15T20:42:33.631872Z  INFO bevy_trenchbroom::config::writing: Successfully wrote TrenchBroom preferences to /Users/chris/Library/Application Support/TrenchBroom/Preferences.json
dim warren
#

Are there other dirs in /Users/chris/Library/Application Support/TrenchBroom/games/ ?

alpine glen
#

nope

dim warren
#

oh nvm there wouldn't be

#

Okay, could you check your /Users/chris/Library/Application Support/TrenchBroom/Preferences.json?

alpine glen
#

leaving everything in that directory also feels very strange, like how would I share the work with someone else?

dim warren
#

this is how mine looks

alpine glen
dim warren
#

Other can just run the game once to fill the dir

#

but ideally that shouldn't be necessary imo

dim warren
#

I'm puzzled 🤷‍♂️

alpine glen
#

okie well I might get back to debugging it later then lol

#

has anyone else worked with trenchbroom on a mac?

dim warren
#

TB is definitely tested intensively on macOS, as its developer uses macOS pretty much exclusively

#

bevy_trenchbroom on the other hand, I don't know

#

It's possible some path is being written in a wrong way

alpine glen
#

yeah, that was what stopped me and made me ask here instead. The readme claims it "just works" and doesn't supply any information about how its supposed to work

dim warren
urban zealot
urban zealot
alpine glen
alpine glen
urban zealot
urban zealot
alpine glen
#

well I don't know what was going on but after a few more restarts of the application it showed up

dim warren
#

I think you ran into a TrenchBroom bug?

alpine glen
#

anyway, I was trying to confirm skein/trenchbroom working together and it does officially. gltf exported using skein, used in a trenchbroom level, loaded through trenchbroom's .map format

dim warren
alpine glen
alpine glen
dim warren
#

Since I remember in another older project I used Blenvy to place some markers in a model for where constraints should be placed

dim warren
#

But yeah I'm very excited to have a reason to use Skein

dim warren
#

Literally everything I've seen from it looks lovely

alpine glen
dim warren
#

@urban zealot FYI avian has a 0.17 branch now. I can open a PR to the 0.17 BTB branch tomorrow for it

#

I don't think we are affected by any breaking changes in Avian

#

but we need to bump it for the avian feature

urban zealot
dim warren
#

then I'm almost unblocked for the full rerecast stack

#

TrenchBroom is just used in some examples, but it would be neat to port those too so we can verify that everything is working together

urban zealot
dim warren
dim warren
#

@urban zealot trying out the 0.17 branch RN and I get this:

#
2025-09-16T17:27:24.194975Z ERROR presentation::third_party::trenchbroom: Could not write TrenchBroom preferences: Failed to deserialize preferences to JSON from /home/hhh/.TrenchBroom/Preferences.json: EOF while parsing a value at line 1 column 0
#

my prefs.json looks fairly normal:

{
  "Controls/Camera/Look speed": 0.4949494898319245,
  "Controls/Camera/Move forward": "D",
  "Controls/Camera/Move right": "H",
  "Controls/Camera/Move speed": 0.2929292917251587,
  "Controls/Camera/Pan speed": 0.4949494898319245,
  "Editor/UV lock": true,
  "Games/Generic/Path": "/home/hhh/git/bevy_trenchbroom/assets",
  "Games/Quake/Path": "/home/hhh/.local/share/trenchbroom",
  "Games/Quake/Tool Path/light": "/home/hhh/.local/share/trenchbroom/tools/current/light",
  "Games/Quake/Tool Path/qbsp": "/home/hhh/.local/share/trenchbroom/tools/current/qbsp",
  "Games/Quake/Tool Path/vis": "/home/hhh/.local/share/trenchbroom/tools/current/vis",
  "Games/Thief Sense Demo/Path": "/home/hhh/git/thief_sense_demo",
  "Games/avian_navmesh/Path": "/home/hhh/git/avian_navmesh",
  "Games/bevy_rerecast/Path": "/home/hhh/git/rerecast",
  "Games/bevy_trenchbroom_example/Path": "/home/hhh/git/bevy_trenchbroom/example/map_loading",
  "Games/boomchain/Path": "/home/hhh/git/chainboom",
  "Games/foxtrot/Path": "/home/hhh/git/foxtrot",
  "Games/presentation/Path": "/home/hhh/git/presentation",
  "Games/trenchbroom_playground/Path": "/home/hhh/git/trenchbroom_playground",
  "Games/your_game_name/Path": "/home/hhh/git/avian_navmesh",
  "Map view/Entity link mode": "transitive",
  "Texture Browser/Icon size": 2,
  "render/Font size": 17,
  "updater/Ask for auto updates": false,
  "updater/Check for updates automatically": true,
  "updater/Include pre-releases": true
}
#

let me just verify that the old BTB version works

#

Oh okay nvm

#

I'm a silly goose

#

this was an old project I just migrated from BTB 0.16(!)

#

and it had a manual implementation of the prefs writing

#

removed that and now it works haha

#

all good 🙂

hushed forge
#

I wonder if it would be possible for bevy_trenchbroom to automatically traverse a class's required components to add base classes

hushed forge
#

okay you can get a list of transitively required components in an exclusive system

dim warren
hushed forge
#

yeah :3

urban zealot
# hushed forge I wonder if it would be possible for bevy_trenchbroom to automatically traverse ...

We switched away from this because some required classes aren't QuakeClasses (we were getting the required components from the macro).
That said, it just came to me that now that we use Bevy's reflection system and have ReflectQuakeClass, with what you're saying we could pretty easily only use the required components that implement QuakeClass
On the other hand, I think having the base(...) attribute with all the other class attributes feels/looks nicer, but I would love to hear if you have a different opinion!

hushed forge
urban zealot
hushed forge
#

so can you set a non-quakeclass component in base()?

hushed forge
#

right, that's the point I was trying to make

#

(probably should've used a different component for my example 😅)

urban zealot
#

Hmm, I just re-read your messages like 5 times I still don't know what you're trying to get across, sorry!

#

I don't know if my brain is failing me but it is not coming to me

dim warren
hushed forge
#

e.g C could be Transform and B could be a first-party bevy component that requires Transform but doesn't implement QuakeClass

urban zealot
hushed forge
#

yeah sorry for being confusing 😅

clear dagger
#

Thought I'd ask here, sorry if it's not super on topic. Was just wondering if it was possible to get the kind of "quad"y style ground that old school runescape has in trenchbroom?

urban zealot
#

(Also I think it's on topic enough)

urban zealot
#

Replicating that look exactly would probably be a little challenging, but you could get pretty far by

  • making a grid of brushes in TB and moving the vertices up and down to your liking
  • not smoothing brush normals (default behavior)
  • having the texture be a scaled up grass-colored gradient, and moving each face around a little in texture space to further disconnect each quad
clear dagger
dim warren
#

Only thing left is

#

any idea what might have caused this?

urban zealot
dim warren
stable crater
#

Hi @urban zealot I'm loading Quake1 BSPs and have started getting triggers etc all set up. The one thing that's really baking my noodle is how to work out the end / target positions for doors and platforms. Do you have any guidance or pointers to docs / examples? I think I'm getting confuised about what is in Bevy space and what is still in Quake space (eg, the lip value) 🙂

urban zealot
# stable crater Hi <@329762623304499202> I'm loading Quake1 BSPs and have started getting trigge...

Sure! Any custom value you have as a property that you want to use for distance (lip value) will need to be converted to Bevy space, which you can do via a function from TrenchBroomConfig
For the rotation, assuming you're doing it the Quake-y way, Quake does it by having rotation fields like angle, angles, and mangle not apply to brush geometry, and instead they get used for the open direction. This is emulated in BTB and you can just get the entity transform's forward direction

You could also do a more general path-based system where the object slides to the position of another, and that shouldn't have to care about Quake space at all

#

We do plan to add a func_door-like class called func_slide, but the project is on maintenance mode from me at the moment, so I haven't gotten around to it

dim warren
#

Random reminder that BTB is very cool cooltofu

#

I've been heavily prototyping the last few weeks and it's been a breeze

dim warren
urban zealot
dim warren
#

Maybe I'll also upstream shitty DIY n:m target and targetname, we'll see

urban zealot
stable crater
#

very helpful thank you @urban zealot ! so, for basic platform moving I can just convert the lip value and move the transform forward? Is this the child transform where the mesh / collider is on?

urban zealot
stable crater
#

That worked a treat, thank you! I can now navigate from start to finish with most levels. That’s far enough for tonight 😄

stable crater
#

@urban zealot I spent a few hours today trying to work out why one of the platforms in Quake E1M1 was going left rather than up. I think there might be an issue with default_global_spawner - I've written a workaround system for my project which seems to fix it. Do you want me to put my notes here or create an issue on github? Tbh I'm not 100% sure I'm right ... all this ye olde Quake map lore is 🫠 (I used to find it easy in the 90's 😄 )

dim warren
#

#1124043933886976171 message

#

I don't think it is, since that __base thingy doesn't have anything to do with glTFs

#

but there's still a connection, maybe?

urban zealot
urban zealot
urban zealot
urban zealot
stable crater
stable crater
#

It was quite a fun bug to find. Walked up to a platform, pressed the button to go up....got punched through a wall 😄

urban zealot
#

@stable crater I'm trying to recreate this, can you point out an exact broken door on E1M1?

stable crater
#

It's the platform in the second room (before the water) ..here's the screenshot

#

the green arrow is the direction the platform moves

#

After my hacky work around (and a system that sets the doors / platforms into the right place)

#

The other platform and door transform forwards are correct

urban zealot
urban zealot
urban zealot
#

also some debug outputs from BTB confirming this

Ok("func_plat"): {"classname": "func_plat", "model": "*7", "sounds": "1"}
Ok("func_plat"): {"spawnflags": "1", "height": "400", "classname": "func_plat", "angle": "-1", "model": "*22", "sounds": "1"}
#

(those are the only 2 func_plats in the level)

dim warren
#

@urban zealot I'm playing around with steam audio integration, and I need to create trimeshes of the brushes, along with their materials

#

I know that brushes in Bevy have a Brushes component

#

And from there, I can get the individual surfaces

#

and each surface has a String for its material. That works great already

#

But I'm not entirely clear on how I would turn that into a trimesh for that given surface

#

Or maybe there's an easier way to accomplish this?

#

IIRC we already create a single Bevy Mesh per material, no?

#

If so, I could just reuse that

urban zealot
urban zealot
dim warren
urban zealot
#

which steam audio integration are you using?

dim warren
dim warren
#

but either my setup is borked, or the recent updates broke it

#

Or cpal is weird

#

The 0.16 demo with audionimbus works for me, the non-bevy CPAL demo on the current main of audionimbus does not

#

pinged the author

urban zealot
# dim warren I'm *trying* audionimbus

Sweet, I had heard of it, but never got around to using it
I found other previous bindings really clunky, and I'm pretty sure this one is a lot better

urban zealot
#

IMO audio is one of the most slept on areas of modern games, hearing Steam Audio for the first time in HL:A kinda blew my mind

dim warren
#

very relatable haha

dim warren
urban zealot
dim warren
#

We have one big compound collider for everything, right?

urban zealot
dim warren
urban zealot
#

It might be a little hacky, but you could try to just use MeshRaycast

urban zealot
#

built-in Bevy raycasting system param

dim warren
#

OOOOOOH

urban zealot
#

you didn't know about that ??

dim warren
#

That would work great 👀

dim warren
#

but I never used it directly, no

#

Let me think, is there any limitation there?

#

there's even a filter

urban zealot
#

Yeah the API is really nice in my personal experience

dim warren
#

so I could hack together something akin to collision layers

#

And I suppose the Entity I get back is the one holding the Handle<Mesh>?

dim warren
#

that's perfect

#

thanks for that suggestion

urban zealot
#

NP!

dim warren
#

It should give an ordered list of faces that one can reuse for the mapping

urban zealot
dim warren
#

yeah let's do the mesh raycast then

#

Though I wonder if there is even anything to upstream in that case hmm

#

Like, should we have a BrushMaterialRayCaster? That seems like overkill

dim warren
#

Maybe the issue is then best addressed by just documenting somewhere how one could do it

#

or adding an example for the non-avian solution

#

or both, actually

urban zealot
#

I like that idea, let me know after you implement it just in case there's any extra implementation details to worry about

dim warren
#

Though hmm, not sure how well the avian solution is doable without upstreamed code

dim warren
#

But first need to figure out this audionimbus business haha

urban zealot
dim warren
#

Not sure I actually need anything beyond footsteps

#

Hmm, I guess putting down loot on carpets should be quieter than on stone

#

but that's very much optional

#

the footsteps are vital

#

(I'm recreating Thief's AI)

urban zealot
stable crater
# urban zealot (those are the only 2 `func_plat`s in the level)

Really interesting! Thank you for digging into this. To save you from my horrible code, my current hack does this :

1. Reads the `angle` value from MoveableFunc (which is passed from the map)
2. Calculates the expected rotation using angle_to_quat (usingfunction from bevy_trenchbroom)
3. Compares expected vs actual Transform.rotation
4. If mismatch detected: Fixes Transform.rotation and logs the correction

So it assumes the angle is right. - Since I wrote the code, let's assume it's not 😄 - Looking at my entities for FuncPlat (which sets MoveableFunc value) I can see this line
let angle = view.src_entity.get::<f32>("angle").unwrap_or(-1.0);
Was this a wrong assumption? I might have got confused with Quake specs

(Note: in my buttons and doors I'm doing let angle = view.src_entity.get::<f32>("angle").unwrap_or(0.0);)

stable crater
dim warren
#

This is just porting the audionimbus stuff to the newest Bevy and co

#

next step: seedling integration, then TrenchBroom integration super_bevy

stable crater
#

@dim warren on the subject of platforms - could recast/rerecast handle linking navmeshes that would require a platform?

dim warren
#

Just attach a collider to the platform and rerecast does the rest 🙂

stable crater
#

🤯 that’s amazing, how does it know that the platform can go up/down bridging the two nav meshes?

dim warren
#

Future versions should be smart enough to only regenerate the parts that actually changed, but for for regenerating everything is surprisingly fast

urban zealot
# stable crater Set the default angle to `0.0` and disabled the work around system and the arrow...

Did not know Quake defaulted specifically func_plats to have a default angle of up
I'm currently very hesitant to upstream a hack for that specifically, but I can (and already have on main) make a simple change that would let you put a hack at the start of the global spawner much easier with something like this in your TrenchBroomConfig

.global_spawner_fn(|prev_spawner| Arc::new(move |view| {
    if view.class.info.derives_from::<MoveableFunc>() && !view.src_entity.properties.contains_key("angle") {
        view.world.entity_mut(view.entity).insert(Transform {
            translation: read_translation_from_entity(view.src_entity, view.tb_config)?,
            rotation: angle_to_quat(-1.),
            scale: Vec3::ONE,
        });
    }

    prev_spawner(view)
}))

It also looks like you have a custom class MoveableFunc that provides angle, the default of which can't be considered in global_spawner out of the box, just in case you had that impression

urban zealot
stable crater
stable crater
dim warren
#

There’s just not yet an option to add them visually in the editor

#

But it works programmatically

stable crater
#

Im going to have to work out a way of turning all the quake platform types in to off mesh connections 🫠

#

If rerecast is as fast as you say, a bit of brute forcing is going to get me most of the way

dim warren
dim warren
#

@urban zealot #art-audio-animation message

#

we did it!

#

It should be very doable to integrate this fully with TrenchBroom 🙂

#

will continue tinkering with that

urban zealot
dry portal
#

@urban zealot @dim warren is anyone working on the bevy 0.17 upgrade?

dry portal
stable crater
#

Just updated to 0.17 using the latest branch. I'm getting a crash on loading one map (good 'ol E1M1.bsp) with :



thread 'Async Compute Task Pool (1)' (103272) panicked at C:\Users\Robin\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-26.0.1\src\backend\wgpu_core.rs:1327:26:
wgpu error: Validation Error

Caused by:
  In Device::create_render_pipeline, label = 'pbr_opaque_mesh_pipeline'
    Error matching ShaderStages(FRAGMENT) shader requirements against the pipeline
      Shader global ResourceBinding { group: 2, binding: 100 } is not available in the pipeline layout
        Binding is missing from the pipeline layout

This looks like one of the shaders being used hasn't been updated to use the new group
Most users who are not using mid-level render APIs will simply need to switch their material bind groups from @group(2) to @group(#{MATERIAL_BIND_GROUP})

I've deleted all my shaders so this might be Trenchboom. Perhaps one of the common level materials / shaders (eg sky) - is there a way I can turn these off to test?

stable crater
#

I've updated the liquid and quake_sky shaders and it fixes it for me. It's a private repo so can't make a PR - so here they are 🙂 (or add me robinlacey and i'll push)

urban zealot
urban zealot
dim warren
stable crater
stable crater
stable crater
#

@urban zealot avian 0.4 has been released so you can change 0.4.0-dev to 0.4.0 on the branch

dim warren
#

@urban zealot are there any blockers on a new release?

#

-# just ignore rapier, it's fine, shhhh

urban zealot
#

looks like it might still be a little while

dim warren
#

seriously, most people put their avian / rapier support in an extra crate for that reason

#

see landmass, tnua, rerecast

#

that way you can update the main crate independently of the physics integration

urban zealot
#

I'll look into it

dim warren
#

rapier users can't use the newest BTB whether you have that feature or not

#

you can still add the rapier feature back in a patch release if you want

#

I suspect not many will need it though

#

For my own crates, I tend to tell people that they are very welcome to submit PRs for rapier if they want support, given that the support code is just like 100 LOC or so they can mostly copy-paste

#

and I never heard back from any of them

#

¯_(ツ)_/¯

digital heath
#

Cart even explicitly calls out the collision event naming there :P

#

left a quick comment suggesting against the suffix

tidal galleon
#

Not sure I actually understand the reasoning for not using the suffix but thnx for pointing that out, I'll fix that up in my own stuff

granite canopy
#

in the quickstart guide theres no mention of how a map should be configured on the trenchbroom side. should i just use the generic template?

dim warren
dim warren
#

@urban zealot how come my point class contains a Brushes component hmm Is that intentional or a bug

#

This messes with my invariants when setting up acoustic materials in the Steam Audio <-> BTB integration

#

since I assume that we can automatically set up all acoustics for brushes, I basically yeet any acoustics that my Avian integration might already have set up automatically

#

but if regular point classes also contain Brushes, then I just yeeted the acoustics material that the user specified for e.g. a chair

urban zealot
urban zealot
#

on main

dim warren
#

NPC point class:

#

Ingame:

#

If you want to compile it yourself, activate the "auto-install" feature on bevy_steam_audio

#

(so it downloads libphonon.so for you)

dim warren
urban zealot
#

Looks like I didn't check to make sure there are actually brushes before adding that
I have now found another problem, when loading maps, Transform will sometimes be added as a required component by things like lights, making this fail in the global spawner

// We can assume that the entity doesn't derive from Transform
if !ent.contains::<Transform>() {
    if view.tb_config.global_transform_application {
        ent.insert(Transform {
            translation: read_translation_from_entity(view.src_entity, view.tb_config)?,
            rotation: read_rotation_from_entity(view.src_entity)?,
            scale: Vec3::ONE,
        });
    } else {
        ent.insert(Transform::default());
    }
}

I have of course not documented why we changed this, but I believe it was talked about in this channel?

dim warren
#

but very possible that I missed it

urban zealot
#

i think

#

Or not, I changed it back and that problem works fine
I might just add an implicit_transform_override into QuakeClassSpawnView, it's a little hacky, but I can't think of anything better right now

urban zealot
dim warren
urban zealot
dim warren
urban zealot
#

0.10 has been released

dim warren
foggy glade
#

is there anything to take into consideration when spawning multiple maps at the same time?

#

I'm spawining the same map 4 times, as different children of different entities with different transforms

#

and I would expect the transform to be properly propagated

#

but it is behaving really weird

#

even more so with physics (avian)

#

so b4 I go mad looking for a reason I might ask here 😅

foggy glade
#

it kind of looks like worldspawn doesn't correctly apply the transform

#

while the other brushes do seem to work consistently

#

okay it's not related to the brush

#

it's related to the way I'm adding the physics

#

If I do this:

#[solid_class(hooks(SpawnHooks::new().convex_collider()))]
struct Brick;
fn brick_spawner(event: On<Add, Brick>, mut commands: Commands) {
    commands.entity(event.event_target());
}
``` it works
#

if I do this:

#[solid_class(hooks(SpawnHooks::new().convex_collider()))]
struct Brick;
fn brick_spawner(event: On<Add, Brick>, mut commands: Commands) {
    commands
        .entity(event.event_target())
        .insert(RigidBody::Dynamic);
}
``` it doesn't
foggy glade
#

doing it like this doesn't work either

#[solid_class(hooks(SpawnHooks::new().convex_collider().with(RigidBody::Dynamic)))]
struct Brick;
#

the colliders are properly created, and they're set as rigidbody dynamic

#

but the transform just says

granite canopy
#

is bsp worth it

dim warren
#

I really tried hard to work with it, but the limitations are just not worth it in my opinion

dim warren
dim warren
foggy glade
dim warren
#

And for solid brushes, TrenchBroom inserts its own children

foggy glade
#

I think it might have to do with the fact that brushes get automatically spawned with RigidBody::Static, and I'm rewriting that component with RigidBody::Static

foggy glade
dim warren
#

Use .with_children() for .insert()

#

If this is the cause of your problem, then I have myself already lost an entire day debugging it

#

That’s not a TrenchBroom specific footgun, but a Bevy footgun in general

foggy glade
#

using children! wasn't the problem

#

and I am in fact not using it in insert

#

but thanks for letting me now it yeets other children

#

do you happen to know if swapping rigidbody types is supported in avian?

dim warren
#

You don’t have rigid bodies as children of other rigid bodies, right?

#

Because that fucks up transforms in Avian

dim warren
#

Maybe call commands.entity(add.entity).log_components()

#

That prints all the components on the entity in a very hard to read list (I fixed that on Bevy main)

#

But it should be alright here

#

If that list does not contain a rigid body, we know the issue

foggy glade
#

I have them as children of other entities with transforms and such

#

but no rigidbodies

dim warren
foggy glade
#

give me a second

dim warren
foggy glade
#

I called it before and after the insert

#

just in case

dim warren
# foggy glade

I can’t see it on mobile, sorry. But is there a rigid body before the insert?

#

If not, I think we found the bug

foggy glade
#

what the fuck

#

there is

#

in fact

#

no rigidbody

#

in the before

#

only in the after

#

im puzzled af

dim warren
#

Take a look at the full hierarchy with the egui inspector and see which entity actually holds the rigid body

foggy glade
#

omw

#

The RigidBody is indeed in the worldspawn 🤔

#

so that doesn't seem to be it

urban zealot
#

Don't listen to Jan's anti-bsp propaganda

stable crater
# granite canopy is bsp worth it

I stuck with it - but my game is more like an old Quake TC - so being able to use old quake maps from the internet is a part of it. If you are building maps in trenchboom, then use .map 😄

dim warren
dim warren
#

you need to be a turbonerd to get baked lighting in Bevy any other way

urban zealot
stable crater
#

Yeah, i wrote my own AO library.. then found ericw tooling and kicked myself

urban zealot
dim warren
foggy glade
#

@urban zealot can I grab your attention for a moment please 😅

urban zealot
#

yes hello

foggy glade
#

I think I've found a bug on Trenchbroom

#

on the Avian integration

#

if you haven't read anything from above

#

basically when adding the Rigidbody property to a brush spawned by trenchbroom

#

the entity gets teleported to 0,0,0

#

well, not to 0,0,0 exactly

#

but rather its own local transform

#

so it is correctly positioned inside the .map

#

but not inside the bevy world (doesn't follow child hierarchies and transform propagation)

#

but again, this only happens when adding RigidBody::Dynamic or RigidBody::Static to it

urban zealot
#

Just to make sure, you're using 0.10, right?

stable crater
#

haha yep! I was originally building this in MonoGame (for nostalgia) ...and they havent really updated the graphics since DX11. So when I started hand rolling my own Forward+ rendering (CPU based, because no compute shaders 😢 ) I realised i was just punishing myself for no reason. Sometimes the most liberating feeling is burning a codebase to the ground and starting again

foggy glade
#

I'm using revision: 2a125b54a23a6b01c117a75ec6849c40ded09941

#

so yeah technically 0.10

urban zealot
#

I believe that is the commit that was published to crates.io

#

I'm recreating the problem, I'll look into it

foggy glade
#

is it also happening to you?

urban zealot
foggy glade
#

Great! I was a bit worried it was something wrong on my end

#

Tag me if you need anything else from me

urban zealot
#

You got it

digital heath
dim warren
#

The important bit here is not the fact that it's using a Binary Space Partition, but that it is preprocessed

#

preprocessed in really really cool ways

digital heath
#

Hmm okay

dim warren
#

It does stuff like trimming things outside the play area, combine brushes into simpler geometry, bake light, generate occlusion data, ...

#

but the tools that do so expect your .map file to adhere to 1990s practices, like only using 15 characters for the textures names. And those 15 characters include the name of the subdirectories bavy_spin

granite canopy
urban zealot
dim warren
foggy glade
urban zealot
# foggy glade did you find anything?

Here are my notes currently
From my testing, if you insert a RigidBody into an entity at the same time it gets spawned from a BTB scene, it sets its global position to its local position.

without RB
local: [1.0159998, 0.6096, -1.016], global: [6.016, 0.6096, -1.016]
with RB
local: [-3.984, 0.6096, -1.016], global: [1.016, 0.6096, -1.016]
  • If you don't add any colliders, it still happens.
  • The transform is fine in the scene world, it only gets messed up when it gets spawned in the main world.
  • It doesn't happen when manually creating a scene with a similar setup, I can't get a small situation to reproduce it in.
  • It seems to happen after or during Add observers are run, as my observer printed the correct local coordinates, but even systems running in First print the wrong coordinates.
  • When restarting repeatedly it very occasionally it doesn't break, so it's probably an ordering issue.
#

This bug is pretty annoying :P

foggy glade
#

yikes

#

looks rough af

#

my guess based on literally just observing the behaviour is that this is probably an avian teleportation issue, which may explain why it doesn't always happen and why the positioning isn't fixed and kind of random

#

maybe it's getting spawned at a position with given physics properties, and then the transform is edited again after adding the rigidbody again somehow?

#

not sure of anything but it definitely is a weird bug

#

thanks for the efforts my man ❤️

urban zealot
urban zealot
foggy glade
#

I've vaguely seen some discussions over at the avian thread

#

about teleporting active physics entities

#

and it is indeed a common issue in most phyisic engines I've used

#

so the guess comes from that

#

but I wouldn't want to misslead you based on conjecture tbh

#

it's just a gut feeling

foggy glade
#

okay @urban zealot I just tested on a small example

#

to try and teleport rigidbodie

#

both dynamic and static

#

and although they get awaken and move a lil bit

#

they do not seem to bug out significantly

#

I also tested switching them from dynamic to static and viceversa

#

and it's also okay

#

so i don't really know, maybe these aren't part of the issue at all, or maybe its just because of a weird interaction on spawn

urban zealot
# foggy glade so i don't really know, maybe these aren't part of the issue at all, or maybe it...

To be honest, I don't know how to further debug this, everything I've tried has led to a dead end
This workaround seems to work, it might have to be good for now

#[solid_class]
#[require(DynamicRigidBodyHack)]
pub struct FuncDoor;

#[derive(Component, Reflect, Default)]
#[reflect(Component)]
struct DynamicRigidBodyHack;

fn dynamic_rigid_body_hack(
    mut commands: Commands,
    query: Query<Entity, With<DynamicRigidBodyHack>>,
) {
    for entity in &query {
        commands.entity(entity).insert(RigidBody::Dynamic).remove::<DynamicRigidBodyHack>();
    }
}
foggy glade
#

When does trenchbroom insert the Rigidbody static component?

#

because entities by default do get an static component inserted

#

Can you try to temporally change that to insert a dynamic instead of static and see if it sticks?

urban zealot
#

When colliders get added, but this seems to happen even without colliders

foggy glade
#

idk, just saying because the default insertion seems to work just fine

urban zealot
foggy glade
#

however if you manually insert an static it also fails

urban zealot
dim warren
#

@digital heath am I remembering correctly that having rigid bodies be children of something else at a non-identity transform is not well behaved in general?

#

Because I think that’s what’s happening here

foggy glade
#

Did you try to not insert the rigidbody with trenchbroom

#

and just insert one using the requires?

#

so basically removing the default behavior of trenchbroom of autoinserting the rigidbody component

urban zealot
foggy glade
#

Fuk

#

okay so it is not based on component-swapping shenanigans confirmed

urban zealot
#

My current best guess is it's some kind of internal Avian ordering issue

foggy glade
#

will have to be that

#

lets see if Jondolf can shine some light on it

#

I'll put in the workaround temporarilly

dim warren
#

Jondolf Jondolf I summon thee

foggy glade
#

Jondolf rn:

dim warren
#

Satana Perkele Vittulainen

digital heath
#

yeah I'm trying to read context

digital heath
foggy glade
#

Guys I actually feel so bad, I'm always coming to bother you with obscure bugs

#

Your names will be big in the credits of our game

urban zealot
dim warren
foggy glade
#

at some point I'll have to contribute to the crates tbh

#

given how much I use them

dim warren
foggy glade
#

I just cant find enough time for everything

digital heath
#

I'm not sure I understand the full context, but there's a system that effectively converts the global Position and Rotation components into a local space Transform at the end of the physics step

#

it sounds like that is somehow maybe breaking something?

#

but again idk if I understood the problem correctly

foggy glade
#

Basically

#

When spawning a brush with Trenchbroom

#

if you hook/observe it to insert a RigidBody component on it

#

the transform gets resetted to origin

urban zealot
foggy glade
#

or smth like that

#

it's not exactly to origin

#

but rather I think it ignores the parent's transform

#

so it is positioned well with respect to .map positioning, but wrong with respect to the entity transform hierarchy

#

looks like it ignores it or something weird

digital heath
#

And I'm guessing this is new in 0.4? Or was it also happening in 0.3

foggy glade
#

it is new, but I don't know whether it's wrong with avian or trenchbroom

#

well

#

actually 🤔

#

I'm not really sure because I have never spawned trenchbroom scenes nested on a hierarchy before

digital heath
#

or wait was there another related one

foggy glade
#

@urban zealot does Trenchbroom do any reparenting on spawn maybe?

#

bevy_trenchbroom I mean

urban zealot
#

I just set PhysicsTransformConfig::position_to_transform to false and it's spawning in the right place (not moving, but I think that is expected)

#

not doing that it breaks

urban zealot
#

I wonder if transforms sometimes aren't propagated by the time position_to_transform runs

digital heath
#

by default Avian runs an additional propagation pass right before physics

#

to make sure global transforms are up to date for collision detection

#

but I won't have time for that until some time tomorrow, it's uhh 2:30 AM right now and I have an exam tomorrow lol

urban zealot
#

It also looks like transform_to_position runs between those two things, that could be a point of failure

foggy glade
#

good night!

#

the issue can wait 😇

granite canopy
#

nvm wrong chat

digital heath
#

wow okay this is several increasingly cursed problems stacked on top of each other

#

I know how to fix it in theory, but I'm trying to figure out how to do it in a non-breaking way so I can ship the fix in a patch release

foggy glade
#

I'm so sorry dude

#

🥲

#

with I could help

digital heath
#

wait wha

#

how exactly does ChildOf work for scenes?

#

it is None in one component's on_add hook and Some in another

#

I would have assumed that the relationships are kinda baked in to the scene and not inserted deferred somehow

#

oh so scene spawning is done in archetype order, and there's no guarantee on the order, so the hierarchy may not be finalized in hooks yet

#

well shit

#

this is so cursed omg

  • on_add for Collider fires init_physics_transform, but ChildOf is None -> the entity's Transform (often identity) is used for the global Position and Rotation
  • on_add for RigidBody fires init_physics_transform again, because it doesn't know that it was already called for the rigid body. But this time ChildOf is actually Some, and Position and Rotation no longer use the placeholder values because they were computed earlier, so they now overwrite the Transform with the new parent's global transform, but based on the old global transform where there was no parent yet
#

this does not happen normally when just spawning hierarchies with pre-defined child-parent relationships, it only happens with scenes (from what I've tested)

foggy glade
#

Wait are you saying that this may even escalate up to a bevy problem?

#

If there's no way to fetch the state of "scene spawning" on hooks/observers

#

that leads to all sorts of problems doesn't it?

lilac jungle
digital heath
#

we can work around this, but it is kinda annoying that hooks or observers for scenes may not have the hierarchy available yet

foggy glade
#

which I gues could only be solved by being able to explicitly state the insertion order of components in scenes

digital heath
foggy glade
#

I guess that's good news

#

in a sense

digital heath
#

it's kind of a crappy fix but I don't think I can do it much better without breaking changes :p

foggy glade
#

THanks for the fix! ❤️

#

however I might suggest that with avian 0.4 having been released just some days ago

#

it might just happen to be the best time for breaking changes? 🤔

#

as people has to migrate anyway

digital heath
#

yes but we can't ship breaking changes in a 0.4.1 patch

#

for 0.5, sure

dim warren
#

@tawny elbow ^

foggy glade
#

damned semver

#

but you're right

digital heath
#

@wooden yarrow This may also fix the issue you were having with ldtk and transforms being reset to the origin, though I haven't tested ldtk specifically

foggy glade
#

lol another guy with the same problem

#

great that we found it and you fixed it 🙂

digital heath
#

yeah, I just hope it didn't silently break something else in the progress lol

#

from what I tested, everything seems to work, but this transform logic has historically been very fickle

#

transforms and hierarchies are the bane of my existence in avian ngl

tawny elbow
#

although i worry about my dynamic bodies e.e

wooden yarrow
dim warren
digital heath
#

I intend to release 0.4.1 this weekend

restive widget
#

@digital heath this also fixed the issue i was having.

granite canopy
#

ive been using ColliderConstructorHierarchy::new(ColliderConstructor::ConvexHullFromMesh), to generate colliders from my blender maps, and it seems to work on btm maps as well.

are thsee functions an alternative to that or is it just for classes?

foggy glade
#

they're the same afaik

#

besides maybe the fact that convex_collider generates a box collider (simpler than a generic polyhedra) if your brush is a box

#

but I guess that's an edge case

granite canopy
#

ah

#

i imagine thats faster if ur talkin bout a ton of brushes but i dont think imma hit that limit anytime soon

foggy glade
#

yeah I tested it for around 50k

#

(it didn't go well)

granite canopy
#

how to hot reloading

#

is that a feature

foggy glade
#

It is, although I haven't looked into it

granite canopy
#

is it a lot to setup

foggy glade
#

it probably is as simple as loading it with the hot reloading asset server

#

as scenes are simple assets

granite canopy
#

oh this is bevy ur talkin about

#

here i am trynna find hot reloading in the btm docs

foggy glade
#

oh, no idea bout that

#

heh

granite canopy
#

ah its just watching_for_changes on AssetServer

#

if i want to enabled that, do i just &mut asset_server in my setup and replace it? surely I cant insert_resource on a built-in resource?

#

nvm i discovered plugin overrides

#
            DefaultPlugins.set(AssetPlugin {
                watch_for_changes_override: Some(true),
                ..Default::default()
            }),

just add this to your plugins @foggy glade

foggy glade
#

curious that watching for changes isn't turned on by default

granite canopy
#

ok actually this doesnt seem to be doing anything

granite canopy
#

the assetserver is watching changes on the .map but i believe its still up to the btm plugin to acknowledge those changes and react accordingly?

urban zealot
#

Have you enabled the file_watcher feature on Bevy?

granite canopy
#

set the scale here, ran the game, opened trenchbroom, and still the default scale is 1

granite canopy
#

i thought it was just the one setting in AssetPlugin that needed to change

urban zealot
granite canopy
#

oh ic

urban zealot
urban zealot
granite canopy
#

for like invisibile walls?

urban zealot
#

And those too

#

But I mean faces that the player can't possibly see or interact with in normal gameplay

#

Just wasting processing power

granite canopy
#

are you saying that bevys version wouldnt work for that, like its only supported by btm

urban zealot
#

Just generating from the mesh, they certainly wouldn't be the full shape of the brush

granite canopy
#

oh

#

just found a major flaw lol

granite canopy
urban zealot
urban zealot
granite canopy
#

dope

#

for now thats all i need

granite canopy
#

damn i have no idea why its not workin for me. ik its hooked up and all, i can see my custom class

urban zealot
granite canopy
#

setting a face on a brush

#

oh

#

dude

#

its bc i was setting it on an already existing brush

#

lol

urban zealot
#

Lol i was literally just typing
"If it's an existing brush it might not update"

granite canopy
#

XD

urban zealot
#

Well good that it's sorted

granite canopy
#

ysirr

#

thx for the help i have a prototyping workflow all setup now

urban zealot
#

no problem

dim warren
#

Oh I see you figured it out 🙂

dim warren
foggy glade
#

@urban zealot can we get a commit with the fixed avian version super_bavy

#

for now Ill fork

cinder parcel
# digital heath <@329762623304499202> <@98517451557314560> this should fix it https://github.com...

hey y'all; Been running into a similar, but different, problem possibly related to this. After updating to 0.17, bevy_trenchbroom seems to be spawning convex colliders that I intend to move (like platforms) incorrectly. It does generate the correct shape, just offset from the visuals. The brush mesh itself, despite being a child of the collider, is in the correct location. Setting the mesh's translation to be equal to the collider's translation causes them to overlap (at the collider's incorrect position), and then setting the collider's translation to zero puts it in the correct location. If I'm not mistaken, it's as if the collider's own vertices are having its world position baked in rather than being local to the center of the object and then the object being offset. Other entities across the map that are static seem to be fine; and all have their transforms at zero no matter where they actually are

#

this seems to be a change from 0.16 somehow as before this update the platform logic was working fine

cinder parcel
#

ah, here's something maybe useful: One of the movables looks like this

{
"classname" "movable"
"name" "fence_01"
"target" "target_fence_01"
"rotation" "true"
// brush 0
{
( 1151.375 256 -240 ) ( 1151.375 256 -239 ) ( 1151.375 255 -240 ) fence [ 1.9967346175427393e-16 1 0 0 ] [ 0 0 -1 16 ] 90 1 1
( 1168 0 -208 ) ( 1168 0 -207 ) ( 1169 0 -208 ) fence [ -1 1.9967346175427393e-16 0 0 ] [ 0 0 -1 16 ] 90 1 1
( 1136 256 -240 ) ( 1136 255 -240 ) ( 1137 256 -240 ) fence [ -1 0 0 0 ] [ 0 -1 0 0 ] 270 1 1
( 1168 0 272 ) ( 1169 0 272 ) ( 1168 -1 272 ) fence [ 1 0 0 0 ] [ 0 -1 0 0 ] 270 1 1
( 1136 256 -240 ) ( 1137 256 -240 ) ( 1136 256 -239 ) fence [ 1 -1.9967346175427393e-16 0 0 ] [ 0 0 -1 16 ] 90 1 1
( 1152 0 -208 ) ( 1152 -1 -208 ) ( 1152 0 -207 ) fence [ -1.9967346175427393e-16 -1 0 0 ] [ 0 0 -1 16 ] 90 1 1
}
// brush 1
{
( 1136 -16 -240 ) ( 1136 -15 -240 ) ( 1136 -16 -239 ) origin [ 0 -1 0 0 ] [ 0 0 -1 0 ] 180 1 1
( 1136 -16 -240 ) ( 1136 -16 -239 ) ( 1137 -16 -240 ) origin [ 1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1
( 1136 -16 -240 ) ( 1137 -16 -240 ) ( 1136 -15 -240 ) origin [ -1 0 0 0 ] [ 0 -1 0 0 ] 180 1 1
( 1168 16 -224 ) ( 1168 17 -224 ) ( 1169 16 -224 ) origin [ 1 0 0 0 ] [ 0 -1 0 0 ] 180 1 1
( 1168 16 -224 ) ( 1169 16 -224 ) ( 1168 16 -223 ) origin [ -1 0 0 0 ] [ 0 0 -1 0 ] 180 1 1
( 1168 16 -224 ) ( 1168 16 -223 ) ( 1168 17 -224 ) origin [ 0 1 0 0 ] [ 0 0 -1 0 ] 180 1 1
}
}

commenting out brush 1 (that is; the brush with origin in it rather than a contextually relevant name) causes their initial position to work but their final position seems to break badly. At least then the visuals and collider stay together. I'm not the one that made this map nor am I very familiar with trenchbroom itself so I'm not certain what I'm looking at, I just noticed that origin brushes are unique to the broken entities.

foggy glade
#

@urban zealot @digital heath I think I have bad news again 😅

#

The bug that Jondolf solved a couple of days ago has a new version

#

basically the exact same happens if you spawn the entities with Disabled

#

I guess this is even more of an edgecase, but it is still a bug nonetheless

#

idk if now that you've worked around it it can be easier to fix

#

to reproduce just take the exact same example you used last time and add the #[require(Disabled)]

#

then remove the Disabled (so you can see the gizmos) (or use a system to draw disabled entities) and all of them will be at origin

#

I'm so sorry 🥴

dim warren
urban zealot
#

I haven't messed with Disabled at all to be honest, I don't really know how it works
I'm currently very deep in getting Quake 2 maps working so I can't help for a little bit

foggy glade
#

I don't think it's in your end

#

you're probably doing fine, its jondolf spawning logic

#

although the only thing Disabled does is basically hide the entitiy from appearing in queries by default, they only appear if you explicitly ask for Disabled entities

#

but by the time they have disabled your library is done with the job so again I don't think there's anything in your end

urban zealot
#

crazy to me to see this working

foggy glade
#

Great work ❤️

#

Now imagine it with Solari baked lighting

#

Or even realtime heheh

dim warren
urban zealot
dim warren
#

Talking about HL, did you ever experiment with decals?

#

They were added to TB to support them in GoldSrc, but should work for Bevy too imo

urban zealot
dim warren
#

Btw I moved away from preload hooks due to the fact that bevy only caches subassets

#

Not sure if you’re aware, but if you load both a #Scene0 and an #Animation0 and even an #Animation1, it will load the entire glTF 3 times

#

so I nowadays preload the entire Handle<Gltf>

#

Which means the only spawn hook I have left in my code is the one for creating solid classes broovy

#

I was thinking; could spawn hooks be replaced with entity observers that BTB adds and triggers for you?

#

You would still have to specify them in the attribute, but at least they would be regular old Bevy observers

urban zealot
#

I am way too tired to think about this or talk right atm, will get back to you tomorrow

dim warren
#

It’s all working lovely as-is 🙂

urban zealot
#

Good night :)

halcyon frigate
#

I think you’ll probably need to implement emissive textures in bevy_trenchbroom for Q2 too. It shouldn’t be too hard, I put that emissive_scale method in the Q2 texinfo and that should be all you need to make it work. Honestly I’m not sure if Q2 uses it at runtime or if it’s just for qrad but now that we’re in ✨ the future✨ and have proper HDR rendering it makes a big difference, the qbsp PR was based on an old project of mine that could render Q2 maps and I used to just fly around maps playing with tonemapping algorithms and stuff 😅

halcyon frigate
# dim warren Not sure if you’re aware, but if you load both a `#Scene0` and an `#Animation0` ...

There’s a PR that fixes this for me (and I’m patching my bevy dependency to my fork that rebases it on main) but it’s marked draft and there doesn’t seem to be any movement https://github.com/bevyengine/bevy/pull/20449

GitHub

Objective

Fixes many_foxes and other animation examples have stopped working #20383.
Fixes Loading an asset and one of its subassets causes two loads of the same asset to occur. #12756.

Solution
...

urban zealot
halcyon frigate
#

No rush, I don’t think it’s holding anyone up or whatever 😅 Just thought you might be interested

urban zealot
# dim warren I was thinking; could spawn hooks be replaced with entity observers that BTB add...

The whole reason spawn hooks exist is because they run in the scene world (maybe they should be renamed to scene hooks?)
Hypothetically they could be replaced by observers, but I can't think of anything useful that would give them. There isn't anything interesting in the scene world I can think of, and this is during the entity hierarchy construction, so you can't safely look at any other entities

dim warren
urban zealot
#

The hooks attribute, or the infrastructure?

dim warren
#

the infrastructure and the concept

#

Having a concept less is a worthy goal imo

#

if an existing Bevy thing already deal with it

#

Idk how the hooks attribute could be removed :/

urban zealot
#

Just had a quick look into the implementation side of this. We would have to get QuakeClassSpawnView or its contents feeding into the observer, and it seems like both observers and resources require static lifetimes, so as far as I know this isn't actually possible

halcyon frigate
urban zealot
#

You can see exactly where they get run if you expand a QuakeClass macro

#[automatically_derived]
impl ::bevy_trenchbroom::class::QuakeClass for FuncPlat {
    const CLASS_INFO: ::bevy_trenchbroom::class::QuakeClassInfo =
        ::bevy_trenchbroom::class::QuakeClassInfo {
            ty: ::bevy_trenchbroom::class::QuakeClassType::Solid,
            name: "func_plat",
            description: None,
            base: &[<BspSolidEntity as ::bevy_trenchbroom::class::QuakeClass>::ERASED_CLASS],
            model: None,
            color: None,
            iconsprite: None,
            size: None,
            decal: false,
            properties: &[],
        };
    fn class_spawn(
        view: &mut ::bevy_trenchbroom::class::QuakeClassSpawnView,
    ) -> ::bevy_trenchbroom::anyhow::Result<()> {
        use ::bevy_trenchbroom::qmap::QuakeEntityErrorResultExt;
        view.world.entity_mut(view.entity).insert(Self);
        let hooks: ::bevy_trenchbroom::class::spawn_hooks::SpawnHooks =
            (view.tb_config.default_solid_spawn_hooks)();
        hooks.apply(view)?;
        Ok(())
    }
}
halcyon frigate
#

Once the scene gets spawned it’s all in the main world though, right?

urban zealot
halcyon frigate
#

Interesting point about them running on the asset server thread, I hadn’t considered that

urban zealot
halcyon frigate
#

Yeah I def think that makes more sense

#

The issue with them is that it ties data and behaviour together though, and one of the biggest strengths of Bevy is that it separates them

#

A lot of that is an issue with Bevy's scene and asset system in general though

urban zealot
halcyon frigate
#

I don’t think you need to conform to it, entities are just configuration at the end of the day

#

Even from my perspective of making a Quake engine it’s useful to split the two, not even mentioning people building their own games. I’m currently rewriting my QuakeC VM so that entities aren’t a singleton bc it makes a lot of other future features a lot simpler to implement

halcyon frigate
urban zealot
#

Just had an idea

// Type parameter for what the scene is a subasset of?
.add_scene_system::<Bsp>(PostSpawn, add_convex_collision_to_solid_classes)

fn add_convex_collision_to_solid_classes(
    mut commands: Commands,
    query: Query<Entity, With<SolidClass>>,
) {
    for entity in &query {
        commands.entity(entity).insert(ConvexCollision);
    }
}

This could also make it so global transform application doesn't have to be as special-cased

halcyon frigate
#

👀 Yeah hooks as systems would def be useful

#

Or systems as hooks, whichever way you want to think about it

#

I wonder if someone’s made an RFC for something like that in Bevy already

#

That’d be really useful for more than just bevy_trenchbroom too

urban zealot
#

I feel like some functionality like this might've been addressed with bsn, I'll have a quick look over that PR again

halcyon frigate
#

I guess one problem with using systems is that what’s available is way less discoverable. Maybe so long as you still have that BspData singleton that gives you a first place to look

urban zealot
urban zealot
# halcyon frigate I guess one problem with using systems is that what’s available is way less disc...

This is true, being able to do a view. and see everything you have access to is nice for developers
Speaking of which, we come back to lifetime problems, for reference, here's QuakeClassSpawnView

pub struct QuakeClassSpawnView<'l, 'w, 'sw> {
    // 'l: local, 'w: world, 'sw: scene world
    /// The file type of the map being loaded.
    pub file_type: MapFileType,
    pub tb_config: &'l TrenchBroomConfig,
    pub type_registry: &'l TypeRegistry,
    /// A map of classnames to classes.
    pub class_map: &'l HashMap<&'static str, &'static ErasedQuakeClass>,
    pub src_entity: &'l QuakeMapEntity,
    pub src_entity_idx: usize,
    /// The class of the entity that is being spawned. Not the class of the [`QuakeClass`] in which this view is passed to (if it is a base class).
    pub class: &'l ErasedQuakeClass,
    /// The scene world being written to.
    pub world: &'sw mut World,
    /// Entity in the scene world.
    pub entity: Entity,
    pub load_context: &'l mut LoadContext<'w>,

    /// Information about the mesh entities this entity contains.
    pub meshes: &'l mut Vec<QuakeClassMeshView<'l>>,
}

LoadContext stands out to me especially for looking quite hard to get access to in these systems

halcyon frigate
#

I guess provisioning new handles would be a pain

urban zealot
halcyon frigate
#

Hm, yeah I’m having trouble figuring out an approach that allows both the kind of copy-on-write asset modification needed for the goldsrc glass and lets you load sub-assets from other files

urban zealot
halcyon frigate
#

I don’t think you need a separate mesh, just a separate material

#

There’s no way to change face-to-material mapping with render modes (and I think it’s fair to not support that) so you can reuse the mesh

urban zealot
#

Forgot render modes aren't separate per brush

halcyon frigate
#

Ah yeah, they’re per entity (and therefore per model)

#

Honestly I kinda feel like scene loading has such different constraints to both regular asset loading and regular gameplay systems, maybe it could even make sense to just do the core in-memory format as an asset, without actually creating a scene at all, and then do initialisation in a subapp or something so you get the full power of the ECS. Configuration could still be done in the regular world and/or with extension methods on the app/world and the fact that it uses a sub-app would be an implementation detail.

#

Although having said that, you don’t need it to continuously run

#

So that’s probably not the right abstraction

urban zealot
#

Just thought through it, I don't think we need render modes to be handled in the scene world, if we don't mind a possible 1-frame delay before windows are transparent

halcyon frigate
#

1 frame delay isn’t the end of the world because you can start it disabled

urban zealot
halcyon frigate
#

Like, just the BspData without any handles, which would be processed by whatever the replacement for hooks is, then once all processing is done the handles would be created and the scene would be considered ready

urban zealot
#

Also I don't think a subapp would be more powerful than the current solution in terms of ECS, everything (like systems and resources) is stored and handled in the World struct anyway

halcyon frigate
#

Like, if you had some SQuakeSpawnView that implemented SystemInput<Inner<'a> = QuakeSpawnView<'a>>

urban zealot
#

Oooh, I did not know about this

halcyon frigate
#

Yeah I actually didn’t realise either 😅 I use SystemIds for my console commands and thought I had to clone the arguments to pass them into the systems that implement the commands, I should look into changing that

urban zealot
#

Can we call an entire schedule with an input is the question

#

I guess I could just store a Vec of SystemIds, but it'd be cool if I didn't have to

halcyon frigate
#

I mean, if the input is a mutable borrow then you need to run all the systems serially anyway

urban zealot
#

Oh that's true

halcyon frigate
#

You can still use schedules to get all the nice ordering constraint stuff but then ultimately just read the execution graph and run all the systems in a loop

urban zealot
#

That sounds good. I think I have a pretty good idea of that this'd look like now, I'll get to prototyping :)

halcyon frigate
#

Nice! I’d love if you pinged me if/when you’ve got a draft PR up, this is very interesting and I’m currently using my own fork of bevy_trenchbroom because the hook system doesn’t fit my (admittedly very unconventional) needs 😅 From this chat I think that this would address my needs

halcyon frigate
urban zealot
#

@halcyon frigate It doesn't look like schedule graphs support systems with inputs or outputs unfortunately

#

We might just have to stick to a Vec<SystemId>

#

Another problem, &'l mut LoadContext<'w> would need both the 'l (local), and 'w (main world) lifetimes, and SystemInput only supplies one

#

Looks like LoadContext only uses its lifetime parameter for the AssetServer, if only it cloned an Arc of it

#

This is looking less and less promising

halcyon frigate
halcyon frigate
#

You could create a new LoadContext with begin_labeled_asset so you don't need to worry about 'l, you're loading a #Scene subasset anyway

#

Then you’ll only have one lifetime

halcyon frigate
#

Posted on that issue, but with some mildly-hairy uses of unsafe it could be possible to have a library for scoped non-'static resources

urban zealot
#

We could do that, apparently I didn't know you could transmute between lifetimes

// Insert as a non-send resource
pub struct LoadContextRes {
    ptr: *mut LoadContext<'static>,
}
impl LoadContextRes {
    pub unsafe fn new(load_context: &mut LoadContext) -> Self {
        Self { ptr: unsafe { std::mem::transmute(load_context) } }
    }
}

Not the prettiest Rust in the world, but the more I poke around, the more it seems like this about the best we can do without that issue you posted being resolved
(We could also make it not a pointer with the trick you described above)

urban zealot
halcyon frigate
#

I was thinking that you’d need to use dummy systems as a facsimile of the real systems (which I guess would be in a hashmap or something) but making the issue def makes me think that, firstly, that would be even more of a filthy hack than I originally thought, and secondly, it’s probably possible to have a cleaner solution

halcyon frigate
urban zealot
halcyon frigate
#

Yep 🙃

urban zealot
#

I don't trust myself to catch every one of them

urban zealot
#

@halcyon frigate You mentioned replacing spawn hooks with your own system, right? What exactly did you replace it with?

halcyon frigate
#

It’s not a better system, it’s just that the hooks didn’t allow me to make the map loading work the way I wanted (where I kinda want to go in the opposite direction, loading it as a bag of models where each model in the model lump is its own sub-asset) so I forked it to hard-code that

#

I can’t remember exactly what I changed and I’m not even 100% sure it’s necessary 😅 I just wanted to get it working

#

I’m slowly converging on a clean codebase but at any given time one system or other is in a dire state as I do a big refactor

halcyon frigate
cinder parcel
# cinder parcel hey y'all; Been running into a similar, but different, problem possibly related ...

following up on this; i was able to fix my problems and restore functionality to before the upgrade by using this simple-ish system:

fn fix_target_tb_entities(
    mut commands: Commands,
    mut entities: Query<(Entity, &Transform, &Collider), With<Target>>,
) {
    for (entity, tf, coll) in entities.iter_mut() {
        if let Some(shape) = coll.shape().as_compound() {
            let mut shapes: Vec<> = shape.shapes().iter().cloned().collect();

            for shape in shapes.iter_mut() {
                shape.0.translation.vector -= SVector::<f32, 3>::from(tf.translation.to_array());
            }

            commands
                .entity(entity)
                .insert(Collider::from(SharedShape::compound(shapes)));
        }
    }
}