Page 1 of 1

[...–790] Bad 3d Floors

Posted: Thu May 06, 2010 21:59
by Geometer
I have found a bug, which occurs when we define 3d floor's floor and ceiling planes using vertex height things. This bug occurs when all three (ceiling) vertex slope things have the same non-integer height. I have generated an example to show this:

Image

On the previous screenshot you can see some weird 3d floors. But if we slightly change the height of some vertex slopes, everything will be much better:

Image

The package which contains good and bad versions is attached.

Re: [...–790] Bad 3d Floors

Posted: Thu Aug 12, 2010 23:51
by Gez
I found the source of the bug.

The deal is this: there are, in gl_walls.cpp, three functions (GLWall::InverseFloors(), GLWall::ClipFFloors() and GLWall::DoFFloorBlocks()) using a block such as this:

Code: Select all

		if (rover->top.plane->a | rover->top.plane->b)
		{
			ff_topleft=rover->top.plane->ZatPoint(vertexes[0]);
			ff_topright=rover->top.plane->ZatPoint(vertexes[1]);
		}
		else
		{
			ff_topleft = ff_topright = *rover->top.texheight;
		}

		if (rover->bottom.plane->a | rover->bottom.plane->b)
		{
			ff_bottomleft=rover->bottom.plane->ZatPoint(vertexes[0]);
			ff_bottomright=rover->bottom.plane->ZatPoint(vertexes[1]);
		}
		else
		{
			ff_bottomleft = ff_bottomright = *rover->bottom.texheight;
		}
The problem is that if a sloped sector is effectively not sloped (because all three vertex heights are at the same height), then it fails the first check and uses the second, taking *rover->top/bottom.texheight instead of the top/bottom.plane->ZatPoint(). In the case of this test map, the texheight you get is 0, so it glitches.

I don't know the precise reason for this test. I've commented out the expression and replaced it with (1) for both top and bottom in all three functions (but DoFFloorBlocks() is enough to solve the problem in the test map). In my tests (the test map, and also Demon Eclipse maps 1, 2 and 7 so far), I haven't seen any glitch yet, with sloped or unsloped 3D floors alike.

Re: [...–790] Bad 3d Floors

Posted: Fri Aug 13, 2010 7:01
by Graf Zahl
The reason is efficiency. This code is called a lot and not calling ZatPoint if not needed saves a significant amount of time in maps without slopes (Nimrod, for example.) I always tried to avoid adding another flag to the data structures for this but it looks like it's necessary after all.

Re: [...–790] Bad 3d Floors

Posted: Fri Aug 13, 2010 11:46
by Gez
For flat slopes like this one, plane->d can be used. But on regular 3D floors, it would glitch.


This is working for me so far:

Code: Select all

		if (rover->top.plane->a | rover->top.plane->b)
		{
			ff_topleft=rover->top.plane->ZatPoint(vertexes[0]);
			ff_topright=rover->top.plane->ZatPoint(vertexes[1]);
		}
		else if (*rover->top.texheight == 0)
		{
			ff_topleft = ff_topright = rover->top.plane->d;
		}
		else
		{
			ff_topleft = ff_topright = *rover->top.texheight;
		}
Could the test case be replicated in a situation where *texheight is not null?

Re: [...–790] Bad 3d Floors

Posted: Fri Aug 13, 2010 11:58
by Graf Zahl
That won't work due to sign issues. Depending on where the plane came from it has to be inverted.

Re: [...–790] Bad 3d Floors

Posted: Fri Aug 13, 2010 12:09
by Graf Zahl
I moved the problem code into a subfunction to reduce redundancy. The function now looks like this:

Code: Select all

inline void GLWall::GetPlanePos(F3DFloor::planeref *planeref, int &left, int &right)
{
	if (planeref->plane->a || planeref->plane->b)
	{
		left=planeref->plane->ZatPoint(vertexes[0]);
		right=planeref->plane->ZatPoint(vertexes[1]);
	}
	else if(planeref->isceiling == sector_t::ceiling)
	{
		left = right = planeref->plane->d;
	}
	else
	{
		left = right = -planeref->plane->d;
	}
}
I think that's enough but I'll run some tests later.