PDA

View Full Version : Alias and Reskins



BuilderBob
July 8th, 2015, 11:57 PM
'Alias' as a tag is not supported in 3.5 or later. There was talk that it was going to be replaced with a better mechanism - is there an update available re progress on implementing this?

Mesh_asset in the mesh-table container does not do the same job because the mesh is then rendered as per the original asset, rather than the asset that refers to it.

An aliasing mechanism should have performance improvements over duplicating the meshes. It also means that reskins can be done without requiring the original creator's approval as there is no copying involved.

WindWalkr
July 9th, 2015, 01:19 AM
At the current time, I believe mesh-asset and texture replacement effects are the functional equivalent to the old aliasing mechanism.

chris

BuilderBob
July 9th, 2015, 02:20 AM
At the current time, I believe mesh-asset and texture replacement effects are the functional equivalent to the old aliasing mechanism.

'mesh-asset' renders the asset with the images of the source asset, not the reskin, defeating the purpose.

Texture replacement has to be implemented in the original asset - it's not relevant to creating a reskin by aliasing.

Unless you are referring to some combination of these two options that I haven't considered.

WindWalkr
July 9th, 2015, 02:41 AM
'mesh-asset' renders the asset with the images of the source asset, not the reskin, defeating the purpose.

Texture replacement has to be implemented in the original asset - it's not relevant to creating a reskin by aliasing.

No, that's not how it works. Texture replacement should work just fine with 'mesh-asset'.

chris

BuilderBob
July 9th, 2015, 03:31 AM
No, that's not how it works. Texture replacement should work just fine with 'mesh-asset'.

OK. I would appreciate an outline of the process, as I am currently working from the description here:
http://www.trainzportal.com/blog/view/mesh-libraries-using-the-mesh-asset-tag

"Note that 'mesh-asset' isn't a replacement for 'alias'. It is not a method of reskinning - the texture file will always be loaded from the referenced asset along with the mesh. It does, however, allow you to pick and choose which meshes are loaded, and control how they are attached to your model using your local mesh table." (emphasis added).

WindWalkr
July 9th, 2015, 07:25 AM
Correct, which is why you use texture replacement effects to replace the textures.

Put those two together, and you have the same mechanism as the 'alias'.

chris

BuilderBob
July 12th, 2015, 07:15 PM
Put those two together, and you have the same mechanism as the 'alias'.

I need another clue.

Does the 'putting together' involve a textureGroupAsset?
or
Does a 'texture replacement effect' work with something other than a load?

WindWalkr
July 12th, 2015, 08:09 PM
Texture replacement effects configure a target for MeshObject.SetFXTextureReplacement(). They have nothing to do with product queues, really, they're just a way to replace a given texture in "your" asset with a texture from any source that you choose.

In case I'm not being clear, I'll say right now that aliasing through either approach works the same way and neither is brilliantly performant. Both require loading up the mesh, then substituting the textures as an afterthought. E2 is better at this (multithreading) but it still requires the second load. We may quite conceivably revisit this in the future to allow substitution prior to loading; Jet couldn't do this but we have a lot more control over E2 so it's something that we could add.

chris

BuilderBob
July 12th, 2015, 08:53 PM
Texture replacement effects configure a target for MeshObject.SetFXTextureReplacement(). They have nothing to do with product queues, really, they're just a way to replace a given texture in "your" asset with a texture from any source that you choose.

OK. That must be an update because everything I have seen indicates that MeshObject.SetFXTextureReplacement() requires a textureGroupAsset?

I will try it with a 'vehicle' MeshObject.

WindWalkr
July 12th, 2015, 09:55 PM
Sorry, I'm quoting you the wrong name. Try: MeshObject.SetFXTextureReplacementTexture(). The parameter is the name of the "*.texture" resource from the asset in question (NOT from the mesh-asset asset.)

chris

BuilderBob
July 12th, 2015, 10:20 PM
Try: MeshObject.SetFXTextureReplacementTexture(). The parameter is the name of the "*.texture" resource from the asset in question (NOT from the mesh-asset asset.)

That certainly sounds like the trick - I will report progress.

BuilderBob
July 19th, 2015, 01:53 AM
Reporting no joy whatsoever.

Set up the aliasing through mesh-asset/mesh tags and a named effects container in the default mesh container. Effects container is kind 'texture-replacement'. So I have a texture replacement effect name to use.

