Jump to content

Asset management in Torque 3D


JeffR

Recommended Posts

Hey Everyone,


We(the SC) have been talking on porting over T2D's TAML, Asset and Module systems into T3D at some point in the future, and I began looking into how that would happen.


Thanks to Lukas' prior work in getting TAML ported to my Entity/Component branch, it didn't take me long to get TAML working on the latest and so I've started meandering my way through the asset and module parts to get an idea of them.


Az insisted I throw down something on the forums about it to get people talking, feedback and for general "this is a thing happening", so here we goooo.


One thing with Torque is that while the art pipeline isn't BAD, it is however unrefined. It's pretty flexible in what it allows you to shove into it and largely doesn't break anything when you do, but updating assets, moving things around, and inter-dependencies between stuff like models, textures and materials can make managing them a mess.


So, today I was brainstorming on it, and came to the idea of implementing asset files. Torque already does this in a fashion with models. You hand it a collada dae, and it processes it and spits out a dts that the engine actually uses. After that point, you can stop using the source collada file and use just the cached edition.


My thoughts on that are to expand that process to cover any and all content assets the engine would use, combined with the asset system in T2D to assist in the management and tracking of them.


And so, you would have a torque asset file. *.tasset, if I wanted to totally ape unreal's naming methodology, haha.


The idea would be that you'd import a peice of content via the editor - sound, texture, material/shader, model, animation - and it would process it and save it out as a *.tasset file(or whatever we end up calling it. For now I'll stick with tasset)

The tasset file would contain the peice of content, as well as a header that is a taml asset descriptor. So it'd provide version data, dependencies and other easy-to-read data in addition to the binary data of the content itself.


This allows several things at once. One, because all assets would exist in this fashion and be handled via the asset manager, WHERE the assets are located is irrelevent. Each asset has information about what other assets it's dependent on. So you have a model that requires TextureA, TextureB and TextureC. They don't have to be in the same folder at all. They just need to exist in the game directory.

In the same vein, it makes the loading code much easier. We can have just one pass that loads all the tasset files in a directory, and because each tasset file can describe what it is via it's header, we can know what to do with it incredibly easily inside the engine. Script-side would be one standard function to load a tasset file and thus could automate the process by a large margin.


In additon to that, versioning/updating assets would be easier. Because we can store version data in the header, it's very easy to pull and compare to see if files are out of date and the like. We can also easily to categorization tags, so it's easier to sort and group assets.


So how would we actually use and make tasset files? Well, we'd need a content browser. Good news though, we basically already have that in the Material Browser.


You'd just expand the same browser UI to work on all tassets. The process from a user-end of things would be to open the content browser, and click a button to import a new asset(or drag-n-drop an asset from your computer to the editor window, which is easy to implement, I've already done it on my internal build) and it'll read it in.

You'd save the tasset file to whatever directory you'd be inclined to as well as put in additional information if needbe, such as version number, categorization tags, etc.


At that point, the tasset would exist in system, and thus would show in the content browser - categorized based on type and/or tags.

If you already have a tasset file and just want to copy it into your project, you'd just open it or drag-n-drop and poof, you're good.


This also removes the need for source files to clutter up your game's directory if you're so inclined and export functions would be as easy as 'save the binary data to a new file at location X' through the content browser.


One other fairly big advantage this would provide us is standardizing the internals. Take textures for example. Torque supports quite a few different types. If we go the tassets route, we could decide on an internal-format of it(because the binaries would save into the tasset file itself anyways) such as DDS. We could do some nice automagical things, warning the user if it's non-pow2, generating mip-maps for them if they want, testing if it's a linear texture, etc. This lets the engine know definitively what sort of texture it's got on hand and can make some things a lot simpler to deal with.


So yeah, figured I'd write town the brainstorm, and see what people thought of it. I think it'd make a LOT of things easier when it comes to using torque in regards to the pipeline stuff, so I'm curious if other peeps feel the same.

Link to comment
Share on other sites

I totally forgot about that thread, actually, haha.


But yeah. moving a stuff to taml would help, and then having tassets to drastically simplify the pipeline would also be a considerable help.


For drag-n-drop, as said I did get it working at a basic level. For the proper implementation, the way I saw it working is you drag-n-drop your file or files/folders into the editor window. It'll detect it happening, and automatically pop open the content browser window and activate the import mode.


From there you could do whatever process you need for the inbound files. Add tags, version numbers, etc. I figure you'd have a project-level setting for what-assets-go-where.


So you could just rig your project settings in the editor so textures go into art/textures, meshes go into art/meshes and so on. So as it generates the tasset files, it'll toss them into the appropriate end-point. Would cut down on a LOT of time fiddling with organization of files, that's for sure.

Link to comment
Share on other sites

Idea: when the .tasset is generated, couldn't it allow for some easy optional optimizations too?


E.g. merging some textures together in the different channels, conversion to .dds etc.

Conversion to .dds is something a lot of people forget or don't know to do, but it improves loadtime and memory usage.

And merging textures together was specifically minded on terrain textures, where you could have normal and parallax map in seperate files and then merge them together when generating the .tasset. Could also allow for flipping the axis, so you don't have to do that manually. This would help import for non-artists.

