pioneer/src/Camera.h

157 lines
4.2 KiB
C++

// Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
#ifndef _CAMERA_H
#define _CAMERA_H
#include "Color.h"
#include "FrameId.h"
#include "graphics/Frustum.h"
#include "graphics/Light.h"
#include "matrix4x4.h"
#include "vector3.h"
class Body;
class Frame;
namespace Graphics {
class Material;
class Renderer;
} // namespace Graphics
class CameraContext : public RefCounted {
public:
// camera for rendering to width x height with view frustum properties
CameraContext(float width, float height, float fovAng, float zNear, float zFar);
~CameraContext();
float GetWidth() const { return m_width; }
float GetHeight() const { return m_height; }
float GetFovAng() const { return m_fovAng; }
float GetZNear() const { return m_zNear; }
float GetZFar() const { return m_zFar; }
// frame to position the camera relative to
void SetCameraFrame(FrameId frame) { m_frame = frame; }
// return the parent frame of this camera
FrameId GetCameraFrame() const { return m_frame; }
// camera position relative to the frame origin
void SetCameraPosition(const vector3d &pos) { m_pos = pos; }
// camera orientation relative to the frame origin
void SetCameraOrient(const matrix3x3d &orient) { m_orient = orient; }
const vector3d GetCameraPos() const { return m_pos; }
const matrix3x3d &GetCameraOrient() const { return m_orient; }
// get the frustum. use for projection
const Graphics::Frustum &GetFrustum() const { return m_frustum; }
// generate and destroy the camere frame, used mostly to transform things to camera space
void BeginFrame();
void EndFrame();
FrameId GetTempFrame() const { return m_camFrame; }
// apply projection and modelview transforms to the renderer
void ApplyDrawTransforms(Graphics::Renderer *r);
private:
float m_width;
float m_height;
float m_fovAng;
float m_zNear;
float m_zFar;
Graphics::Frustum m_frustum;
FrameId m_frame;
vector3d m_pos;
matrix3x3d m_orient;
FrameId m_camFrame;
};
class Camera {
public:
Camera(RefCountedPtr<CameraContext> context, Graphics::Renderer *renderer);
const CameraContext *GetContext() const { return m_context.Get(); }
void Update();
void Draw(const Body *excludeBody = nullptr);
// camera-specific light with attached source body
class LightSource {
public:
LightSource(const Body *b, Graphics::Light &light) :
m_body(b),
m_light(light) {}
const Body *GetBody() const { return m_body; }
const Graphics::Light &GetLight() const { return m_light; }
private:
const Body *m_body;
Graphics::Light m_light;
};
struct Shadow {
vector3d centre;
float srad;
float lrad;
bool operator<(const Shadow &other) const { return srad / lrad < other.srad / other.lrad; }
};
void CalcShadows(const int lightNum, const Body *b, std::vector<Shadow> &shadowsOut) const;
float ShadowedIntensity(const int lightNum, const Body *b) const;
void PrincipalShadows(const Body *b, const int n, std::vector<Shadow> &shadowsOut) const;
// lights with properties in camera space
const std::vector<LightSource> &GetLightSources() const { return m_lightSources; }
int GetNumLightSources() const { return static_cast<Uint32>(m_lightSources.size()); }
private:
RefCountedPtr<CameraContext> m_context;
Graphics::Renderer *m_renderer;
std::unique_ptr<Graphics::Material> m_billboardMaterial;
// temp attrs for sorting and drawing
struct BodyAttrs {
Body *body;
// camera position and orientation relative to the body
vector3d viewCoords;
matrix4x4d viewTransform;
// body distance from camera
double camDist;
// body flags. DRAW_LAST is the interesting one
Uint32 bodyFlags;
// if true, draw object as billboard of billboardSize at billboardPos
bool billboard;
vector3f billboardPos;
float billboardSize;
Color billboardColor;
// for sorting. "should a be drawn before b?"
// NOTE: Add below function (thus an indirection) in order
// to decouple Camera from Body.h
static bool sort_BodyAttrs(const BodyAttrs &a, const BodyAttrs &b);
friend bool operator<(const BodyAttrs &a, const BodyAttrs &b)
{
return sort_BodyAttrs(a, b);
};
};
std::list<BodyAttrs> m_sortedBodies;
std::vector<LightSource> m_lightSources;
};
#endif