mesh-table
{
default
{
effects
{
reskin
{
kind "texture-replacement"
texture "map2.texture"
}
}
mesh-asset <kuid previously used with 'alias' tag>
mesh "default mesh from above asset .im"
auto-create 1
}

Create a replacement texture (map2.texture.txt. and map2.tga)

Then put the line
SetFXTextureReplacementTexture("reskin", "map2");

into the Init function of the script.

Nothing happens. No script errors, and no texture replacement.

An example would be much appreciated.

WindWalkr
July 19th, 2015, 01:58 AM
"map2" sounds incorrect, as the name of a texture resource is expected there.

It's probably worth checking the game logs to see if any runtime issues are reported.

chris

BuilderBob
July 20th, 2015, 02:41 AM
"map2" sounds incorrect, as the name of a texture resource is expected there.

It's probably worth checking the game logs to see if any runtime issues are reported.

I have stripped it down to the absolute minimum using an asset created for the purpose, and still no luck. There is nothing reported in the log.

1. Base asset. This has no changes or coding to support the reskinning.


kuid <kuid:634338:101008>
username "3ds Sample - Original"
kind "scenery"
trainz-build 3.5
mesh-table
{
default
{
mesh "3ds_sample.im"
auto-create 1
}
}
category-class "BS"
category-era "2000s"
category-region "00"
thumbnails
{
...
}


This the reskin asset.


kuid <kuid:634338:101009>
username "3ds Sample - Reskinned"
kind "scenery"
trainz-build 3.5
script "reskin"
class "reskin"
mesh-table
{
default
{
mesh-asset <kuid:634338:101008>
mesh "3ds_sample.im"
auto-create 1

effects
{
main
{
texture "new.texture"
kind "texture-replacement"
}
}
}
}
category-class "BS"
category-era "2000s"
category-region "00"
thumbnails
{
...
}


It has the named texture replacement effect.

This is the script.


include "MapObject.gs"
// For assets at build 3.5 and higher, 'alias' is no longer available as a tag.
// It is replaced by the 'mesh-asset' tag in the mesh table. However, for
// reskining using an alias, the mesh-asset tag must be supported by a texture replacement
// script so that the replacement texture is applied to the aliased mesh.
class reskin isclass MapObject
{
public void Init(void)
{
inherited();
// ! This will change the texture name that have to be replaced on the effects mesh.
// WARNING: This will typically cause Trainz to freeze for a short period when called and/or when
// the mesh in question first becomes visible.
//
// Param: effectName the name of the effect that we want to apply the texture to
// Param: textureName the name of the texture that we want to apply
//
// Sets the specified texture onto the named effect.
SetFXTextureReplacementTexture("main", "new");
Interface.Print("3ds texture replaced");
}
};


I'm not sure what you mean by a 'texture resource' for the function argument. The description refers to an effect and a texture.

WindWalkr
July 20th, 2015, 02:56 AM
For referring to a texture:

* A texture file: "foo.texture.txt". (This is what you should see in Windows Explorer. This is not used in game.)
* A texture resource: "foo.texture" (This is what you use in-game, eg. in a script or config.txt file. Notice the absence of the .txt here. This is NOT a filename.)
* Nothing at all, so you shouldn't ever see this: "foo". (This doesn't refer to an actual file, nor does it refer to a texture resource. It will not be useful for any purpose beyond human speech.)


For referring to an effect:

* Always use the effect name exactly as per the config.txt file.


chris

BuilderBob
July 20th, 2015, 05:47 AM
For referring to an effect:
* Always use the effect name exactly as per the config.txt file.

Changing
SetFXTextureReplacementTexture("main", "new");
to
SetFXTextureReplacementTexture("main", "new.texture");
produces exactly the same result - no texture change at all. I think I have tried every possible combination for those two parameters. Oddly, no errors are ever created, whatever arguments I use.

I will continue to hunt for an example of the usage of the function.

andi06
July 20th, 2015, 06:11 AM
Most mesh effect routines fail silently rather than issuing any kind of exception or message.



effects {
main {
texture "new.texture"
kind "texture-replacement"
}
}


At a guess your problem lies in the red text. This needs to refer to the name of the original texture resource in the original asset which you are planning to replace. As far as your aliased asset is concerned the script line 'SetFXTextureReplacementTexture("main", "new.texture");' will probably be replacing new.texture with itself :-)

[EDIT: This mechanism does work if you get your references correct]

BuilderBob
July 20th, 2015, 07:13 AM
At a guess your problem lies in the red text. This needs to refer to the name of the original texture resource in the original asset which you are planning to replace. As far as your aliased asset is concerned the script line 'SetFXTextureReplacementTexture("main", "new.texture");' will probably be replacing new.texture with itself :-)

If it would do that, I would be happy! The problem is that it always uses the original, whatever I put as the arguments, including that original texture. That syntax, BTW, is nearly the same as the now defunct SwapTextureOnMesh(), so it was a good guess, even though it doesn't match the documentation.


