ProbnikGL

http://www.letransit.ee/img/mg/probnikgl.rar
Size: 1 762 kbytes
http://www.letransit.ee/img/mg/ui.pk3 ; problems with unpacking this file
Size: 45 kbytes


Thats my bsp loader it loads map with light map
Archive has source
It has console: press ` tilde: ` ~
Look image if you dont know where it is :)
http://healthlinks.washington.edu/howto/navigating/tilde.gif

/devmap ; load a map
/devmap maps/level
/devmap maps/level1
/devmap maps/level2
/devmap maps/level3

/vid_restart ; restart...

All variables can be found in *.cfg file

*.pk3 files are no "magic packed file" its just renamed ZIP! file

Have phun

Please feedback ;)
Posted on 2004-02-18 14:39:53 by zabnik
Corrupt archive :( sorry man, the exe extracted ok but some of its dependancies didnt and I just see fullscreen black:(

Congrats on completing that anyway :)

I ended up deciding not to go with bsp in the end, I'm implementing a hybrid scenegraph and hierarchical arbitrary volumes (osp 2) engine ;)
I'm just hooked on the idea of osp2 not mapping empty space, and I love the idea of hierarchical culling .. then there's the ability to add/remove/alter surfaces dynamically in realtime, it's just too hard to make holes in geometry in a bsp..
Posted on 2004-02-19 21:58:27 by Homer
Nice program :) I could manage to make it run despite of the corrupted archive (EvilHomer2k, the second link is for the missing file). However I had two problems:

1) The tilde key is not there for non-english keyboards, in fact mine doesn't have a tilde key. :grin: It took me a while to figure out which key triggered the console.

2) The console itself doesn't seem to work correctly... I just see all white. :(

Hope you fix this soon! :alright:
Posted on 2004-02-20 11:24:57 by QvasiModo
OK then ill soon upload screenshots and it loads md3 now w/o animation

Homer, what is osp2 ? 1st time I see that
Posted on 2004-02-23 14:00:15 by zabnik
HI!

Me again with my ProbnikGL!
With new eXtended problems :)

I'm stuck at "CheckBrush", the problem is that I'm getting stuck in mid-air.
Actually I converted that function from C++ sample. Currently I'm using it like this:

m2m m_traceRatio,r4_1_0

mov m_traceType,TYPE_SPHERE
mov m_bCollided,FALSE
m2m m_traceRadius,cl_cameraRadius
mov esi,addrBrush
mov ecx,nBrush
.while ecx
push esi
push ecx

mov eax,[esi.BSP_BRUSH.textureID]
imul eax,sizeof BSP_TEXTURE
add eax,offset addrTexture
mov eax,[eax.BSP_TEXTURE.textureType]
and eax,01h
; Check if we have brush sides and the current brush is solid and collidable
.if [esi.BSP_BRUSH.numOfBrushSides] > 0 && eax
invoke CheckBrush,esi,old_xpos,old_ypos,old_zpos,xpos,ypos,zpos
.endif

pop ecx
pop esi
add esi,sizeof BSP_BRUSH
dec ecx
.endw


Question: Do I use it correctly or not? Well I'm just trying to make it work, so I skipped the "CheckNode".

The C++ sample: http://www.gametutorials.com/Tutorials/opengl/OpenGL_Pg5.htm
Posted on 2004-11-28 12:53:33 by zabnik
Well?

Actually I managed to do simple collision detection in BSP Tree using the "FindLeaf" proc from C++ tutorial converted by to ASM!

