I have started porting my code over to C++ and as with everything I code I make modular libs everywhere I can, so here is the first of many hopefully
Its a basic camera class that allows you to setup and use the camera to orbit an object or a position (the joys of overloaded functions and encapsulation) and includes raycasting for object selection
Camera.h
#pragma once
#include "agk.h"
struct Vector2 {
float x;
float y;
};
struct Vector3 {
float x;
float y;
float z;
};
struct Range {
float fNear;
float fFar;
};
struct Angle {
float fCurrent;
float fMin;
float fMax;
float fStep;
};
struct Elevation {
float fCurrent;
float fMin;
float fMax;
float fStep;
};
struct Distance {
float fCurrent;
float fMin;
float fMax;
float fStep;
};
class Camera {
float fMMX;
float fMMY;
Range range;
Angle angle;
Elevation elevation;
Distance distance;
public:
Camera(float fAngle, float fElevation, float fDistance, float fNear, float fFar);
~Camera();
void Update(UINT iObjectID);
void Update(float fX, float fY, float fZ);
UINT Raycast(UINT iObjectID = NULL);
void SetAngleMax(float fValue);
void SetAngleMin(float fValue);
void SetAngleStep(float fValue);
void SetElevationMax(float fValue);
void SetElevationMin(float fValue);
void SetElevationStep(float fValue);
void SetDistanceMax(float fValue);
void SetDistanceMin(float fValue);
void SetDistanceStep(float fValue);
};
Camera.cpp
#include "Camera.h"
Camera::Camera(float fAngle, float fElevation, float fDistance, float fNear, float fFar)
{
range.fNear = fNear;
range.fFar = fFar;
distance.fMin = fNear;
distance.fMax = fFar;
distance.fStep = 1.0f;
distance.fCurrent = fDistance;
angle.fMin = -1.0f;
angle.fMax = -1.0f;
angle.fStep = 1.05f;
angle.fCurrent = fAngle;
elevation.fMin = 1.0f;
elevation.fMax = 180.0f;
elevation.fStep = 0.5;
elevation.fCurrent = fElevation;
agk::SetCameraRange(1, range.fNear, range.fFar);
}
Camera::~Camera(){}
void Camera::Update(UINT iObjectID)
{
if (agk::GetObjectExists(iObjectID))
{
float fOrigX = agk::GetObjectX(iObjectID);
float fOrigY = agk::GetObjectY(iObjectID);
float fOrigZ = agk::GetObjectZ(iObjectID);
this->Update(fOrigX, fOrigY, fOrigZ);
}
}
void Camera::Update(float fX, float fY, float fZ) {
fMMX = agk::GetPointerX() - fMMX;
fMMY = agk::GetPointerY() - fMMY;
if (agk::GetRawMouseRightState() == 1)
{
angle.fCurrent = angle.fCurrent + fMMX * angle.fStep;
elevation.fCurrent = agk::Clamp(elevation.fCurrent - fMMY * elevation.fStep, elevation.fMin, elevation.fMax);
}
float fDelta = agk::GetRawMouseWheelDelta();
if (fDelta != 0.0f) {
distance.fCurrent = agk::Clamp(distance.fCurrent - fDelta * distance.fStep, distance.fMin, distance.fMax);
}
float fOrbitX = distance.fCurrent * agk::Sin(elevation.fCurrent) * agk::Sin(angle.fCurrent) + fX;
float fOrbitY = distance.fCurrent * agk::Cos(elevation.fCurrent) + fY;
float fOrbitZ = distance.fCurrent * agk::Sin(elevation.fCurrent) * agk::Cos(angle.fCurrent) + fZ;
agk::SetCameraPosition(1, fOrbitX, fOrbitY, fOrbitZ);
agk::SetCameraLookAt(1, fX, fY, fZ, 0);
fMMX = agk::GetPointerX();
fMMY = agk::GetPointerY();
}
UINT Camera::Raycast(UINT iObjectID) {
Vector2 vMouse;
vMouse.x = agk::GetPointerX();
vMouse.y = agk::GetPointerY();
Vector3 vScreen;
vScreen.x = agk::Get3DVectorXFromScreen(vMouse.x, vMouse.y) * distance.fCurrent * 100.0f;
vScreen.y = agk::Get3DVectorYFromScreen(vMouse.x, vMouse.y) * distance.fCurrent * 100.0f;
vScreen.z = agk::Get3DVectorZFromScreen(vMouse.x, vMouse.y) * distance.fCurrent * 100.0f;
Vector3 vCamera;
vCamera.x = agk::GetCameraX(1);
vCamera.y = agk::GetCameraY(1);
vCamera.z = agk::GetCameraZ(1);
Vector3 vTarget;
vTarget.x = vCamera.x + vScreen.x;
vTarget.y = vCamera.y + vScreen.y;
vTarget.z = vCamera.z + vScreen.z;
return agk::ObjectRayCast(iObjectID, vCamera.x, vCamera.y, vCamera.z, vTarget.x, vTarget.y, vTarget.z);
}
// Setters
void Camera::SetAngleMax(float fValue){angle.fMax = fValue;}
void Camera::SetAngleMin(float fValue){angle.fMin = fValue;}
void Camera::SetAngleStep(float fValue){angle.fStep = fValue;}
void Camera::SetElevationMax(float fValue){elevation.fMax = fValue;}
void Camera::SetElevationMin(float fValue){elevation.fMin = fValue;}
void Camera::SetElevationStep(float fValue){elevation.fStep = fValue;}
void Camera::SetDistanceMax(float fValue){distance.fMax = fValue;}
void Camera::SetDistanceMin(float fValue){distance.fMin = fValue;}
void Camera::SetDistanceStep(float fValue){distance.fStep = fValue;}
And a usage example:
// Includes
#include "template.h"
#include "Camera.h"
// Namespace
using namespace AGK;
app App;
// these should really be in a class, avoid globals where possible
Camera * gCamera; // Decalre the camera as global pointer (on the *heap)
UINT iBoxID; // Decalre the camera as global pointer (on the stack (without the *)
void app::Begin(void)
{
// create the camera
gCamera = new Camera(45, 50, 40, 30, 10000);
iBoxID = agk::CreateObjectBox(10.0f, 10.0f, 10.0f);
agk::SetWindowSize(1024, 768, false);
agk::SetVirtualResolution (1024, 768);
agk::SetClearColor( 151, 170, 204 );
agk::SetSyncRate(0,0);
agk::SetScissor(0,0,0,0);
}
int app::Loop (void)
{
// orbit object
//gCamera->Update(iBoxID);
// or orbit position
gCamera->Update(0, 0, 0);
UINT iHitObject = gCamera->Raycast(iBoxID);
if (iHitObject)
{
agk::SetObjectColor(iBoxID, 255, 0, 0, 255);
}
else
{
agk::SetObjectColor(iBoxID, 0, 255, 0, 255);
}
// mixing strings and nunbers
char buffer[50];
sprintf(buffer, "Object Hit? %i", iHitObject);
agk::Print(buffer);
agk::Print( agk::ScreenFPS() );
agk::Print("Right mouse button to move camera");
agk::Print("Mouse wheel to zoom");
agk::Sync();
return 0;
}
void app::End (void)
{
// always delete when "new" is used
delete gCamera;
}
C++ can be pretty complex and daunting when you first look at it but it really isn't that bad once you get a grip with the basics and there is a wealth of information out there on the dos and don'ts
Why use C++ ? ... in a empty project with unrestricted FPS (set to 0) I see 100 frames pre second more in Tier2 than Tier1 on my laptop, that's how much Basic eats, need I say any more?
I am no C++ guru and I am still learning a lot myself so if YOU can improve on my code or have any pointers for me then please don't hold back.
I got some cool stuff in the works, watch this space
Visual Studio can be downloaded here:
https://visualstudio.microsoft.com/vs/older-downloads/
TGC recomend 2015, 2019 works to, I have not tried 2022 yet, the project templates are already in your AppGameKit install under "Tier2"... Have Fun