This mechanism does work if you get your references correct]

I am sure it does - the problem is getting the references right. If you can point me at an example, even vaguely, that would be appreciated.

EDIT/ That does work - many thanks.

I misread your comment because I had not appreciated that the texture specified in the texture-replacement container does not have to exist in the asset.

I need to re-test with textures of the same name, because that is the common case. I will document it and hopefully the blog can be updated.

Thanks again. /EDIT

andi06
July 20th, 2015, 07:58 AM
I've used <kuid:-1:1009> Misc_Jetty which should be on the dls.

Install the asset and open it for edit, find the texture that you want to replace. I've used AssetX to do this but you can also get the information via Windows Explorer:

705

I'm going to replace jetty_planks.texture.

Clone the asset and give it a new kuid.
You will need to add a mesh-table if the asset doesn't have one.
Delete all of the files copied from the old asset except config.txt which you will need to edit as shown below.
Add a script file called jetty.gs together with the config.txt references to it.
Provide a new tga and texture.txt file for the new texture, repeat if you want to skin the other textures.
Install and place in the game.

706

[Edit: You don't have to use the same names and I would suggest that it will be far easier if you don't]

RPearson
July 20th, 2015, 02:48 PM
Andi06, BuilderBob and Chris I've been following this topic with a bit of interest. But what happens if the original model (asset) has it's own custom script that's required to provide some special features and characteristics to the asset? With the old "alias tag" I just did nothing (scripting wise the alias tag provided the necessary link) and the original script was executed and my new textures added. AFAIK when I add a new script and class and reference them in the config.txt the old script(s) are not run on my new asset. Is something else now required in addition to the short piece of code andi06 shows in the example? Maybe like inheriting from the old class or some such techniques.

Is there a good way to do this for all cases?

Bob Pearson