How: When "CAMERA" is outside the map then the LEAF, where the camera is, cluster number equals -1, sooo.... when I get cluster -1 I put camera to old positon. BUT It's still wrong, I can't do the sliding effect using this method, so sad ;(
Posted on 2004-11-28 13:15:00 by zabnik
Do it properly then - find out what leaf the camera is in, extract the frustum from the current view matrix, now apply frustum culling to all the surfaces within that leaf. Use the PVS information to help cull surfaces in OTHER leaves.
Posted on 2004-11-29 05:08:07 by Homer
I did the PVS thingy, now I'm trying to do collision detection with sliding effect.
The "CheckBrush" isn't working:



; My check brush
CheckBrush proc uses esi edi ecx ebx pBrush:DWORD,vStart_x:REAL4,vStart_y:REAL4,vStart_z:REAL4,vEnd_x:REAL4,vEnd_y:REAL4,vEnd_z:REAL4

LOCAL startRatio:REAL4,endRatio:REAL4,Ratio1:REAL4,Ratio:REAL4
LOCAL startsOut:BYTE
LOCAL startDistance:REAL4,endDistance:REAL4
; Let's store a variable for the offset (like for sphere collision)
LOCAL _offset:REAL4

m2m m_traceRatio,r4_1_0
m2m endRatio,r4_1_0 ; = 1.0f ; Set the end ratio to 1
m2m startRatio,r4_n1_0 ; = -1.0f ; Like in BrushCollision.htm, start a ratio at -1
mov startsOut,FALSE ; This tells us if we starting outside the brush
mov m_bCollided,FALSE

; This function actually does the collision detection between our movement
; vector and the brushes in the world data. We will go through all of the
; brush sides and check our start and end ratio against the planes to see if
; they pass each other. We start the startRatio at -1 and the endRatio at
; 1, but as we set the ratios to their intersection points (ratios), then
; they slowly move toward each other. If they pass each other, then there
; is definitely not a collision.

; Go through all of the brush sides and check collision against each plane
mov edi,pBrush
mov ecx,[edi.BSP_BRUSH.numOfBrushSides]
.while ecx

push ecx

; Here we grab the current brush side and plane in this brush
;tBSPBrushSide *pBrushSide = &m_pBrushSides[pBrush->brushSide + i];
mov eax,[edi.BSP_BRUSH.brushSide]
add eax,ecx
imul eax,eax,sizeof BSP_BRUSHSIDE
add eax,addrBrushside

comment ;
mov ebx,[eax.BSP_BRUSHSIDE.textureID]
imul ebx,ebx,sizeof BSP_TEXTURE
add ebx,offset addrTexture
mov ebx,[ebx.BSP_TEXTURE.textureType]
and ebx,01h
.if !ebx
inc ecx
.continue
.endif;

;tBSPPlane *pPlane = &m_pPlanes[pBrushSide->plane];
mov esi,[eax.BSP_BRUSHSIDE.plane]
imul esi,esi,sizeof BSP_PLANE
add esi,addrPlane

; If we are testing sphere collision we need to add the sphere radius
.if m_traceType == TYPE_SPHERE
m2m _offset,m_traceRadius
.endif

; Test the start and end points against the current plane of the brush side.
; Notice that we add an offset to the distance from the origin, which makes
; our sphere collision work.
;float startDistance = Dot(vStart, pPlane->vNormal) - (pPlane->d + offset);
fld [esi.BSP_PLANE.vNormal.x]
fmul [vStart_x]
fld [esi.BSP_PLANE.vNormal.y]
fmul [vStart_y]
fld [esi.BSP_PLANE.vNormal.z]
fmul [vStart_z]
faddp st(1),st(0)
faddp st(1),st(0)
fld [esi.BSP_PLANE.d]
fadd _offset
fsubp st(1),st(0)
fstp startDistance
;float endDistance = Dot(vEnd, pPlane->vNormal) - (pPlane->d + offset);
fld [esi.BSP_PLANE.vNormal.x]
fmul [vEnd_x]
fld [esi.BSP_PLANE.vNormal.y]
fmul [vEnd_y]
fld [esi.BSP_PLANE.vNormal.z]
fmul [vEnd_z]
faddp st(1),st(0)
faddp st(1),st(0)
fld [esi.BSP_PLANE.d]
fadd _offset
fsubp st(1),st(0)
fstp endDistance

; Make sure we start outside of the brush's volume
fcmp startDistance,r4_0_0
.if !ZERO? && !CARRY? ;(startDistance > 0)
mov startsOut,TRUE
.endif

; Stop checking since both the start and end position are in front of the plane
fcmp startDistance,r4_0_0
.if !ZERO? && !CARRY? ;(startDistance > 0)
fcmp endDistance,r4_0_0
.if !ZERO? && !CARRY? ;(endDistance > 0)
ret
.endif
.endif

; Continue on to the next brush side if both points are behind or on the plane
fcmp startDistance,r4_0_0
.if CARRY? || ZERO? ;(startDistance <= 0)
fcmp endDistance,r4_0_0
.if CARRY? || ZERO? ;(endDistance <= 0)
pop ecx
dec ecx
.continue
.endif
.endif

; If the distance of the start point is greater than the end point, we have a collision!
fcmp startDistance,endDistance
.if !ZERO? && !CARRY? ; (startDistance > endDistance)
; This gets a ratio from our starting point to the approximate collision spot
;float Ratio1 = (startDistance - kEpsilon) / (startDistance - endDistance);
fld startDistance ; ST(1)
fsub kEpsilon
fld startDistance ; ST(0)
fsub endDistance
fdivp st(1),st(0) ; ST(0) = ST(1) / ST(0)
fstp Ratio1

; If this is the first time coming here, then this will always be true,
; since startRatio starts at -1.0f. We want to find the closest collision,
; so we still continue to check all of the brushes before quitting.
fcmp Ratio1,startRatio
.if !ZERO? && !CARRY? ;(Ratio1 > startRatio)
; Set the startRatio (currently the closest collision distance from start)
m2m startRatio,Ratio1
mov m_bCollided,TRUE ; Let us know we collided!
.endif
.else
; Get the ratio of the current brush side for the endRatio
;float Ratio = (startDistance + kEpsilon) / (startDistance - endDistance);
fld startDistance ; ST(1)
fadd kEpsilon
fld startDistance ; ST(0)
fsub endDistance
fdivp st(1),st(0) ; ST(0) = ST(1) / ST(0)
fstp Ratio

; If the ratio is less than the current endRatio, assign a new endRatio.
; This will usually always be true when starting out.
fcmp Ratio,endRatio
.if CARRY? ;(Ratio < endRatio)
m2m endRatio,Ratio
.endif
.endif

pop ecx
dec ecx

.endw

; If we didn't start outside of the brush we don't want to count this collision - return;
.if startsOut == FALSE
ret
.endif

; If our startRatio is less than the endRatio there was a collision!!!
fcmp startRatio,endRatio
.if CARRY? ;(startRatio < endRatio)
; Make sure the startRatio moved from the start and check if the collision
; ratio we just got is less than the current ratio stored in m_traceRatio.
; We want the closest collision to our original starting position.
fcmp startRatio,r4_n1_0
.if !ZERO? && !CARRY? ;(startRatio > -1)
fcmp startRatio,m_traceRatio
.if CARRY? ;(startRatio < m_traceRatio)
; If the startRatio is less than 0, just set it to 0
fcmp startRatio,r4_0_0
.if CARRY? ;(startRatio < 0)
m2m startRatio,r4_0_0
.endif
.endif
; Store the new ratio in our member variable for later
m2m m_traceRatio,startRatio
.endif
.endif

ret

CheckBrush endp

// GameTutorial's check brush
void CQuake3BSP::CheckBrush(tBSPBrush *pBrush, CVector3 vStart, CVector3 vEnd)
{
float startRatio = -1.0f; // Like in BrushCollision.htm, start a ratio at -1
float endRatio = 1.0f; // Set the end ratio to 1
bool startsOut = false; // This tells us if we starting outside the brush

// This function actually does the collision detection between our movement
// vector and the brushes in the world data. We will go through all of the
// brush sides and check our start and end ratio against the planes to see if
// they pass each other. We start the startRatio at -1 and the endRatio at
// 1, but as we set the ratios to their intersection points (ratios), then
// they slowly move toward each other. If they pass each other, then there
// is definitely not a collision.

// Go through all of the brush sides and check collision against each plane
for(int i = 0; i < pBrush->numOfBrushSides; i++)
{
// Here we grab the current brush side and plane in this brush
tBSPBrushSide *pBrushSide = &m_pBrushSides[pBrush->brushSide + i];
tBSPPlane *pPlane = &m_pPlanes[pBrushSide->plane];

// Let's store a variable for the offset (like for sphere collision)
float offset = 0.0f;

// If we are testing sphere collision we need to add the sphere radius
if(m_traceType == TYPE_SPHERE)
offset = m_traceRadius;

// Test the start and end points against the current plane of the brush side.
// Notice that we add an offset to the distance from the origin, which makes
// our sphere collision work.
float startDistance = Dot(vStart, pPlane->vNormal) - (pPlane->d + offset);
float endDistance = Dot(vEnd, pPlane->vNormal) - (pPlane->d + offset);

// Make sure we start outside of the brush's volume
if(startDistance > 0) startsOut = true;

// Stop checking since both the start and end position are in front of the plane
if(startDistance > 0 && endDistance > 0)
return;

// Continue on to the next brush side if both points are behind or on the plane
if(startDistance <= 0 && endDistance <= 0)
continue;

// If the distance of the start point is greater than the end point, we have a collision!
if(startDistance > endDistance)
{
// This gets a ratio from our starting point to the approximate collision spot
float Ratio1 = (startDistance - kEpsilon) / (startDistance - endDistance);

// If this is the first time coming here, then this will always be true,
// since startRatio starts at -1.0f. We want to find the closest collision,
// so we still continue to check all of the brushes before quitting.
if(Ratio1 > startRatio)
{
// Set the startRatio (currently the closest collision distance from start)
startRatio = Ratio1;
m_bCollided = true; // Let us know we collided!
}
}
else
{
// Get the ratio of the current brush side for the endRatio
float Ratio = (startDistance + kEpsilon) / (startDistance - endDistance);

// If the ratio is less than the current endRatio, assign a new endRatio.
// This will usually always be true when starting out.
if(Ratio < endRatio)
endRatio = Ratio;
}
}

// If we didn't start outside of the brush we don't want to count this collision - return;
if(startsOut == false)
{
return;
}

// If our startRatio is less than the endRatio there was a collision!!!
if(startRatio < endRatio)
{
// Make sure the startRatio moved from the start and check if the collision
// ratio we just got is less than the current ratio stored in m_traceRatio.
// We want the closest collision to our original starting position.
if(startRatio > -1 && startRatio < m_traceRatio)
{
// If the startRatio is less than 0, just set it to 0
if(startRatio < 0)
startRatio = 0;

// Store the new ratio in our member variable for later
m_traceRatio = startRatio;
}
}
}


fcmp macro arg1,arg2

fld arg1
fcomp arg2
fstsw ax
fwait
sahf
endm
Posted on 2004-11-29 16:02:38 by zabnik
zabnik, won't this fcomp be a bit faster:


ufcomp macro var1,var2
mov eax,var1
mov ebx,var2
mov ecx,eax
and ecx,ebx
sar ecx,31
xor eax,ecx
xor ebx,ecx
cmp eax,ebx
endm

after the macro, you use jxx as if you compared two signed integers. Only exception is that -0.0 < 0.0 ^^"


edit: tested:



invoke GetTickCount
push eax
mov ecx,1000000000
push ecx
@@:
;-----------------\
; fcmp ke1,ke2 ; 4276 milliseconds
;ufcomp ke1,ke2 ; 3765 milliseconds
;-----------------/
dec dword ptr[esp]
jnz @B
pop ecx

invoke GetTickCount
pop edx
sub eax,edx
print eax

with both lines commented (empty code in loop), it takes 3355 milliseconds, so actually to execute 1 bil times, fcmp takes 921ms, while ufcomp takes 410ms
124% speedup , taking 0.7 cycle ...
This is on an AthlonXP2000+ (DDR 400MHz)
Posted on 2004-11-29 17:11:37 by Ultrano
Ofcourse it will be faster, but it will be useless if my "CheckBrush" isn't working.
Posted on 2004-11-30 12:37:04 by zabnik
Hi!

I uploaded the new ProbnikGL with simply collision detection, using Leaf's cluster number.
If its negative that mean's the camera is outside the map so I put old position in current.

http://www.hot.ee/valk777/ProbnikGL_0_03.rar - binary
http://www.hot.ee/valk777/probnikgl_0_03.asm - source

A nice screenshot with lightmap:
Posted on 2004-12-06 16:02:22 by zabnik
So far, so good - can you instance the camera and/or switch it to third person view, and how does your camera collision operate in third person? :)
Posted on 2004-12-06 22:18:10 by Homer
I will try when I do the sliding effect.
Posted on 2004-12-07 08:03:06 by zabnik
By sliding effect, do you mean basic physics in terms of velocity and direction of travel, or do you ALSO mean friction coefficients for surfaces, possibly gravity thrown into the mix... ?
Posted on 2004-12-07 08:42:22 by Homer
Yea, basic, not ALL at a same time ofcourse, I never did that before.

