We are now at a point where the 2d graphics side of things has reached a certain stableness. There are still parts of the original wme engine which are not implemented yet, but the main functionality is there, at least for Alpha Polaris (and the demos as well). Some screenshots:
What cannot be seen on the screenshots is movement of course. There were some more issues with it since the scripting code of Alpha Polaris is expecting a Direct3D coordinate system. So some conversions were needed. But now things seem to work as expected or at least nothing unexpected has happened. But then this is only the very beginning of the game.
One thing that worked straight out of the box was 2d object selection. On the other hand, 3d object selection together with attaching these objects to characters is still missing. Implementing this will be the next goal. After that, we will be able to have some fun with rifles and bears!
So last Tuesday I thought that I had the .X file stuff basically finished, up to missing details at least. Unfortunately this was not correct. After getting everything to work in the Wintermute 3D demo, I decided to try out and see, what would happen in Alpha Polaris. Well, this was the first result:
The black something flying over the bed is supposed to be the main protagonist of the game. So this didn’t work out so well. Issues were negative texture coordinates together with clamping and a wrong mesh update function, which did not set all vertex position values to zero before calculating the new positions during an animation.
After fixing this, I realized, that my model was still using the Direct3D coordinate system, which caused it to appear mirrored. So this meant some more work figuring out how to correctly change the coordinate system to an OpenGL one and fixing some more bugs along the way. Lesson learned here: The coordinate system has definitively to be consistent.
Now things are looking much better. Pictures will follow over the weekend, there are still some other issues in Alpha Polaris, which have to be fixed.
So, most of the necessary Wintermute 3D code is now imported. Also, the .X loader is almost finished, meaning in particular that the animation data is loaded in and applied. Here is the current state in a video (rightclick -> play should start the video):
So basic animations are essentially working (although there could be buggy edge case which so far did not appear). Also path-finding seems to work already. On the other hand there are still some glitches like the model being visible in the initial screen, the teapot disappearing when reentering the front part of the scene (although it will reappear again if you just go towards the back and then to the front again), letters two far away, etc. .. .
Wintermute3D offers the possibility to load in and display 3d models from .X files. For this it relies on functionality offered by the D3DX helper library, which parses in the data into an intermediate data structure. Wme then puts the data from there into it’s own data structure, which actually closely resembles the .X file format, meaning that essentially for every non-trivial data type there is a class in the engine code. Now although these classes are portable, which is very convenient, the loader itself is missing and has to be implemented from scratch.
So the first thing I did at the beginning of this week was to import the usable code from Wme3D into ResidualVM. This took some time, but now almost all importing of necessary or potentially useful code is already done. After that I started to work on a parser for the .X file format. Originally the plan was to base the parser on the Assimp library, but after some more research on the format, I thought, that implementing a recursive descent parser from scratch might be just as good as an option. So that’s what I did. Now at the moment, several key parts are still missing, but the essential structure is there and I am able to load in some data in display in “some” way onto screen, like this:
In front of the first door, there is a 3d model of what is supposed to be Trinity from the movie Matrix. As one can see, it’s somewhat displaced in mid air. Also the scene geometry is messed up, as can be seen by comparing above image to the one from my last post. But hey, what can you hope for..
One thing that I have to change about the whole .X parsing stuff is the handling of commas and semicolons. By design, .X files like semicolons, everywhere, and the code shows this very explicitly at the moment.
During all of this work I also learned the hard, that the override keyword can be very useful (if you use it). Some of the classes, that I imported, where supposed to override certain virtual member functions. But the function signatures of the base classes had changed when they where imported into ScummVM and so nothing was overridden. And then I wondered, why the imported code wasn’t called. Another moral of this story could be though, that checking compiler warnings, at least sometimes and also keeping them minimal would be a good idea..
The coding phase of this year’s GSoC will begin this week. What has happened so far on the porting of Wintermute3D into ResidualVM. Well, first I started learning a little about OpenGL 2.1.Having done some Direct3D 9 in the past, a lot of the concepts were familiar to me, but nevertheless a different API is a different API. I tried out some loading of .X files as well via the assimp library, just to get a feeling for what would expect me since .X files are a big part of the project.
One aspect of the project is to load in data from an .X file. My first plan was to base a parser on assimp, taking out the code and reusing parts of it. But I realized after starting to write a lexer for the .X format that writing a recursive descent parser myself as well is not that difficult and might be even more straight forward. At the moment I am more concerned about displaying and animating the data, which has a lot of room for little, hard to find, errors, although I can reuse a lot of code here from the original code base.
As an additional exercise, I took the existing renderer for the Wintermute port of ScummVM, after importing the code into my ResidualVM fork and implemented a simple texture renderer based on it.
After that, I got a little bit more ambitious and decided to go for an actual OpenGL based renderer for the 2d graphics part, which would also be the foundation for the rest of the project. In the beginning things were buggy, partly due to miscalculations of coordinates but also due to the fact that Direct3D offers something called transformed vertices, which bypass the transformation pipeline. It took me some time to realize this as I was searching the Wintermute code base for the part where actual 2d rendering to the viewport is activated. The catch is that this is done by setting a specific vertex format. Now OpenGL has no direct equivalent for this but one can set an orthographic projection via glOrtho to archieve the same effect.
Here is a screenshot showing a temporary state (this is from the Wintermute 2d demo). It was taken after I discovered how to setup 2d rendering onto the viewport. As one can see, the color key is still there and the sprites are somewhat displaced, which is due to the fact the Direct3D and OpenGL differ in what corner of the viewport has coordinates (0, 0). These things have been fixed since then. What is still missing on the picture above are two more sprites displaying two people. This is because I didn’t yet implement the necessary functions and I might postpone this until much later since complete support for 2d graphics is not the goal of this project.
I also wanted to do some 3d rendering, so I took some of the Wintermute3D code for the scene geometry and reintegrated it into the ScummVM Wintermute port. To display the scene geometry (which is actually supposed to be invisible and only the for lightning and shadows as well as path finding), I needed to implemented a .3ds loader. Now fortunately the .3ds format is not so complicated and Wintermute3D even has a .3ds loader which I used for comparison. On the other hand, I still had enough pointer arithmetic bugs in the beginning but I like this kind of stuff, so it was fine. Displaying the data correctly was again another story, I had some fights with camera and projections matrices and had to find out the hard way, that the .3ds format is using a right-handed coordinate system where the z axis is pointing upwards. Wintermute3D is just exchanging the the y and x coordinates, but this also changes handedness (a great illustration that switching rows in a matrix negates the sign of the determinant!) and thus does not work for OpenGL, one has also to negate the z coordinate (or y coordinate, from the .3ds perspective). After taking this into account, I got the following result:
Hello guys, my name is Gunnar and I am one of the fortunate students who got accepted into this year’s GSoC to work on the ResidualVM project. Essentially my goal will be to port the missing 3d graphics parts of the Wintermute engine which are missing in the existing Wintermute port in ScummVM.
Why do I want to do this? Well, I really enjoy programming, game programming in particular, although I never worked out an actual game, mainly for the reason that I shunned away from all the asset creation stuff, which I do not enjoy at all. But with this project this will be irrelevant as the assets are already there and only the code has to be written, very much to my own taste. Also I like the idea of making games run on Linux (or non Windows platforms in general) and I also start to really enjoy the idea of open source software.
Some more personal information. I am 26 years old and currently a student at the university of Münster in Germany. My subjects are Mathematics and Computer Science, although I focused on Mathematics in the past few years. My programming activities consisted mainly in student assistant jobs but now I am looking forward to open source development.
I will leave this as is for now. Until the start of coding on first June I will mainly prepare myself for the task and post some updates here.