GodView
by Nelson A. K. Gonsalves · in Torque Game Engine · 10/29/2002 (7:21 pm) · 9 replies
---------------------------------------------------------
EDITED November 10th
---------------------------------------------------------
I did some code cleanup... nothing really changed... Just fewer lines for the same functionality.
---------------------------------------------------------
EDITED October 31th
---------------------------------------------------------
Added code to change the camera when the view of the character is blocked by an Interior Object, the camera will switch to the interior settings specified(via $prefs) and if even so the Interior object is on the way it will change the view to a top-down perspective(x and y offsets set to 0, z offset set to the collision z and camera rotation to -90)
So now you can go into houses and still see the character :). I didnt follow the standard isometric way of removing the house's roof when inside... but my way has some advantages, like being able to see all interior walls(most isometric games block the view of some sides, south side frequently), also as the camera gets closer to the player when inside, it provides extra detail for seeing items and stuff inside the houses. :)
Well... I think that's it...
P.S.: I changed the instructions and code bellow to include the above feature.
---------------------------------------------------------
I just submitted this to the resource section and decided to post it here so more people can see it right away :)
This is my first try at creating a resourse so any feedback is welcome :)
This code allows you to view the game area from a third person camera with a custom offset and rotation. The camera is centralized on the player and follows his movements but doesnt rotate, creates an effect similar to isometric games, like Diablo and Ultima Online.
--Installation Instructions:
- Add "godView.cc" to your Engine Code.
- Add the following line to Player.h under the Player declaration or around line 408 if you have a clean install:
virtual void getCameraTransform(F32* pos,MatrixF* mat); //Added for GodView
- Add the following lines somewhere in your game scripts(~\client\defaults.cs is a nice place):
$pref::Player::GodView = true; //Activate/Deactivate GodView
$pref::Player::GodViewFov = 10;//Field of View used when in GodView
$pref::Player::ViewRotation0 = (-45);//Camera Pitch
$pref::Player::ViewRotation1 = (0);//Camera Roll
$pref::Player::ViewRotation2 = (0);//Camera Yaw
$pref::Player::ViewOffset0 = (0);//How far to the sides of the player
$pref::Player::ViewOffset1 = (-100);//How far behind the player
$pref::Player::ViewOffset2 = (100);//How far above the player
$pref::Player::GodViewFovInterior = 90;//Field of View used when in GodView and inside a building(interior object)
$pref::Player::ViewRotationInterior0 = (-45);//Camera Pitch when inside a building(interior object)
$pref::Player::ViewRotationInterior1 = (0);//Camera Roll when inside a building(interior object)
$pref::Player::ViewRotationInterior2 = (0);//Camera Yaw when inside a building(interior object)
$pref::Player::ViewOffsetInterior0 = (0);//How far to the sides of the player when inside a building(interior object)
$pref::Player::ViewOffsetInterior1 = (-5);//How far behind the player when inside a building(interior object)
$pref::Player::ViewOffsetInterior2 = (4);//How far above the player when inside a building(interior object)
While in-game you can switch GodView On and Off by setting $pref::Player::GodView
When the view of the character is Blocked by a Interior Object then the camera will switch to the interior settings above and if even so the Interior object is on the way it will change the view to a top-down perspective(x and y offsets set to 0, z offset set to the collision z and camera rotation to -90)
Also, you can change any of the $prefs and it will update the camera instantly, going into first person mode disables the effect until you switch to third person mode again.
Have fun and let me know of any problems you find and suggestions you might have.
//-------------------------------------------------------
//godView.cc
//-------------------------------------------------------
#include "game/player.h"
#include "game/shadow.h"
void Player::getCameraTransform(F32* pos,MatrixF* mat)
{
// Returns camera to world space transform
// Handles camera position
//If Godview is false or the camera is in first person mode then set FOV to default and let the parent handle this.
if (!Con::getFloatVariable("$pref::Player::GodView")||isFirstPerson()) {
if(getCameraFov()!=Con::getFloatVariable("$Pref::Player::defaultFov"))
setCameraFov(Con::getFloatVariable("$Pref::Player::defaultFov"));
Parent::getCameraTransform(pos,mat);
return;
}
if (isServerObject() && mShapeInstance)
mShapeInstance->animateNodeSubtrees(true); //not sure what this is for, keeping it here for now.
Point3F objStartPos,startPos;
//Use the camera node as the starting position if it exists.
if (mDataBlock->cameraNode != -1) {
mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&objStartPos);
getRenderTransform().mulP(objStartPos,&startPos);
}
else
{
getRenderTransform().getColumn(3,&startPos);
}
Point3F Offset;
Point3F ViewRotation;
RayInfo Collision;
if(!gClientContainer.castRay(Point3F(startPos.x+Con::getFloatVariable("$pref::Player::ViewOffset0"), startPos.y+Con::getFloatVariable("$pref::Player::ViewOffset1"), startPos.z+Con::getFloatVariable("$pref::Player::ViewOffset2")), Point3F(startPos.x, startPos.y, startPos.z), InteriorObjectType, &Collision)) {
if(getCameraFov()!=Con::getFloatVariable("$Pref::Player::GodViewFov"))
setCameraFov(Con::getFloatVariable("$Pref::Player::GodViewFov"));
ViewRotation[0] = Con::getFloatVariable("$pref::Player::ViewRotation0");
ViewRotation[1] = Con::getFloatVariable("$pref::Player::ViewRotation1");
ViewRotation[2] = Con::getFloatVariable("$pref::Player::ViewRotation2");
Offset[0] = Con::getFloatVariable("$pref::Player::ViewOffset0");
Offset[1] = Con::getFloatVariable("$pref::Player::ViewOffset1");
Offset[2] = Con::getFloatVariable("$pref::Player::ViewOffset2");
}
else {
if(getCameraFov()!=Con::getFloatVariable("$Pref::Player::GodViewFovInterior"))
setCameraFov(Con::getFloatVariable("$Pref::Player::GodViewFovInterior"));
Point3F newPos;
float newCamRot;
if (!gClientContainer.castRay(Point3F(startPos.x+Con::getFloatVariable("$pref::Player::ViewOffsetInterior0"), startPos.y+Con::getFloatVariable("$pref::Player::ViewOffsetInterior1"), startPos.z+Con::getFloatVariable("$pref::Player::ViewOffsetInterior2")-1), Point3F(startPos.x, startPos.y, startPos.z), InteriorObjectType, &Collision))
{
newPos.x=Con::getFloatVariable("$pref::Player::ViewOffsetInterior0");
newPos.y=Con::getFloatVariable("$pref::Player::ViewOffsetInterior1");
newPos.z=Con::getFloatVariable("$pref::Player::ViewOffsetInterior2");
newCamRot = Con::getFloatVariable("$pref::Player::ViewRotationInterior0");
}
else
{
newPos.x=0;
newPos.y=0;
newPos.z=Collision.t+2;
newCamRot=-90;
}
ViewRotation[0] = newCamRot;
ViewRotation[1] = Con::getFloatVariable("$pref::Player::ViewRotationInterior1");
ViewRotation[2] = Con::getFloatVariable("$pref::Player::ViewRotationInterior2");
Offset[0] = newPos.x;
Offset[1] = newPos.y;
Offset[2] = newPos.z;
}
EulerF Rotate;
QuatF QRotation;
Rotate.set(mDegToRad(ViewRotation[0]),
mDegToRad(ViewRotation[1]),
mDegToRad(ViewRotation[2]));
QRotation.set(Rotate);
QRotation.setMatrix(mat);
mat->setColumn(3,startPos + Offset);
}
EDITED November 10th
---------------------------------------------------------
I did some code cleanup... nothing really changed... Just fewer lines for the same functionality.
---------------------------------------------------------
EDITED October 31th
---------------------------------------------------------
Added code to change the camera when the view of the character is blocked by an Interior Object, the camera will switch to the interior settings specified(via $prefs) and if even so the Interior object is on the way it will change the view to a top-down perspective(x and y offsets set to 0, z offset set to the collision z and camera rotation to -90)
So now you can go into houses and still see the character :). I didnt follow the standard isometric way of removing the house's roof when inside... but my way has some advantages, like being able to see all interior walls(most isometric games block the view of some sides, south side frequently), also as the camera gets closer to the player when inside, it provides extra detail for seeing items and stuff inside the houses. :)
Well... I think that's it...
P.S.: I changed the instructions and code bellow to include the above feature.
---------------------------------------------------------
I just submitted this to the resource section and decided to post it here so more people can see it right away :)
This is my first try at creating a resourse so any feedback is welcome :)
This code allows you to view the game area from a third person camera with a custom offset and rotation. The camera is centralized on the player and follows his movements but doesnt rotate, creates an effect similar to isometric games, like Diablo and Ultima Online.
--Installation Instructions:
- Add "godView.cc" to your Engine Code.
- Add the following line to Player.h under the Player declaration or around line 408 if you have a clean install:
virtual void getCameraTransform(F32* pos,MatrixF* mat); //Added for GodView
- Add the following lines somewhere in your game scripts(~\client\defaults.cs is a nice place):
$pref::Player::GodView = true; //Activate/Deactivate GodView
$pref::Player::GodViewFov = 10;//Field of View used when in GodView
$pref::Player::ViewRotation0 = (-45);//Camera Pitch
$pref::Player::ViewRotation1 = (0);//Camera Roll
$pref::Player::ViewRotation2 = (0);//Camera Yaw
$pref::Player::ViewOffset0 = (0);//How far to the sides of the player
$pref::Player::ViewOffset1 = (-100);//How far behind the player
$pref::Player::ViewOffset2 = (100);//How far above the player
$pref::Player::GodViewFovInterior = 90;//Field of View used when in GodView and inside a building(interior object)
$pref::Player::ViewRotationInterior0 = (-45);//Camera Pitch when inside a building(interior object)
$pref::Player::ViewRotationInterior1 = (0);//Camera Roll when inside a building(interior object)
$pref::Player::ViewRotationInterior2 = (0);//Camera Yaw when inside a building(interior object)
$pref::Player::ViewOffsetInterior0 = (0);//How far to the sides of the player when inside a building(interior object)
$pref::Player::ViewOffsetInterior1 = (-5);//How far behind the player when inside a building(interior object)
$pref::Player::ViewOffsetInterior2 = (4);//How far above the player when inside a building(interior object)
While in-game you can switch GodView On and Off by setting $pref::Player::GodView
When the view of the character is Blocked by a Interior Object then the camera will switch to the interior settings above and if even so the Interior object is on the way it will change the view to a top-down perspective(x and y offsets set to 0, z offset set to the collision z and camera rotation to -90)
Also, you can change any of the $prefs and it will update the camera instantly, going into first person mode disables the effect until you switch to third person mode again.
Have fun and let me know of any problems you find and suggestions you might have.
//-------------------------------------------------------
//godView.cc
//-------------------------------------------------------
#include "game/player.h"
#include "game/shadow.h"
void Player::getCameraTransform(F32* pos,MatrixF* mat)
{
// Returns camera to world space transform
// Handles camera position
//If Godview is false or the camera is in first person mode then set FOV to default and let the parent handle this.
if (!Con::getFloatVariable("$pref::Player::GodView")||isFirstPerson()) {
if(getCameraFov()!=Con::getFloatVariable("$Pref::Player::defaultFov"))
setCameraFov(Con::getFloatVariable("$Pref::Player::defaultFov"));
Parent::getCameraTransform(pos,mat);
return;
}
if (isServerObject() && mShapeInstance)
mShapeInstance->animateNodeSubtrees(true); //not sure what this is for, keeping it here for now.
Point3F objStartPos,startPos;
//Use the camera node as the starting position if it exists.
if (mDataBlock->cameraNode != -1) {
mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&objStartPos);
getRenderTransform().mulP(objStartPos,&startPos);
}
else
{
getRenderTransform().getColumn(3,&startPos);
}
Point3F Offset;
Point3F ViewRotation;
RayInfo Collision;
if(!gClientContainer.castRay(Point3F(startPos.x+Con::getFloatVariable("$pref::Player::ViewOffset0"), startPos.y+Con::getFloatVariable("$pref::Player::ViewOffset1"), startPos.z+Con::getFloatVariable("$pref::Player::ViewOffset2")), Point3F(startPos.x, startPos.y, startPos.z), InteriorObjectType, &Collision)) {
if(getCameraFov()!=Con::getFloatVariable("$Pref::Player::GodViewFov"))
setCameraFov(Con::getFloatVariable("$Pref::Player::GodViewFov"));
ViewRotation[0] = Con::getFloatVariable("$pref::Player::ViewRotation0");
ViewRotation[1] = Con::getFloatVariable("$pref::Player::ViewRotation1");
ViewRotation[2] = Con::getFloatVariable("$pref::Player::ViewRotation2");
Offset[0] = Con::getFloatVariable("$pref::Player::ViewOffset0");
Offset[1] = Con::getFloatVariable("$pref::Player::ViewOffset1");
Offset[2] = Con::getFloatVariable("$pref::Player::ViewOffset2");
}
else {
if(getCameraFov()!=Con::getFloatVariable("$Pref::Player::GodViewFovInterior"))
setCameraFov(Con::getFloatVariable("$Pref::Player::GodViewFovInterior"));
Point3F newPos;
float newCamRot;
if (!gClientContainer.castRay(Point3F(startPos.x+Con::getFloatVariable("$pref::Player::ViewOffsetInterior0"), startPos.y+Con::getFloatVariable("$pref::Player::ViewOffsetInterior1"), startPos.z+Con::getFloatVariable("$pref::Player::ViewOffsetInterior2")-1), Point3F(startPos.x, startPos.y, startPos.z), InteriorObjectType, &Collision))
{
newPos.x=Con::getFloatVariable("$pref::Player::ViewOffsetInterior0");
newPos.y=Con::getFloatVariable("$pref::Player::ViewOffsetInterior1");
newPos.z=Con::getFloatVariable("$pref::Player::ViewOffsetInterior2");
newCamRot = Con::getFloatVariable("$pref::Player::ViewRotationInterior0");
}
else
{
newPos.x=0;
newPos.y=0;
newPos.z=Collision.t+2;
newCamRot=-90;
}
ViewRotation[0] = newCamRot;
ViewRotation[1] = Con::getFloatVariable("$pref::Player::ViewRotationInterior1");
ViewRotation[2] = Con::getFloatVariable("$pref::Player::ViewRotationInterior2");
Offset[0] = newPos.x;
Offset[1] = newPos.y;
Offset[2] = newPos.z;
}
EulerF Rotate;
QuatF QRotation;
Rotate.set(mDegToRad(ViewRotation[0]),
mDegToRad(ViewRotation[1]),
mDegToRad(ViewRotation[2]));
QRotation.set(Rotate);
QRotation.setMatrix(mat);
mat->setColumn(3,startPos + Offset);
}
#3
10/30/2002 (11:06 pm)
I just edited the above post to add a new feature, for more details look at the first topic in this thread.
#4
First off, you rock. This is such a cool piece of code, and you deservce kudos for writing it.
Now, I have a question. What if I want a traditional third person setup, where the camera stays behind the user at all times, no matter how they turn? Can you hint at how this might be done?
Another possibility is a free motion camera, such as one finds in Sacrifice. The camera is loose around a running character.
Anyway, any help you can give would be great. I have tried a number of things, but I have yet to have any success.
Thanks
11/09/2002 (11:58 am)
Nelson,First off, you rock. This is such a cool piece of code, and you deservce kudos for writing it.
Now, I have a question. What if I want a traditional third person setup, where the camera stays behind the user at all times, no matter how they turn? Can you hint at how this might be done?
Another possibility is a free motion camera, such as one finds in Sacrifice. The camera is loose around a running character.
Anyway, any help you can give would be great. I have tried a number of things, but I have yet to have any success.
Thanks
#5
I'm glad you liked it.
Hmmm... by traditional third person camera you mean like the one already included in the engine, but maybe with some more offset control?
I'm not familiar with Sacrifice, what exactly do you mean by free motion, it is loose around the character but how do you control it? And how does it behaves?
I might do some more work on this soon... I was never a fan of first person view, and third person view in torque could use some work. :)
11/09/2002 (11:11 pm)
Thank you Chris :)I'm glad you liked it.
Hmmm... by traditional third person camera you mean like the one already included in the engine, but maybe with some more offset control?
I'm not familiar with Sacrifice, what exactly do you mean by free motion, it is loose around the character but how do you control it? And how does it behaves?
I might do some more work on this soon... I was never a fan of first person view, and third person view in torque could use some work. :)
#6
Yeah I think first person has it's place, but it certainly gets overused.
When I say traditional third person, I mean both the camera control and the view of the person. As an example, when the character turns, the camera stays behind them, and when you move the mouse, the camera moves, not the player. The player is controlled using the keyboard controls. The camera moves with the mouse rotations.
Sacrifice was a game by Shiny Entertainment that had a really interested control system. The character was controlled with the keyboard, as in most 3rd persons, but the mouse allowed a full rotation around the character, with both zoom in and zoom out functionality. So it was third person, but with more control of the camera. It looks like the Torque engine could easily control this.
If you have time, could you let me know what objects control the camera? I can write the code to do the rest, I think.
Thanks again
Chris
11/10/2002 (6:16 pm)
Nelson,Yeah I think first person has it's place, but it certainly gets overused.
When I say traditional third person, I mean both the camera control and the view of the person. As an example, when the character turns, the camera stays behind them, and when you move the mouse, the camera moves, not the player. The player is controlled using the keyboard controls. The camera moves with the mouse rotations.
Sacrifice was a game by Shiny Entertainment that had a really interested control system. The character was controlled with the keyboard, as in most 3rd persons, but the mouse allowed a full rotation around the character, with both zoom in and zoom out functionality. So it was third person, but with more control of the camera. It looks like the Torque engine could easily control this.
If you have time, could you let me know what objects control the camera? I can write the code to do the rest, I think.
Thanks again
Chris
#7
(under Movement Keys)
function cameraright(%val)
{
$pref::Player::ViewRotation2 += getMouseAdjustAmount(%val*3);
$pref::Player::ViewOffset1 += getMouseAdjustAmount();
// $pref::Player::ViewOffset0 += getMouseAdjustAmount(%val/10);
}
function cameraleft(%val)
{
$pref::Player::ViewRotation2 -= getMouseAdjustAmount(%val*3);
$pref::Player::ViewOffset1 -= getMouseAdjustAmount();
// $pref::Player::ViewOffset0 -= getMouseAdjustAmount(%val/10);
}
And at the end of Movement Keys, changing:
EDIT: You will also need to add the keybindings to config.cs
12/24/2004 (12:27 am)
I've managed to add the following to default.bind.cs to get rotational/movemet control of the camera, but the camera doesn't orbit around the player.(under Movement Keys)
function cameraright(%val)
{
$pref::Player::ViewRotation2 += getMouseAdjustAmount(%val*3);
$pref::Player::ViewOffset1 += getMouseAdjustAmount();
// $pref::Player::ViewOffset0 += getMouseAdjustAmount(%val/10);
}
function cameraleft(%val)
{
$pref::Player::ViewRotation2 -= getMouseAdjustAmount(%val*3);
$pref::Player::ViewOffset1 -= getMouseAdjustAmount();
// $pref::Player::ViewOffset0 -= getMouseAdjustAmount(%val/10);
}
And at the end of Movement Keys, changing:
moveMap.bind( mouse, xaxis, yaw ); moveMap.bind( mouse, yaxis, pitch );with:
moveMap.bind( mouse, xaxis, cameraleft ); moveMap.bind( mouse, yaxis, cameraright );
EDIT: You will also need to add the keybindings to config.cs
#8
12/24/2004 (1:49 am)
You should just implement the advanced Camera resource. While quite useful at the time, this thread has been deprecated by a much more flexible camera system, including pretty much the exact camera mode you are looking for here (it's called Orbit mode).
#9
%camera.setOrbitMode(%player, %transformdownward, Max, Min, Cur, 0);
LocalClientConnection.setCameraObject(%camera);
LocalClientConnection.setControlObject(%player);
the distanced of the orbit camera by default is controled by (Max - Min). If you want to fix this then look for
pos *= mMaxOrbitDist - mMinOrbitDist
and replace that with
pos *= mCurOrbitDist
You will also need to expose mCurOrbitDist to the script either as a direct variable or using console functions.
However, I can't seem to get the OrbitMode to work in 1.5 even though there is only one line difference between the camera source files in 1.4.2 and 1.5.2
You can even get a fixed camera mode by doing this:
%camera.setFlyMode();
LocalClientConnection.setCameraObject(%camera);
LocalClientConnection.setControlObject(%player);
%camera.setPosition(); // <- Uhhhh I forgot the function but you get the Idea
To return to first and third person you have to turn the camera and the control object back to the player then toggle if you want first person or not.
I have not figured out a tracking mode using the default camera resource... This would be the only thing that would need to be added...
Unless....
Doesn't the pathed camera have a track mode? If this is the case could you not just set up one node and have it track the player?! I'm not sure about that part...
08/12/2007 (9:40 am)
Better! in 1.4 you could use the default camera resource to create a god mode... however it tended to bob with your character. Here is an example:%camera.setOrbitMode(%player, %transformdownward, Max, Min, Cur, 0);
LocalClientConnection.setCameraObject(%camera);
LocalClientConnection.setControlObject(%player);
the distanced of the orbit camera by default is controled by (Max - Min). If you want to fix this then look for
pos *= mMaxOrbitDist - mMinOrbitDist
and replace that with
pos *= mCurOrbitDist
You will also need to expose mCurOrbitDist to the script either as a direct variable or using console functions.
However, I can't seem to get the OrbitMode to work in 1.5 even though there is only one line difference between the camera source files in 1.4.2 and 1.5.2
You can even get a fixed camera mode by doing this:
%camera.setFlyMode();
LocalClientConnection.setCameraObject(%camera);
LocalClientConnection.setControlObject(%player);
%camera.setPosition(); // <- Uhhhh I forgot the function but you get the Idea
To return to first and third person you have to turn the camera and the control object back to the player then toggle if you want first person or not.
I have not figured out a tracking mode using the default camera resource... This would be the only thing that would need to be added...
Unless....
Doesn't the pathed camera have a track mode? If this is the case could you not just set up one node and have it track the player?! I'm not sure about that part...
Torque Owner Davis Ray Sickmon, Jr
Default Studio Name