I just cleaned up the CVS and am in the process of uploading my current code base. I have working Bioware-data rsource manager and resoure browser that lets me look at resources. I now also have the loading as display of map geometry and txtures working within that browser. (Thats my dev environment. When I release I will move all the necessary bits to a proper J3D loader.)
Lots still to do in terms of environment animations, transparncy, sounds, lighting and genreal speed and efficiency but its workign well enouhg to load bsaic maps. Ill put some screen shots in the WWW directory of the project.
Note that there are NO docs. I know this so you dont have to tell me. Its still way too early for that, Ill doc when we hit first release of the loader.
The Area GIt file baically gets me to Template files for the doors, but templates only have a pallete node number, not the resref of the actual palette they came from.
Anyone knwo whrere the pallete res refs for a given area are hiding?
Hey Jeff I just came from the NWN Development arena. Let me know if you need some info about things. My expertise was in creating HAKs. Mostly new creatures and textures, but I have allot of 2da knowledge. The render looks good so far. Not looking to join a project but hopefully I can save you some time and answer some questions.
At the moment msot of the questions Im running into are very low level and have to do with figuring out the binary 3D file format. Im working from Torlack’s notes which, while impresive, aren’t always very clear or detailed.
But I seem to be making progress anyway! I’m working on Doors and palcables right now… I have some positioning stuff stil lto get right but its getting close.
Just put up my latest snap shot in the WWW directory.
Doors are now in the right places (You can also see transparency working, look at the tree.) The grate that drops gets placed perfectly. The doors that swing are all 90 degrees in rotation and set at the center of the door frame.
I have a strong suspicion this is due to my not yet having figured out where to get the data for animating the door states (open/closed.) if anyone has suggestions please mak them otherwise I’ll keep digging and experimenting!
Slightly related, I’ve just added skeleton animation to my NWN text model loader. The walking iron golem looks very cool. Sorry, no Web Start demos yet, just some old (too dark) screenshots at the project page. The source code from http://sourceforge.net/projects/nwn-j3d was helpful when implementing the model loader.
I’m also interested in code that parses binary NWN model files. Maybe you have something I can use?
Have you done interpolation between animations ? It is quite important for models to look believable.
As for binary model format, THE SOURCE is Torlack website (http://torlack.com/index.html?topics=nwndata_binmdl), plus his model compiler/decompiler. Don’t even bother looking at my c-tools, I have done decompilation in interative manner and never managed to refactor the beast, while Torlack started from coding only from point where he had general idea how everything works - so it is a lot more readable.
[quote]Have you done interpolation between animations ? It is quite important for models to look believable.
[/quote]
Yes, I do linear interpolation of the orientation quaternions (using SLERP) and points. I’ve also done some tests with quadric interpolation as this should result in smoother animation, but it’s hard to tell the difference. Are NWN model animations designed for linear interpolation?
Btw, are you the same ‘abies’ responsible for the http://sourceforge.net/projects/nwn-j3d project? If so, thanks for making the source code available, it’s really helpful when trying to make sense of the model format.
Yes, that’s what I found when searching the web. As binary models can be converted to text, there really are no big reasons for implementing a binary loader, right?
Yes, linear interpolation is ok. Just to be sure - I was not talking about interpolating between keyframes in single animation, I was talking about interpolation when changing animations. For example, you were in middle of turning head to left and at the instance you start two handed swing. Without interpolation between anims, head will pop into stright position in instant. What I have done, was blending two of the animations at very start. As far as I remember, it was also linear interpolation, just between poses of two anims (previous and target) at given time - with weight being dependent on one of parameters of target animation (transition speed or something like that).
I know that it is not very clear - if you want more info, I could write an equation for that.
Same abies, just 2 years older
Depending on what you want to do. If you just want to play with models and have something for your game - no need. If you want to interact with NWN world (hak/mod browser, world editor etc), then it is not possible to require everybody to first run all resources through decompiler.
Certainly there is no need to implement model writing in binary - it is just a difference of speed for original NWN and in extremly few cases somebody would really want to do it, they can always use a converter.
You can grab my binary loading code from JNWN if you want.
The source starts from “AreaViewer”. AreaViewer calls MDLLoader to actually load the models. To proeprly load binary models you must have an NWN resource manager as textures and such are accessed by resref. I have one in my code base, you can see how AreaViewer and MDLLoader instance and use it.
No docs, no comments, but verbose variable and method names for the most part.
Translating the binary IS slow. For my project im planning on actually writing a tile-converter that will store them in Java3D io format for fast load at run-time. Having said that there is still a good deal of caching I coudl be doing that im not yet that will speed this code up. (Currently AFAIR all Im cachign is textures.)
Have fun. Im eventually going to need creature loading when I start work on the actual client so you guys’ projects definitely interest me.
Yes, some kind of interpolation between animations is needed. I’m considering storing the current orientation and position for each node and then move these values towards a target position. That way you can stop in the middle of an animation and start another one smoothly.
Btw, what is the “transtime” animation parameter found in the model files used for?
True. I’ve no plans for supporting other NWN data besides loading NWN models. I’ll probably implement a custom binary model format to increase model read/write performance.
A question about the text model format: in the face list there is an extra int value after each vertex index triplet. For example:
faces 48
3 0 1 >4< 3 0 1 >1<
Is this some kind surface grouping used when calculating vertex normals, or what is this value used for? Currently I just ignore it.
[quote]You can grab my binary loading code from JNWN if you want.
The source starts from “AreaViewer”. AreaViewer calls MDLLoader to actually load the models. To proeprly load binary models you must have an NWN resource manager as textures and such are accessed by resref. I have one in my code base, you can see how AreaViewer and MDLLoader instance and use it.
[/quote]
Ok, I’ll look into it when I get some time.
You’re welcome to check it out. The project has just started so it’s far from stable and the documentation is non-existant.
be sure to grba the latest version of MDLLoader as I fixed the bug thatw as causing the doors to be positioned wrong. they work now!
Placeables next then I’ll probably do the official J3D Loader class for the maps (the 3D desktop guys want it so they cna show NWN maps as 3D backdrops) . Following that I get to start actually building a game client
When animation changes, we are at certain position O (original)
Theoretic target animation position T(t) for time t is computed
by linear interpolation between keyframes surrounding t.
Real position R(t) for given t is computed in following manner, for
transistion time tt.
if t >= tt then
R(t) = T(t)
else
R(t) = T(t) + (O-T(0))*(1-t/tt)
It seems that I have just stored position/orientation at time of animation change and then linearly interpolated between that and target animation (where target animation was already running).
Trick is that inteporlation is R(t) = T(t) + (O-T(0))(1-t/tt) (first O is original, second is zero - bad naming on my part), instead of R(t) = T(t)(t/tt) + (O-T(t))*(1-t/tt). This is not really interpolating between two animations like I have before. I’m running target animation, but at very start, there is an error in position, resulting in previous animation not ending in place corrected for starting current one. What I do, is just running current animation and applying original error diminishing proportionally to (1-t/tt). I don’t exactly remember why I have chosen this solution - probably I have experimented with both and this one looked better.
First of magic integers (4 in this case) is smoothing group indentifier. Ascii format does not have normals specified, you need to compute them yourself. Normally, for each vertex you average normals of all faces sharing it - but in this way, you cannot get hard edges. What you need is duplicating vertices which are shared by faces from more than one group and computing normals only for each group.
Second of these integers was not identified to this point as far as I remember.
Ok, I remember seeing the formulas in your docs, but I never read them carefully. Now I see what the transition time is used for.
Ok, this is what I thought. Seems the group integer is a bit mask because it’s almost always a power of 2. Maybe each bit identifies a group. That way a face can be part of multiple groups. Correct?