andi06
July 20th, 2015, 03:57 PM
Basically you are going to have to reimpliment the script (let's call it ParentAsset.gs") in the child asset:

1. Add this to config.txt:



script-include-table {
0 <kuid of parent asset>
}


2. Change the child script to look like this:



include "ParentAsset.gs"

class Child isclass ParentAssetClass {

public void Init(Asset self) {
inherited(self);
SetFXTextureReplacementTexture("boards","env.texture");
}

};


This script should do everything in the child asset that the original script was doing in the parent. The difficulty that might arise is whether or not there are any other resources in the parent that are referenced by the script.

The example I gave was a parent asset which only had one mesh file. For more complex assets you would certainly need additional mesh-table entries and other resources might also be required - some might need to be copied over. I don't think that there will be a 'one size fits all' solution.

I think that the principal drawback of this mechanism as a replacement for alias will be that it will require some level of skill to update an exsting aliased asset to use this technique. It certainly isn't anything that could be automated.

RPearson
July 20th, 2015, 04:19 PM
Thanks andi06 that's kind of what I was thinking. You've highlited the basics in this thread though.

Bob Pearson

BuilderBob
July 20th, 2015, 05:05 PM
Andi06, BuilderBob and Chris I've been following this topic with a bit of interest. But what happens if the original model (asset) has it's own custom script that's required to provide some special features and characteristics to the asset? With the old "alias tag" I just did nothing (scripting wise the alias tag provided the necessary link) and the original script was executed and my new textures added. AFAIK when I add a new script and class and reference them in the config.txt the old script(s) are not run on my new asset. Is something else now required in addition to the short piece of code andi06 shows in the example? Maybe like inheriting from the old class or some such techniques.

Is there a good way to do this for all cases?

Bob Pearson

This problem will definitely come up in many cases. It has both problems and benefits - in many cases issues with scripting in the aliased asset have simply been ignored, but with the new form of aliasing they can be addressed. Similarly, auto numbering, which was typically simply overruled with a number embedded in the new texture, can probably be reimplemented correctly.

Presumably the aliasing is being used in order to avoid copying original work. If the script is an original work then it has to be referenced and executed from the reskin. This can be done with a script-include container and a matching include statement in the script for the reskin. If the script is a generic one that can be copied (such as many of the scripts provided for use with a library) then it can be included with the reskin. But it would need to be carefully examined for any issues relating to the aliased mesh and its textures.

Edit/ The description is now available at
http://online.ts2009.com/mediaWiki/index.php/HowTo/Reskin_an_Asset_using_an_alias
/Edit

WindWalkr
July 21st, 2015, 12:00 AM
I should stick my head in here again and point out that this approach doesn't really bring any benefits over the old aliasing technique. It DOES work, and will continue to work, but it's not particularly performant and I can't really encourage it on those grounds. It is feasible that the user will see the train vehicle with its original textures before the replacement kicks in, as we can't make any guarantees about how fast these replacements are- just that they will happen.

Basically: it's a useful technique in the right situation, but don't go overboard and try to use it on everything you make.

chris

BuilderBob
July 21st, 2015, 12:59 AM
I should stick my head in here again and point out that this approach doesn't really bring any benefits over the old aliasing technique. It DOES work, and will continue to work, but it's not particularly performant and I can't really encourage it on those grounds. It is feasible that the user will see the train vehicle with its original textures before the replacement kicks in, as we can't make any guarantees about how fast these replacements are- just that they will happen.

... and the TS12 preview in the Surveyor list doesn't do the replacement (the preview window and the list preview in T:ANE both get it right). But where the original reskinning used the old alias tag, there's no other option.

andi06
July 22nd, 2015, 12:49 PM
I thought that I might try something a little more complicated here so I had a go at aliasing the tender on Auran's Duchess, load.im was the first target:

709

Original coal load (on the left) - 3832 polys (no LOD), texture size unknown.
Replacement - 90 polys, texture size 256 x 128 diffuse, 256 x 128 normal.

I've been reviewing what I would need to do to bring my rolling stock up to TANE standards and I thought that I should look at this asset as one of Auran's flagship payware examples. I know that this was originally produced for TS2009 but I don't recall that LOD facilities or requirements were markedly different, the asset has been updated for TANE and it is still being actively marketed.

Details of <kuid:523:1972900> BR Duchess Green for build 76401

Loco Polycount LOD0 = 72,292 / LOD1 = 59,461 / LOD2 = 35,444 / LOD3 = 12,175
Tender Polycount LOD0 = 12,520 / LOD1 = 7,907 / LOD2 = 5,571 (plus 3,832 for coal at all levels)
Animation cut off - not implemented
Render cut off - not implemented
Attachment cut off - not implemented
Textures (excluding normal, reflection and alpha-number maps) - 8

As a result the loco and tender are rendering 20,000 polys (not to mention bogies, couplings and other attachments) even at close to minimap levels - not good and I don't expect the coaches are any better.

Details of the textures used are hidden by encryption but there are no doubt other horror stories in there.

I know that this is nothing to do with Chris but he must find it difficult to appear here and advise us on how to produce efficient TANE standard content when his own company is producing this sort of thing. These findings certainly add weight to those who complain about the quality of Auran's published examples.

WindWalkr
July 22nd, 2015, 09:04 PM
I know that this is nothing to do with Chris but he must find it difficult to appear here and advise us on how to produce efficient TANE standard content when his own company is producing this sort of thing. These findings certainly add weight to those who complain about the quality of Auran's published examples.

One of the reasons that we rarely publish examples, I guess.

To be quite honest, I have yet to see a loco "done right". Part of the reason for that is lack of tools in the right hands- by the time something is in front of me for any sort of review, it's usually "too late" for the creator to go back to the drawing board and fix what they should have done right the first time. This goes for both internally commissioned and third-party content, and yes, it's one of the more frustrating aspects of my job. I'm sure it's frustrating for you also :)

Hopefully the tools we are working on now will go some way to correcting that.

chris

andi06
July 23rd, 2015, 03:40 AM
To be quite honest, I have yet to see a loco "done right". Part of the reason for that is lack of tools in the right hands- by the time something is in front of me for any sort of review, it's usually "too late" for the creator to go back to the drawing board and fix what they should have done right the first time.
I intend to bring all of my rolling stock up to TANE LOD standards. These are all existing meshes and I'm quite prepared to 'go back to the drawing board', if it helps I'm happy to refer some of these to you for comment (I don't promise to agree with you though) and to write up anything useful on the WIKI. Using the semi-automatic mesh reduction that I tried out on the asset illustrated at the start of this thread means that this is not nearly as much work as I was expecting.

I started on one of these assets last night and this has given rise to a couple of queries:

1. Submesh suppression:

Given a submesh definition like this:



right-passenger-door {
mesh "right-doors.im"
anim "right-doors.kin"
auto-create 1
att "a.origin"
att-parent "default"
}


Am I correct in assuming that the entire submesh will be dropped automatically by way of attachment culling if the helper point is defined as 'a.origin:Cull'? Is attachment culling working at present?

2. Interior-lighting

The 'interior-light-texture/interior-light-color' mechanism will be useful when it eventually works (on most of my models it should enable me to drop an entire mesh) However on some of my simpler stock using texture as a mechanism is inconvenient. Interiors viewed from outside don't generally need a lot of texture space and many of mine use a corner of the main asset texture which I don't want to light since it would make the exterior glow in the dark :-)