Link to comment
Share on other sites

It'd also presumably allow us to modify manifest files automatically so you don't have to keep adding exec()s when you add new stuff. Though I guess most of those execs are for datablocks, right? Are materials.cs files automatically loaded?

 

Material loading works the same as main.cs loading. It does a 'find all files named X' in a given directory and execs them. Really, we'd just do the same thing automatically for tassets. When building your project, we can assume that if there's a tasset in the game dir, we want it. From there, we could - through the power of TAML and asset management - have a 'build' function. That'll go through all your taml and asset files and track dependencies and could clean up unused stuff. If a taml or tasset file has no calls or references or is depended upon, it's not in use and can be culled out.


I'd actually suggest for a 'build' function, it'd generate a new directory in your project dir, ie: MyProjects/SuperAwesomeProject/finalBuild/ or something to that effect.

The build function of the editor would copy all files that are actually in use into that, leave a lean, cleaned-up game structure. This would let us let end users keep their source art in the project dir if they want, as well as just leave a bunch of WIP tassets and scripts in there, without requiring them to clean it up themselves when you want to do a final build for release.

 

Idea: when the .tasset is generated, couldn't it allow for some easy optional optimizations too?


E.g. merging some textures together in the different channels, conversion to .dds etc.

Conversion to .dds is something a lot of people forget or don't know to do, but it improves loadtime and memory usage.

And merging textures together was specifically minded on terrain textures, where you could have normal and parallax map in seperate files and then merge them together when generating the .tasset. Could also allow for flipping the axis, so you don't have to do that manually. This would help import for non-artists.

 

I'd made a brief comment about the dds thing, but yeah, you could definitely do other optimizations as well.


Like with Az's PBR branch, where the materials allow you to pick which channel acts as what property, that's slower than having it all in one file preemptively, but single-file is trickier for non-artists or newbie artists.

With tassets, you'd make your material, assign the files in whatever manner you want and then it'll convert it into a single dds file with everything in the associated channel for you in the end tasset file.

Link to comment
Share on other sites

Material loading works the same as main.cs loading. It does a 'find all files named X' in a given directory and execs them. Really, we'd just do the same thing automatically for tassets.

At build-time, maybe, but I think that's a pattern we should get rid of at runtime. Remember the zip-inside-a-zip bug we had when 3.7 came out? It's also a security risk if you care about that, which hobby people like me don't, but actual studios releasing actual games might. But yeah, as you say, being able to pull out a clean directory for distribution is kind of the big win there.

Link to comment
Share on other sites

Material loading works the same as main.cs loading. It does a 'find all files named X' in a given directory and execs them. Really, we'd just do the same thing automatically for tassets.

At build-time, maybe, but I think that's a pattern we should get rid of at runtime. Remember the zip-inside-a-zip bug we had when 3.7 came out? It's also a security risk if you care about that, which hobby people like me don't, but actual studios releasing actual games might. But yeah, as you say, being able to pull out a clean directory for distribution is kind of the big win there.

 

Hm, yeah, that's a fair point.

Well, since you'd be importing assets via a process and not just hurling them into the void of your game directory by way of the OS directories, it'd be pretty trivial to have an manifest file to load them be updated for you.

Link to comment
Share on other sites

So in chat Az raised a couple good points that should be brought up here:


The biggest one is backward compatibility and/or making it easy to port projects up to using tassets.


If you have most of a project already set up, having to manually port to this sytem would indeed be a pretty huge pain. So there would need to be some fashion of batch-conversion tool that automates it for the end user. I don't think it'd be too hard to do. You could have a command in the content browser/import function that will automatically poll the game directory for valid assets and run an import function on them if they don't already exist as a tasset. From there you would just need to add categorization tags and the like as needed.


The other one is that it would probably break live-reload as described. And this is definitely something I didn't really consider. We back and forthed in irc about it, and a good way to do it would be to have a source-path reference in the tasset itself. When the tasset is loaded, it can hook into T3D's resource manager as normal for the source file path. This way, if the source file is modified, the resource changed callback would happen and the asset can be updated as well.


Maybe make it a project setting to have it auto-reload, or merely inform the user and then they can click on that tasset in the content browser to manually trip a reload?



Another thing we were talking about is improvements to handling GUIs. I don't know if this is expressly a "asset" thing - I don't know that we'd convert guis to tassets or not. I'd wager no, and they'd just be TAML + script. But I'll put it here lacking a better place to discuss it for now. My idea on GUI management is to have 'callback fields' in the gui editor itself. Similar to how the trigger object has onEnter/Exit/Tick command blocks you can edit easily, the gui controls would have command fields for various callbacks. onWake/onSleep/onMouseDown, etc.


If you want to script functionality on it, you'd select that gui control in the gui editor, and edit that particular callback field. This would automatically add it to the associated gui's script file without needing to do it yourself. This removes yet another element of needing to go into the game dir and manage files yourself without loosing any of the functionality. Heck, this would probably drastically improve the usability of the guis if you can hammer some script on a gui and immediately test it by leaving the editor(updating the field would logically trigger a re-exec of the script file)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...