How? Spawning TSStatic object when not in Camera Frustum
by Viren Thambidorai · in Torque Game Engine Advanced · 08/27/2008 (11:51 pm) · 10 replies
How do I re-spawn/objects only when they are Not in Camera view.
I have destroyable Tree objects(TSStatic). when vehicle collides with them, they are removed from scene and collision is disabled.(in tsstatic class).
A schedule() is called to execute unHide(), which enables collision and add it Back to scene.
I want to re-spawn them after specific time(using schedule) only when re-spawn point(object location ) is not in Frustum.
Do I need to create plane using aspect/fov, near/far and check if location is in front of plane ?
Any suggestions how to do this ?
Thanks
I have destroyable Tree objects(TSStatic). when vehicle collides with them, they are removed from scene and collision is disabled.(in tsstatic class).
A schedule() is called to execute unHide(), which enables collision and add it Back to scene.
I want to re-spawn them after specific time(using schedule) only when re-spawn point(object location ) is not in Frustum.
Do I need to create plane using aspect/fov, near/far and check if location is in front of plane ?
Any suggestions how to do this ?
Thanks
#2
It would be a nice feature to have from script.
It should just take a SceneObject and tests its world box against the current view frustum. This would be gClientSceneGraph->getFrustum() on the client side (or in a single player only game).
On the server side things get tricky. I would add the visibility test to the connection so you can do something like %clientConnection.isVisible( %mySceneObject ). Internally i think it would have to build a frustum from the current camera settings... as i don't think it ever keeps a Frustum object around.
Either way... its doable and should be a fairly simple project with someone with a little programming experience.
09/02/2008 (1:44 am)
I don't think there is currently a "isVisible" test available from script... but you could easily add one. It would be a nice feature to have from script.
It should just take a SceneObject and tests its world box against the current view frustum. This would be gClientSceneGraph->getFrustum() on the client side (or in a single player only game).
On the server side things get tricky. I would add the visibility test to the connection so you can do something like %clientConnection.isVisible( %mySceneObject ). Internally i think it would have to build a frustum from the current camera settings... as i don't think it ever keeps a Frustum object around.
Either way... its doable and should be a fairly simple project with someone with a little programming experience.
#3
I was thinking of doing it in engine, in the unhide function.
Before the object is added back to scene and collision is enabled, I have to check if the object
location is in camera frustum.
I am using script just to call(schedule) unhide function(in engine), after specified amount of time.
all other things are done in TSStatic class.
i got following from searching,
For searching the point in frustum=> A point is within the frustum if it is in front of all six planes
simultaneously.
I have to calculate the distance of the point from the plane. If the distance is positive then the point is in front of the plane. If it's negative then it's behind the plane.
Here's the formula for calculating a point's distance from a plane:
distance = A * X + B * Y + C * Z + D
Where A, B, C, and D are the four numbers that define the plane and X, Y, and Z are the point's coordinates.
we can use dot product for checking the distance.
The three parameters A,B,C are the plane normal values, and D is distance of plane from origin.
But how to get those values in TGEA ?
I tried using
But the A,B,C values for clipping planes are always zero, hence result is always 0, that is not in any plane.
Or do I have to basic way,
multiply projMatrix and viewMatrix and store values in plane, then check for angle using dot product between plane and object location.
Thanks in advance.
09/02/2008 (3:42 am)
Thanks for reply !I was thinking of doing it in engine, in the unhide function.
Before the object is added back to scene and collision is enabled, I have to check if the object
location is in camera frustum.
I am using script just to call(schedule) unhide function(in engine), after specified amount of time.
all other things are done in TSStatic class.
i got following from searching,
For searching the point in frustum=> A point is within the frustum if it is in front of all six planes
simultaneously.
I have to calculate the distance of the point from the plane. If the distance is positive then the point is in front of the plane. If it's negative then it's behind the plane.
Here's the formula for calculating a point's distance from a plane:
distance = A * X + B * Y + C * Z + D
Where A, B, C, and D are the four numbers that define the plane and X, Y, and Z are the point's coordinates.
we can use dot product for checking the distance.
The three parameters A,B,C are the plane normal values, and D is distance of plane from origin.
But how to get those values in TGEA ?
I tried using
state->getBaseZoneState().clipPlanes[i].distToPlane(this->getPosition())
But the A,B,C values for clipping planes are always zero, hence result is always 0, that is not in any plane.
Or do I have to basic way,
multiply projMatrix and viewMatrix and store values in plane, then check for angle using dot product between plane and object location.
Thanks in advance.
#4
If you look at GameProcessCameraQuery() you can see how it builds most of these. In fact you can use the same code except if your game is multiplayer. In multiplayer there are multiple clients all with the potential for the object to be in view. So you may need to test multiple client GameConnection objects in that case.
The one thing that this code doesn't deal with is the aspect ratio... this isn't something only known on the client at this time. You can probably safely hard code it for a typical 3/4 ratio.
09/02/2008 (8:47 am)
If your using TGEA 1.7 you can use the Frustum class to do the test...Frustum frustum; frustum.set( fov, screenAspectRatio, nearPlaneDist, farPlaneDist, cameraTransform ); if ( frustum.intersects( sceneObject->getWorldBox() ) ) Con::printf( "The object is visible!" );... but you'll need the fov, aspectRatio of the players window/screen, the near and far distance and the camera transform.
If you look at GameProcessCameraQuery() you can see how it builds most of these. In fact you can use the same code except if your game is multiplayer. In multiplayer there are multiple clients all with the potential for the object to be in view. So you may need to test multiple client GameConnection objects in that case.
The one thing that this code doesn't deal with is the aspect ratio... this isn't something only known on the client at this time. You can probably safely hard code it for a typical 3/4 ratio.
#5
I think I can get those parameters using GFX->getFrustum(F32*,....)
I'll look into gameProcessQuery()..
09/04/2008 (7:13 am)
I am using TGEA 1.0.3 and My game is single player. I think I can get those parameters using GFX->getFrustum(F32*,....)
I'll look into gameProcessQuery()..
#6
09/04/2008 (7:59 am)
@Viren - Maybe... not sure if the GFX frustum settings will be correct when your script code is called. Anyway... being single player makes it easier to solve.
#7
Since I am using TGEA 1.0.3, there is no Frustum class,
I'll set the 6 plane from view-projection matrix. {any other way for finding the six planes ?}
Then compare using dot product, to check if a point is inside any frustum.
09/08/2008 (1:53 am)
I think I've to do it manually.Since I am using TGEA 1.0.3, there is no Frustum class,
I'll set the 6 plane from view-projection matrix. {any other way for finding the six planes ?}
Then compare using dot product, to check if a point is inside any frustum.
#8
pointInFrustum Funtction
inFrustum always returns false, even if camera is looking at the object location.
What do I need to change ?
09/09/2008 (6:05 am)
Got code from Frustum class from TGEA 1.7MatrixF projMat = GFX->getProjectionMatrix(); projMat = projMat * GFX->getViewMatrix(); //get view-proj Matrix mPlanes[ PlaneRight ].set( projMat[3] - projMat[0], projMat[7] - projMat[4], projMat[11] - projMat[8], projMat[15] - projMat[12] ); // Left clipping plane. mPlanes[ PlaneLeft ].set( projMat[3] + projMat[0], projMat[7] + projMat[4], projMat[11] + projMat[8], projMat[15] + projMat[12] ); // Bottom clipping plane. mPlanes[ PlaneBottom ].set( projMat[3] + projMat[1], projMat[7] + projMat[5], projMat[11] + projMat[9], projMat[15] + projMat[13] ); // Top clipping plane. mPlanes[ PlaneTop ].set( projMat[3] - projMat[1], projMat[7] - projMat[5], projMat[11] - projMat[9], projMat[15] - projMat[13] ); // Near clipping plane mPlanes[ PlaneNear ].set( projMat[3] + projMat[2], projMat[7] + projMat[6], projMat[11] + projMat[10], projMat[15] + projMat[14] ); // Far clipping plane. mPlanes[ PlaneFar ].set( projMat[3] - projMat[2], projMat[7] - projMat[6], projMat[11] - projMat[10], projMat[15] - projMat[14] ); for ( S32 i=0; i < PlaneCount; i++ ) mPlanes[i].normalize(); bool inFrustum = pointInFrustum(this->getPosition()); //'this' is TSStatic object.
pointInFrustum Funtction
bool pointInFrustum( const Point3F &point ) const
{
F32 maxDot;
// Note the planes are ordered left, right, near,
// far, top, bottom for getting early rejections
// from the typical horizontal scene.
for ( S32 i = 0; i < PlaneCount; i++ )
{
const PlaneF &plane = mPlanes[ i ];
// This is pretty much as optimal as you can
// get for a plane vs point test...
//
// 1 comparision
// 2 multiplies
// 1 adds
//
// It will early out as soon as it detects the
// point is outside one of the planes.
maxDot = mDot( plane , point ) + plane.d;
if ( maxDot < 0.0f )
return false;
}
return true;
}inFrustum always returns false, even if camera is looking at the object location.
What do I need to change ?
#9
I suspect i'm building one or more of the planes facing the wrong direction... which would cause your test to fail. You'll have to do a little debugging to check things and fix any errors.
09/10/2008 (7:24 pm)
@Viren - The Frustum::set() function that builds a frustum from a projection matrix may or may not be correct. I commented where i got the algorithm from, but since i never ended up using it in the code... its pretty much untested. I suspect i'm building one or more of the planes facing the wrong direction... which would cause your test to fail. You'll have to do a little debugging to check things and fix any errors.
#10
09/11/2008 (10:55 pm)
I implemented that in different way, more optimized than the standard six plane compare method.
Torque 3D Owner Viren Thambidorai