Monday, August 4, 2014

Working on the Remaining Issues for Text Rendering

Continued from the previous entry.

In the previous entry, we (mostly) fixed all of the text problems in the set wed, but discovered that there were issues in the set gmi. Since both Elaine and Guybrush's text were in the wrong place, I decided to make the game draw her bounding box too. Here's a typical scene with some text:

Bounding boxes drawn for Elaine and Guybrush
We can see here that the bounding box for Elaine is very wrong, while Guybrush's looks pretty good. So, there appear to be two more issues related to text positioning here:
  1. The bounding boxes are still wrong
  2. The text isn't being placed in the right position above the bounding box
We'll investigate each issue, starting with the bounding boxes. First, how are the bounding boxes calculated? In the graphics driver, there is a function that iterates through the transformed and projected vertices in each component of a costume and finds the bounding box coordinates that enclose these points. To debug this issue, I stepped through each costume component and tried using that as the bounding box coordinates. It turns out that using only the active costume as specified by the wearChore for the dimensions of the bounding box makes the bounding box fit the actor. The result of this change (in PR #976) is shown below:

With the new Bounding Box code
I then decided that the reposition function seemed like a hack, so I examined the retail version in a debugger and found that a simple manipulation of the X and Y coordinates produced just about the same result. With this function removed and the code simplified, here's the current output difference for this text in the set gmi:

Pretty close!
We're very close now with the text placement in this scene, with the text still being placed one pixel too low, but otherwise perfect! Let's check out some other, previously problematic scenes, starting with the set mel, when you meet Carla and Otis again for the first time:

Retail
ResidualVM
As you can see, the text placement for both characters is a little bit off. After some inspection, I found that Carla's text is placed using a specified X and Y coordinate passed as a parameter to SayLine. This text is placed by ResidualVM 9 pixels too high, as compared to the retail version. It turns out that in ResidualVM, there was code that shifted the text when it was too close to the edge, which was using a constant value for shift amount. Replacing this constant with the text height puts Carla's text 1 pixel too low, like most of the other text so far, but very close to the right position.

For Otis' text, the positioning is much further off. His text is placed 41 pixels too low and 17 pixels to the right. After some work with the debugger, I found that the Retail version of EMI was placing Otis' "Yeeps!" at the position: (394, 25). To check that this was accurate, I checked the screen  shot above and found that location, and measured to make sure that the output made sense with these numbers:

Yeeps!
So, the location matches, with the red dot in the middle of the second "e" representing the point specified by the retail version (394, 25). We can see that this dot is 25px from the top and 394 pixels to the right. We can also see that the text is centered in the X axis around this point. ResidualVM does center the text properly, but the point selected is (411, 66). So, where does the difference come from? I continued debugging until I found the bounding box information for Otis and added that to the image below, along with the "Yeeps!" text from the retail version:

Retail bounding box in red, ResidualVM in blue (center line drawn as well)



So, my previous fixes for the bounding box above didn't match the retail version, and we can see that the retail text is placed centered at the top of the retail bounding box. The retail version calculates a bounding box at point (394, 25) with a size of (254, 365).

After some discussion with Akz and Klusark on IRC and some test code, Akz saw that the retail version's bounding box could be computed from the coordinates provided as part of the costume data. Using the bounding box position as the center and projecting the points of the bounding box into screen coordinates resulted in a bounding box that matched the retail version. With this change, the text is now rendering in the right place, although it's still 1 pixel lower than it should be. Here's the difference in the scene again with Otis and Carla:

The text is pretty close now!
Another issue arose when Klusark tested the set tri. In this set, the text was layered on top of other text, resulting in a mess! This was actually the original bug that inspired all of the text refactoring in the first place, so I probably should have tested this sooner. Why wasn't this text fixed by these changes? It turns out that the text is placed based on the position of the ship. So, when the ship moves, the text should be placed relative to the ship's location. To find the ship's location, a function called WorldToScreen is called to find the screen coordinates for the ship. The text is then rendered using these coordinates. In the retail version, instead of passing a screen coordinate (0,0 -> 640,480), it instead passes a floating point value in the range -1 to 1. Removing the conversion from the function and adding it as needed throughout the graphics primitive drawing code fixes the issue, although the result isn't exactly right, with the text being drawn above the ship rather than below. Still, it's quite a bit better than it was!

Working text on the Tri-Island Map
This work can be found in the updated PR #964.

No comments:

Post a Comment