On the other hand my source files always have the interior as a separate mesh object. Is it possible to implement an alternative, something like this:

interior-light-mesh xxxx
interior-mesh-color x,y,z

This would have the added bonus of saving an unneccessary texture file.

WindWalkr
July 23rd, 2015, 04:58 AM
I intend to bring all of my rolling stock up to TANE LOD standards.

If you're serious about it, then don't push forward too quickly. Much better that we get the tools in place, talk about the various aspects of how things need to be improved, and make sure that you've got the facilities to improve things properly.

One of my concerns at the moment is that people are doing things which are horrible for performance, but which have become the norm and so will be hard to walk away from. This is something we'll have to work through carefully, because if we simply say "don't do this" but don't offer a direct alternative or at least an acceptable compromise, then creators will simply ignore the recommendation.



1. Submesh suppression:

Given a submesh definition like this:



right-passenger-door {
mesh "right-doors.im"
anim "right-doors.kin"
auto-create 1
att "a.origin"
att-parent "default"
}


Am I correct in assuming that the entire submesh will be dropped automatically by way of attachment culling if the helper point is defined as 'a.origin:Cull'? Is attachment culling working at present?

Jet lm.txt files have a culling "lod level" specified for attachment points, beyond which all ":cull" attachment points will be dropped. Similarly, I believe that there is a level below which animation is suppressed. This is a single mode change- you can't select certain things to drop at certain distances.

T:ANE does not support this kind of culling at the current time. The three subsystems (LOD, attachment points, and animation) are not closely integrated as they were in Jet, and we've yet to get a clean way to pass the LOD outcomes back to the others. We've got some plans in place for how to proceed here but they're not yet at the implementation stage.

I'm also of the belief that the single mode change is insufficient for our purposes. Recent locos have become far more complex than was envisioned when LM was introduced, and we really need to cull some elements much much sooner than others. Fan or vent animations for example. Small attachments which are nice for close-up detail but which aren't visible more than 50 meters away. Larger elements perhaps including the bogeys in the far distance. I'm hoping to address these in time for it to be useful in the next Trainz release. It should go some way to allowing creators to introduce these kinds of third-party features without also killing performance.




2. Interior-lighting

The 'interior-light-texture/interior-light-color' mechanism will be useful when it eventually works (on most of my models it should enable me to drop an entire mesh) However on some of my simpler stock using texture as a mechanism is inconvenient. Interiors viewed from outside don't generally need a lot of texture space and many of mine use a corner of the main asset texture which I don't want to light since it would make the exterior glow in the dark :-)

Once you're using a separate mesh, you may as well use a separate texture anyway. Trainz can't currently stitch movable or animated meshes, so you're paying the cost of two separate draw calls whether or not there are two textures. There may be a small loss, but we're better off paying that up front and getting rid of the second mesh as quickly as possible via LOD.

chris

andi06
July 23rd, 2015, 05:48 AM
I'm also of the belief that the single mode change is insufficient for our purposes. Recent locos have become far more complex than was envisioned when LM was introduced, and we really need to cull some elements much much sooner than others.
There is an additional mechanism available and that is for the submeshes to have their own lm.txt files which use the RenderCutOff flag to suppress rendering at lower LOD levels. This allows different submeshes to have their own cut-off levels. However if this is used with a mesh library it does require the lm.txt to be located in the mesh library. This works but we have already crossed swords about it :-)


Once you're using a separate mesh, you may as well use a separate texture anyway. Trainz can't currently stitch movable or animated meshes, so you're paying the cost of two separate draw calls whether or not there are two textures. There may be a small loss, but we're better off paying that up front and getting rid of the second mesh as quickly as possible via LOD.
I was referring to a separate mesh-object within the Max source rather than a separately exported TRS submesh. Its no big deal to reorganise these assets but the second texture is entirely unnecessary.

WindWalkr
July 23rd, 2015, 05:59 AM
There is an additional mechanism available and that is for the submeshes to have their own lm.txt files which use the RenderCutOff flag to suppress rendering at lower LOD levels. This allows different submeshes to have their own cut-off levels.

At some additional cost, yeah, I guess so. Probably better than nothing as long as you can cut if out quickly- but it still doesn't work in T:ANE as we stand right now.



I was referring to a separate mesh-object within the Max source rather than a separately exported TRS submesh. Its no big deal to reorganise these assets but the second texture is entirely unnecessary.

I was referring to your suggestion of using a separate exported IM: "interior-light-mesh xxxx"


chris