FRUSTUM TUTORIAL | V3.2
Using the Fusion for VBS3 Frustum information feature
Introduction
The Fusion for VBS3 Frustrum information feature provides functionality to programmatically access
information related to the latest viewpoint within VBS3. This example demonstrated in this tutorial is
intended to show how Fusion for VBS3 can be used to access the current Frustum within VBS3 run-time
environment using the OnNgDrawnPass callback. The view/viewing frustum is the region of space in
modeled world that may appear on the screen; it is the field of view of the notional camera.
The frustum information provided through this callback relates to the current viewpoint within VBS3.
This viewpoint could either be related to the player view or the view of a controlled camera.
This tutorial provides step by step instruction on how to obtain the viewing frustum of the player Unit
and apply an action to objects within the viewing frustum.
1
Fusion for VBS3 v3.2 Tutorials
© SimCentric Technologies 2014
Action is applied only to the blue object as it is within the view frustum of the camera.
Background
The OnNgDrawnPass must be invoked to obtain Frustum information. The syntax of this callbacks is as
follows:
VBS3PLUGIN_EXPORT void WINAPI OnNgDrawnPass(paramDrawnPass *param, DWORD
paramSize);
The OnNgDrawnPass callback expedites obtaining the viewing frustum of current VBS3 viewpoint. This
callback sends in as its argument a pointer which can be used to directly access the Frustum details
within the VBS3 environment.
2
Fusion for VBS3 v3.2 Tutorials
© SimCentric Technologies 2014
Walkthrough
The following tutorial gives a thorough description of how to obtain the viewing frustum of a player unit
using the call back OnNgDrawnPass and apply the ‘prone’status to all the units within the view
frustum.
Assume ABC is a triangle with position A, position B and position C. The player Unit is in position A and
the other two positions are vertices of the frustum in X, Z plane.
3
Fusion for VBS3 v3.2 Tutorials
© SimCentric Technologies 2014
clipDistFar(Far plane) – The maximum distance viewed by the camera.
projTanLeft – The tangent value of angle on the left
projTanRight – The tangent value of angle on the right
Assume that U is a unit located at position P around the player Unit and in order to find whether U is
within the player Unit’s viewing frustum the position of B and C must be calculated. If U is within the
frustum view of the player Unit, then the area of the triangle (ABC) == area of triangle (PAB)+area of
triangle (PAC)+ area of triangle (PBC). If U is within the viewing frustum of the player Unit, the ‘prone’
status is applied to the unit. In the following tutorial the above logic is applied to 150 units.
To begin, declare and initialize all the relevant global variables. The following code is an example of how
the global variables are declared in this plugin.
4
Fusion for VBS3 v3.2 Tutorials
© SimCentric Technologies 2014
#define PI (3.141592653589793)
Unit playerUnit;
volatile bool started = false;
string displayString;
//matrix which contains the values to calculate the positions of A,B and C
D3DXMATRIX translationMatrix, Matrix, rotationMatrix;
D3DXVECTOR3 vectorB_in, vectorB_out ,vectorC_in, vectorC_out;
//position of the player unit
position3D posA, posB, posC;
//viewing direction of player unit
double previous_Direction = 0;
double curent_Direction = 0;
//Time difference
float totaltime = 0.0f;
FrustumSpecNG view_frustum;
// Area of the triangles
double A1, A2;
double K1 = 0.995;
double K2 = 1.005;
Unit unit[150];
Following the declaration of the global variables, obtain the viewing frustum values by calling the call
back OnNgDrawnPass.The viewing frustum value includes position,direction,speed,projection angle of
the camera. The values of frustum view are stored in a FustrumSpecNG struct. These values are used to
calculate the current camera direction of the player unit. The following is an example of how it could be
done.
//Obtain the values of the viewing frustum
VBS3PLUGIN_EXPORT void WINAPI OnNgDrawnPass(paramDrawnPass *param, DWORD
paramSize)
{
view_frustum = param->cameraFrustum;
};
5
Fusion for VBS3 v3.2 Tutorials
© SimCentric Technologies 2014
Once the frustum values are obtained, create a function to calculate the area of a given triangle. The
following code is an example of how it could be done.
//Calculate area of a given triaingle
double getArea(position3D& posA, position3D& posB, position3D& posC)
{
return abs((posA.getX()*(posB.getZ()-posC.getZ()) +
posB.getX()*(posC.getZ()-posA.getZ()) + posC.getX()*(posA.getZ()posB.getZ()))/2);
}
Create a function to check whether the area Of (ABC) = area Of [(PAB) + area Of (PAC) +area Of (PBC)].
Where P is the position of an unit around the player unit. The following is the example code to
accomplish this:
//Function to check areaOf(ABC) == areOf(PAB)+ areOf(PAC)+ areOf(PBC)
bool isSame(position3D& pos)
{
A1 = getArea(posA, posB, pos) + getArea(posA, posC, pos) +
getArea(posC, posB, pos);
A2 = getArea(posA, posB, posC);
return ( K1*A1 < A2 && A2 < K2*A1 );
}
where, ‘pos’ denotes the position P which is the units position around the player unit.
Following the creation of the above function find the camera direction in radians . The following code
is an example of how it could be done.
6
Fusion for VBS3 v3.2 Tutorials
© SimCentric Technologies 2014
//Calculates current camera direction in radians using viewDirX and
viewDirZ
//viewdir is the direction in which the player is seeing
if (view_frustum.viewDirX > 0 && view_frustum.viewDirZ > 0) //find out
which angle it is closer to the axis
curent_Direction = atan(view_frustum.viewDirX/view_frustum.viewDirZ);
else if (view_frustum.viewDirX > 0 && view_frustum.viewDirZ < 0)
curent_Direction = PI+atan(view_frustum.viewDirX/view_frustum.viewDirZ);
else if (view_frustum.viewDirX < 0 && view_frustum.viewDirZ < 0)
curent_Direction = atan(view_frustum.viewDirX/view_frustum.viewDirZ)+PI;
else if (view_frustum.viewDirX < 0 && view_frustum.viewDirZ > 0)
curent_Direction = 2*PI+atan(view_frustum.viewDirX/view_frustum.viewDirZ);
The viewing angle differs each time the player changes his direction and the values calculated for each
direction of the player is stored.The above calculated value in radians is used to find the positions of A,B
and C using the tranformation and translation matrix, the following code is explained in detail below.
If the previous direction is not equal to the current direction, the rotational matrix uses the values of
the current direction to rotate about the origin and then translate it from the origin and store the final
value into the matrix(rotation + translation).
7
Fusion for VBS3 v3.2 Tutorials
© SimCentric Technologies 2014
//The totaltime stores deltaT (Time difference between each
onsimulation loop) and once the value is >o.5f and if the previous
direction and the current direction is different the positions A, B
and C are obtained.
This check has been done to optimize the performance
totaltime += deltaT;
if (totaltime > 0.5f && previous_Direction != curent_Direction && started)
{
totaltime = 0.0f;
//Creates a rotation matrix to rotate about the origin
D3DXMatrixRotationY(&rotationMatrix, curent_Direction);
//Creates a translation matrix about the origin - for it to move
D3DXMatrixTranslation(&translationMatrix, view_frustum.pointPosX, 0,
view_frustum.pointPosZ);
//Create a transformation matrix (rotation+ translation)
Matrix = (rotationMatrix)*(translationMatrix);
The functions below calculates the positions of A, B and C using the values in the matrix.
D3DXVECTOR3(-view_frustum.clipDistFar*view_frustum.projTanLeft, 0,
view_frustum.clipDistFar); contains three parameters x,z,y respectively.Where
X= clipDistFar*view_frustum.projTanLeft
Z=0
Y= clipDistFar
Vector B obtains the value clipDistFar value from view_frustum to calculate the position B. And these
values are used for the transformation. Simillarly for vector C. This calculation enables to find the
positions of B and C.
8
Fusion for VBS3 v3.2 Tutorials
© SimCentric Technologies 2014
//Obtain the coordinates of position B
vectorB_in = D3DXVECTOR3(view_frustum.clipDistFar*view_frustum.projTanLeft, 0,
view_frustum.clipDistFar);
D3DXVec3TransformCoord(&vectorB_out, &vectorB_in, &Matrix);
//Obtain the coordinates of position C
vectorC_in =
D3DXVECTOR3(view_frustum.clipDistFar*view_frustum.projTanRight, 0,
view_frustum.clipDistFar);
D3DXVec3TransformCoord(&vectorC_out, &vectorC_in, &Matrix);
//As Y values are not used, and as the the viewing frustum is taken from
the player Unit's upper body a terrain height of 1 m is added to the
position
double ret = TerrainUtilities::getTerrainHeight(view_frustum.pointPosX,
view_frustum.pointPosZ);
posA = position3D(view_frustum.pointPosX, view_frustum.pointPosZ, ret + 1);
posB = position3D(vectorB_out.x, vectorB_out.z, ret + 1);
posC = position3D(vectorC_out.x, vectorC_out.z, ret + 1);
Once the positions of A ,B and C are identified , find the units within the view frustum of the player Unit
and apply the actions accordingly (i.e. whether the units should ’prone’ or remain standing.The
following code is an example of how it could be done.
//Apply the 'prone' status for the units within the viewing frustum of the
player unit.
for (int i = 0; i < 150; ++i)
{
//Check if the unit is within the view frustum of the playerUnit and apply
the actions accordingly
if(isSame(position3D(unit[i].getPosition())))
{
//Apply the 'prone' status to the unit
UnitUtilities::applyUnitPos(unit[i],DOWN);
}
else
UnitUtilities::applyUnitPos(unit[i],UP);
}
previous_Direction = curent_Direction;
}
9
Fusion for VBS3 v3.2 Tutorials
© SimCentric Technologies 2014
The following code is implemented within the input parameter ‘a’ in the plugin function callback. This
parameter creates 150 units and initializes the scenario.
//Obtain the player’s properties
playerUnit = MissionUtilities::getPlayer();
//Update the player’s properties
UnitUtilities::updateStaticProperties(playerUnit);
UnitUtilities::updateDynamicProperties(playerUnit);
//Obtain the position of the player Unit, as to create the 150 units
relative to the playerUnit's position
position3D playerUnit_pos = playerUnit.getPosition();
//Create 150 units
int count = 0;
for (int j = 0; j < 15; ++j)
for (int i = 0; i < 10; ++i)
{
//Set the position to units
unit[count].setPosition(playerUnit.getPosition() + position3D(j + 1, i + 1,
0));
//Create the units and update their properties
UnitUtilities::CreateUnit(unit[count]);
UnitUtilities::updateStaticProperties(unit[count]);
UnitUtilities::updateDynamicProperties(unit[count]);
++count;
}
****
10
Fusion for VBS3 v3.2 Tutorials
© SimCentric Technologies 2014
© Copyright 2026 Paperzz