Hard Light Productions Forums
Modding, Mission Design, and Coding => FS2 Open Coding - The Source Code Project (SCP) => Topic started by: Goober5000 on January 16, 2003, 01:23:24 am
-
Inspired by Bobboau's previous work on the nameplate code, I took it upon myself to add support for complete texture replacement on ships in-mission. :D It is now possible to reskin a ship model without needing an extra table entry. :nod:
Here's the final product...
http://fs2source.warpcore.org/exes/fs2_open_3.41_unofficial.exe
Add the following to the bottom of one or more ship entries in a mission file...
$Texture Replace:
+old: [old texture]
+new: [new texture]
or$Duplicate Model Texture Replace:
+old: [old texture]
+new: [new texture]
The +old: and +new: lines can be repeated, if desired, to allow replacement of more than one texture on a ship. If you're using the $Duplicate Model Texture Replace method, there is a limit of 50 possible texture replacements per mission. But if people so desire, the limit can be raised.
The most obvious use for this mod is to allow custom nameplates on ships (à la the Galatea and the Bastion). The nameplate code was never completely finished, but you can accomplish the same result by (e.g., on the Orion) replacing capital01-05a with whatever the filename of your custom nameplate is. (Speaking of custom nameplates, this seems like a good time to highlight my Orion nameplate tutorial (http://www.geocities.com/ipw47/nameplates.html). ;) :D)
You'll need to reskin a duplicate model if you want to substitute animated or transparent textures, but this is probably the optimal solution if you want to add cockpit kill count art, custom ship nameplates, or any stuff like that. Of course, mission designers can experiment on their own to see which method plays better in a given mission. :)
For the SCP gurus and anyone else interested, the way I implemented the $Texture Replace method was to add an array to the ship structure, int replacement_textures[MAX_MODEL_TEXTURES], which I initialized to -1 and later loaded the duplicate textures with a one-to-one correspondence to the textures in the polymodel struct. In the model render routine, I check to see if the texture currently being rendered has a positive (greater than -1) ID number in the associated replacement texture array, and if so I render that texture instead of the texture in the polymodel struct.
The way I implemented the $Duplicate Model Texture Replace method was to duplicate the ship model (not a trivial task!) for all ships with custom textures, and then reskin this duplicate model with the custom textures as the mission was loading. Once the mission has loaded, the model is all retextured, initialized, and ready to go, so there's no extra calculation in the middle of the mission.
[This post has been edited to reflect the final state of the mod, with both the ship texture array method and the duplicate model method implemented. :)]
-
From the way you describe it, it sounds like using this to do custom textures for a lot of ships will dramatically increase the memory requirements and may slow down loading time.
-
I doubt it'll have that much of an effect. The only significant amount of extra memory required is for the duplicate model, and this is the same as it would be if you added another ship class to the mission. There's a little bit of calculation involved to reskin the model, but I don't think it has a noticeable time lag.
If you have a lot of modified ships, well, that might be another story. But the in-mission stuff should still run at the same speed.
-
wow, you make an entire dupluicate model?
why not just have something flaged in the ship structure?
maybe that's why I never got mine fully bugless...
-
I did it this way because if you allow more than one texture, the additional calculation per frame to substitute the extra textures would pile up and cause significant drop in frame rates. By putting all the new textures on a new model, you eliminate the need for on-the-fly calculations. :)
-
Originally posted by Goober5000
The only significant amount of extra memory required is for the duplicate model, and this is the same as it would be if you added another ship class to the mission.
This is what I mean. It might also lower the amount of ship types you can effectively have in a mission. (Each reskinned ship would count as a seperate ship type and there's gotta be a ship types per mission limit somewhere.) :) Not sure how much memory it takes so I'll use the POF filesizes in an example about how easily it all adds up. If I read this right, an Orion's POF file takes up about 600kb. Two of them would take up over a megabyte. Three would take up over a megabyte and a half. And that's not counting textures. If all three were regular Orions, they should take up about the same amount of space as one. (For this I'm just talking about the POF data, not the table/mission data.) Not saying this is a problem, but people might hit internal FS2 limits sooner then they may be expecting. (And I don't doubt that there are MODders out there who have a habit of hitting various internal FS2 limits, like the subsystems per mission limit, ships per mission limit, and so on.) :)
-
Originally posted by EdrickV
This is what I mean. It might also lower the amount of ship types you can effectively have in a mission. (Each reskinned ship would count as a seperate ship type and there's gotta be a ship types per mission limit somewhere.) :)
There probably is, but the reskinned ship doesn't count as an extra ship type. The routine loads an extra model, but it doesn't take up another ship type slot.
Not sure how much memory it takes so I'll use the POF filesizes in an example about how easily it all adds up. If I read this right, an Orion's POF file takes up about 600kb. Two of them would take up over a megabyte. Three would take up over a megabyte and a half. And that's not counting textures. If all three were regular Orions, they should take up about the same amount of space as one.
Eh, okay, but suppose someone built a mission with a Hecate, an Orion, a Typhon, a Hatshepshut, a Demon, etc. All different models, but they all work well enough together in-mission.
I suppose the best answer can only be obtained by testing it out. :p Keep in mind also that this is a debug build; the release version will be even faster than this.
-
it just seems a bit ineffecent...
the way I had it was I had a global array of ints each corisponded to a ship texture, at start up and after a ship was rendered this list was all set to -1, before a ship was rendered I set the values in the array to what they were in a similar array in the ship structure (wich was innitalised to -1, but changed based on mission file flags), and like I said I set the array to all -1 after, in the tamaped poly function it checked if there was a replacement texture in the array (if(replacement[p(+44)] != -1), I think it was), if there was it used what ever taxture was in the array, otherwise it would use the normal one.
but I guess you're way works, more than I could say for mine
(I just love my messy global arrays don't I:) )
-
:) Globals are fun. :drevil:
It was a trade-off. I first thought of doing it this way, so that's the way I did it. I couldn't see any good way to substitute more than one texture using a similar process as yours, Bobboau.
-
Originally posted by Goober5000
There probably is, but the reskinned ship doesn't count as an extra ship type. The routine loads an extra model, but it doesn't take up another ship type slot.
Eh, okay, but suppose someone built a mission with a Hecate, an Orion, a Typhon, a Hatshepshut, a Demon, etc. All different models, but they all work well enough together in-mission.
If it doesn't take up another ship type slot, then that is good. (Though somewhere there's got to be a polymodel limit too. :) ) And I'll give you a better example, one based on something I can easily imagine people doing and on how I think the two versions of the code work.
Imagine a Babylon Project mission where you are defending B5 against an Earth Forces destroyer and it's fighters. 1 friendly station, 4 wings of 4 Starfury ships, (2 friendly, 2 hostile) and 1 hostile destroyer.
Without reskins, that would (I think) be a total of 3 models, assuming all the starfuries were of the same kind. (Just like all Herc II's are the same kind in FS2.) Now let's do some reskinning.
1. Reskin the destroyer. No change, there's only one of them.
2. Reskin 3 wings of AI fighters so each of the wings has their own skin. Suddenly each of those 12 fighters uses it's own model. The fourth wing is left alone.
Results: The mission now uses 15 models instead of 3. And most missions I've seen use more actual ships then this which would raise the number of models used even higher. All in all, this was probably the best way to do in-game reskinning at this time. It's just not perfect. (But then, what is?) :)
-
Oh, great :doubt: and I spent all yesterday night doing reskins and changing map names for the demo version of the Tau ships :p
( just joking with the "oh great" ;) that's very cool, and who cares if it's a bit longer to load? I prefer the mission to load more slowly rathert than have slowdowns ingame )
-
Goober this is a very nice wellcomed addition.
-
Thank you. :)
To all: I would still say, reskin your ships if you're going to use a bunch of the same kind in the same mission. With this code, if you custom-reskin four of the same ships the same way, you're nevertheless going to load four new models! Unfortunately, I can't meet halfway on this - it's either make a new ship class and don't load any extra models, or don't make a ship class and load a new model for each reskinned ship.
If you need an Orion with a custom nameplate (or something similar) it's ideal. But I'm not sure (like EdrickV) of the effect if you end up reskinning a whole fleet. :)
I uploaded a release version and posted the link in the first post, so you can compare the speeds. :)
-
Good work Goober. This is something I've been waiting to see for a while. It will always be useful to be able to replace a model's textures at a class level in my opinion.
Although it would probably be useful to be able to replace textures on a ship by ship basis too. Exactly how bad would the performance hit be?
-
Will this be implementable in FRED 4.0?
-
Originally posted by Goober5000
Thank you. :)
To all: I would still say, reskin your ships if you're going to use a bunch of the same kind in the same mission. With this code, if you custom-reskin four of the same ships the same way, you're nevertheless going to load four new models! Unfortunately, I can't meet halfway on this - it's either make a new ship class and don't load any extra models, or don't make a ship class and load a new model for each reskinned ship.
If you need an Orion with a custom nameplate (or something similar) it's ideal. But I'm not sure (like EdrickV) of the effect if you end up reskinning a whole fleet. :)
I uploaded a release version and posted the link in the first post, so you can compare the speeds. :)
ah ok
"thinks he didn't put a nameplate on the Gaia, only on the Ryujin" D'oh!
-
Originally posted by IPAndrews
Although it would probably be useful to be able to replace textures on a ship by ship basis too. Exactly how bad would the performance hit be?
Read the thread! This is replacement of textures on a ship-by-ship basis, and there were a bunch of posts wondering about performance hits.
Originally posted by Black Wolf
Will this be implementable in FRED 4.0?
Fred 3.41 (or later), you mean? I haven't figured out how to do that yet. :)
-
Well, I'm dumb. You can put multiple substitute textures on a ship without requiring an extra model. So, I did. :) Here's the alternate (debug) version...
http://fs2source.warpcore.org/exes/alt_fs2_open_3.41_debug.exe
You can use it exactly the same way as the other one; it's just a difference in implementation.
I think I'll still keep the other method in the codebase, and call it $Duplicate Model or something. The duplicate model method is the only way to reskin animated or transparent textures, so people may need that instead.
-
ok...in all honesty...I don't think it is going to matter too much. FS2 was designed to have reasonable performance on 64 megs of ram IIRC. I have 512 megs of ram, and I know that I don't have all that much. So, this shouldn't be too much of an issue.
Oh, and IP, does this mean that we're gonna have Black Omega 'furies in the next TBP release ;7
-
Originally posted by Goober5000
Well, I'm dumb. You can put multiple substitute textures on a ship without requiring an extra model. So, I did. :) Here's the alternate (debug) version...
Ok, now I'm curious. How'd you get the texture substitution without making a copy of the polymodel? :)
-
Essentially, I just added an array to the ship structure:
int replacement_textures[MAX_MODEL_TEXTURES];
I initialized the array to -1. Then when the mission ran through the parsing routine, I loaded the duplicate textures and assigned their ID numbers to the replacement texture array with a one-to-one correspondence to the textures in the polymodel struct.
In the model render routine, it checks to see if the texture it's currently rendering has a positive (greater than -1) ID number in the associated replacement texture array. If it does, it renders that texture instead of the texture in the polymodel struct.
That's the gist of it. I also made some special fiddly code that would skip completely over the replacement texture check if the object had absolutely no replacement textures whatsoever, in order to optimize the thing for asteroids, debris, jump nodes, and so on. :)
I changed the model parsing routine to load the substitute textures if it encounters a $Texture Replace entry, and to reskin a duplicate model if it encounters a $Duplicate Model Texture Replace entry. (The format of the two is exactly the same, with the +old and +new lines following the heading.)
You'll need to reskin a duplicate model if you want to substitute animated or transparent textures, but this is probably the optimal solution if you want to add cockpit kill count art, custom ship nameplates, or any stuff like that. Of course, mission designers can experiment on their own to see which method plays better in a given mission. :)
-
Hmm. Sounds like there might be a slight in game preformance hit when rendering reskinned models, but with decent computers we probably won't even notice. Will have to see if there's any noticable preformance problems.
-
Originally posted by Goober5000
(The format of the two is exactly the same, with the +old and +new lines following the heading.)
You'll need to reskin a duplicate model if you want to substitute animated or transparent textures
Then shouldn't the code automatically determine and use the correct method? No point in concerning the FREDder with neepish internal details.
-
Originally posted by Goober5000
Well, I'm dumb. You can put multiple substitute textures on a ship without requiring an extra model. So, I did. :) Here's the alternate (debug) version...
http://fs2source.warpcore.org/exes/alt_fs2_open_3.41_debug.exe
You can use it exactly the same way as the other one; it's just a difference in implementation.
I think I'll still keep the other method in the codebase, and call it $Duplicate Model or something. The duplicate model method is the only way to reskin animated or transparent textures, so people may need that instead.
yes, keep them both with two different entries, that way one could make alpha wing blue, beta wing red, and alpha1 having shark jaws on the ship, and beta one having pink dots everywhere!!! yay! ok, the exemples aren't the best ever, but you get what I mean :p
-
the Robotech TC (if it wasn't dead...) would love this stuff...
-
Originally posted by ZylonBane
Then shouldn't the code automatically determine and use the correct method? No point in concerning the FREDder with neepish internal details.
:wtf:
Because there's no easy way for the code to do this, and anyway it's only a two-word difference in the file. The FREDder is the best judge - not the code.
:rolleyes:
-
When you get right down to basics, electronic computers don't think. They just do what they are told. (Even if what they are told to do isn't what they should do, which is how computer crashes happen.) The best computer ever invented is still the human brain. (At least on this planet. ;) )