I have fixed the CheckBrush, now im doing sliding, something is not okay now, because when I try to fly throught some wall I warp into unknownage, but some walls are okey, and It slides by them as I wanted.

http://www.hot.ee/valk777/probnikgl.exe
You may look at it. It needs all *.pk3 from older package
Posted on 2004-12-08 10:34:25 by zabnik
Make a BSP map that consists of nothing but a cube with 6 walls and nice simple surface normals - use it to check that your planar collision code is behaving itself :)
Posted on 2004-12-09 02:08:59 by Homer
Great idea :idea: must try...
Posted on 2004-12-09 08:53:52 by zabnik
Sorry to be so obvious:P Great idea? No, just simple prooftesting, I know, but it's important to eliminate the bleeding obvious when debugging, it saves time chasing red herrings :)
Posted on 2004-12-11 09:03:46 by Homer
I created box map, but something strange is going on:
    |             |

| |
----+-------------+----
|*************|
|*** solid ***|
|*************|
----+-------------+----
| |
| |

Im colliding with each line
Posted on 2004-12-20 16:04:02 by zabnik
My educated guess based on your reply:
You are colliding with the (infinite) plane defined by each surface.
Your point/plane collision test is working, but you need a second more refined test for point/polygon.

You need to firstly test if the point is before, behind or on the plane, and if its behind or on the plane you should test if its within the bounds of the surface geometry itself.

You seem to have forgotten that a flat plane defined by a flat surface extends beyond that surface (to infinity - and beyond !!)
Posted on 2004-12-20 22:22:54 by Homer