Support for third person view and so on.
This commit is contained in:
parent
df40c16c5a
commit
66627a4de2
@ -104,7 +104,10 @@ namespace spades {
|
||||
// FIXME: preferences?
|
||||
corpseSoftTimeLimit(30.f), // FIXME: this is not used
|
||||
corpseSoftLimit(6),
|
||||
corpseHardLimit(16)
|
||||
corpseHardLimit(16),
|
||||
|
||||
followYaw(0.f),
|
||||
followPitch(0.f)
|
||||
{
|
||||
SPADES_MARK_FUNCTION();
|
||||
SPLog("Initializing...");
|
||||
|
@ -48,6 +48,146 @@ SPADES_SETTING(cg_ejectBrass, "");
|
||||
|
||||
namespace spades {
|
||||
namespace client {
|
||||
|
||||
class SandboxedRenderer : public IRenderer {
|
||||
Handle<IRenderer> base;
|
||||
AABB3 clipBox;
|
||||
bool allowDepthHack;
|
||||
|
||||
void OnProhibitedAction() {
|
||||
}
|
||||
|
||||
bool CheckVisibility(const AABB3 &box) {
|
||||
if (!clipBox.Contains(box) ||
|
||||
!isfinite(box.min.x) || !isfinite(box.min.y) || !isfinite(box.min.z) ||
|
||||
!isfinite(box.max.x) || !isfinite(box.max.y) || !isfinite(box.max.z)) {
|
||||
OnProhibitedAction();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
protected:
|
||||
~SandboxedRenderer(){}
|
||||
public:
|
||||
|
||||
SandboxedRenderer(IRenderer *base) :
|
||||
base(base) {}
|
||||
|
||||
void SetClipBox(const AABB3 &b)
|
||||
{ clipBox = b; }
|
||||
void SetAllowDepthHack(bool h)
|
||||
{ allowDepthHack = h; }
|
||||
|
||||
void Init() { OnProhibitedAction(); }
|
||||
void Shutdown() { OnProhibitedAction(); }
|
||||
|
||||
IImage *RegisterImage(const char *filename)
|
||||
{ return base->RegisterImage(filename); }
|
||||
IModel *RegisterModel(const char *filename)
|
||||
{ return base->RegisterModel(filename); }
|
||||
|
||||
IImage *CreateImage(Bitmap *bmp)
|
||||
{ return base->CreateImage(bmp); }
|
||||
IModel *CreateModel(VoxelModel *m)
|
||||
{ return base->CreateModel(m); }
|
||||
|
||||
void SetGameMap(GameMap *)
|
||||
{ OnProhibitedAction(); }
|
||||
|
||||
void SetFogDistance(float)
|
||||
{ OnProhibitedAction(); }
|
||||
void SetFogColor(Vector3)
|
||||
{ OnProhibitedAction(); }
|
||||
|
||||
void StartScene(const SceneDefinition&)
|
||||
{ OnProhibitedAction(); }
|
||||
|
||||
void AddLight(const client::DynamicLightParam& light) {
|
||||
Vector3 rad(light.radius, light.radius, light.radius);
|
||||
if (CheckVisibility(AABB3(light.origin - rad, light.origin + rad))) {
|
||||
base->AddLight(light);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderModel(IModel *model, const ModelRenderParam& p) {
|
||||
if (!model) {
|
||||
SPInvalidArgument("model");
|
||||
return;
|
||||
}
|
||||
if (p.depthHack && !allowDepthHack) {
|
||||
OnProhibitedAction();
|
||||
return;
|
||||
}
|
||||
auto bounds = (p.matrix * OBB3(model->GetBoundingBox())).GetBoundingAABB();
|
||||
if (CheckVisibility(bounds)) {
|
||||
base->RenderModel(model, p);
|
||||
}
|
||||
}
|
||||
void AddDebugLine(Vector3 a, Vector3 b, Vector4 color) {
|
||||
OnProhibitedAction();
|
||||
}
|
||||
|
||||
void AddSprite(IImage *image, Vector3 center, float radius, float rotation) {
|
||||
Vector3 rad(radius * 1.5f, radius * 1.5f, radius * 1.5f);
|
||||
if (CheckVisibility(AABB3(center - rad, center + rad))) {
|
||||
base->AddSprite(image, center, radius, rotation);
|
||||
}
|
||||
}
|
||||
void AddLongSprite(IImage *image, Vector3 p1, Vector3 p2, float radius)
|
||||
{
|
||||
Vector3 rad(radius * 1.5f, radius * 1.5f, radius * 1.5f);
|
||||
AABB3 bounds1(p1 - rad, p1 + rad);
|
||||
AABB3 bounds2(p2 - rad, p2 + rad);
|
||||
bounds1 += bounds2;
|
||||
if (CheckVisibility(bounds1)) {
|
||||
base->AddLongSprite(image, p1, p2, radius);
|
||||
}
|
||||
}
|
||||
|
||||
void EndScene() { OnProhibitedAction(); }
|
||||
|
||||
void MultiplyScreenColor(Vector3) { OnProhibitedAction(); }
|
||||
|
||||
/** Sets color for image drawing. Deprecated because
|
||||
* some methods treats this as an alpha premultiplied, while
|
||||
* others treats this as an alpha non-premultiplied.
|
||||
* @deprecated */
|
||||
void SetColor(Vector4 col) {
|
||||
base->SetColor(col);
|
||||
}
|
||||
|
||||
/** Sets color for image drawing. Always alpha premultiplied. */
|
||||
void SetColorAlphaPremultiplied(Vector4 col) {
|
||||
base->SetColorAlphaPremultiplied(col);
|
||||
}
|
||||
|
||||
void DrawImage(IImage *, const Vector2& outTopLeft)
|
||||
{ OnProhibitedAction(); }
|
||||
void DrawImage(IImage *, const AABB2& outRect)
|
||||
{ OnProhibitedAction(); }
|
||||
void DrawImage(IImage *, const Vector2& outTopLeft, const AABB2& inRect)
|
||||
{ OnProhibitedAction(); }
|
||||
void DrawImage(IImage *, const AABB2& outRect, const AABB2& inRect)
|
||||
{ OnProhibitedAction(); }
|
||||
void DrawImage(IImage *, const Vector2& outTopLeft, const Vector2& outTopRight, const Vector2& outBottomLeft, const AABB2& inRect)
|
||||
{ OnProhibitedAction(); }
|
||||
|
||||
void DrawFlatGameMap(const AABB2& outRect, const AABB2& inRect)
|
||||
{ OnProhibitedAction(); }
|
||||
|
||||
void FrameDone()
|
||||
{ OnProhibitedAction(); }
|
||||
|
||||
void Flip()
|
||||
{ OnProhibitedAction(); }
|
||||
|
||||
Bitmap *ReadBitmap()
|
||||
{ OnProhibitedAction(); return nullptr; }
|
||||
|
||||
float ScreenWidth() { return base->ScreenWidth(); }
|
||||
float ScreenHeight() { return base->ScreenHeight(); }
|
||||
};
|
||||
|
||||
ClientPlayer::ClientPlayer(Player *p,
|
||||
Client *c):
|
||||
player(p), client(c){
|
||||
@ -65,6 +205,9 @@ namespace spades {
|
||||
IRenderer *renderer = client->GetRenderer();
|
||||
IAudioDevice *audio = client->GetAudioDevice();
|
||||
|
||||
sandboxedRenderer.Set(new SandboxedRenderer(renderer), false);
|
||||
renderer = sandboxedRenderer;
|
||||
|
||||
static ScriptFunction spadeFactory("ISpadeSkin@ CreateThirdPersonSpadeSkin(Renderer@, AudioDevice@)");
|
||||
spadeSkin = initScriptFactory( spadeFactory, renderer, audio );
|
||||
|
||||
@ -407,6 +550,10 @@ namespace spades {
|
||||
World *world = client->GetWorld();
|
||||
Matrix4 eyeMatrix = GetEyeMatrix();
|
||||
|
||||
sandboxedRenderer->SetClipBox(AABB3(eyeMatrix.GetOrigin() - Vector3(20.f, 20.f, 20.f),
|
||||
eyeMatrix.GetOrigin() + Vector3(20.f, 20.f, 20.f)));
|
||||
sandboxedRenderer->SetAllowDepthHack(true);
|
||||
|
||||
if(client->flashlightOn){
|
||||
float brightness;
|
||||
brightness = client->time - client->flashlightOnTime;
|
||||
@ -597,6 +744,11 @@ namespace spades {
|
||||
return;
|
||||
}
|
||||
|
||||
auto origin = p->GetOrigin();
|
||||
sandboxedRenderer->SetClipBox(AABB3(origin - Vector3(2.f, 2.f, 4.f),
|
||||
origin + Vector3(2.f, 2.f, 2.f)));
|
||||
sandboxedRenderer->SetAllowDepthHack(false);
|
||||
|
||||
// ready for tool rendering
|
||||
asIScriptObject *skin;
|
||||
|
||||
|
@ -35,6 +35,8 @@ namespace spades {
|
||||
class IRenderer;
|
||||
class IAudioDevice;
|
||||
|
||||
class SandboxedRenderer;
|
||||
|
||||
/** Representation of player which is used by
|
||||
* drawing/view layer of game client. */
|
||||
class ClientPlayer: public RefCountedObject {
|
||||
@ -60,6 +62,8 @@ namespace spades {
|
||||
asIScriptObject *weaponViewSkin;
|
||||
asIScriptObject *grenadeViewSkin;
|
||||
|
||||
Handle<SandboxedRenderer> sandboxedRenderer;
|
||||
|
||||
Matrix4 GetEyeMatrix();
|
||||
void AddToSceneThirdPersonView();
|
||||
void AddToSceneFirstPersonView();
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "NetClient.h"
|
||||
|
||||
SPADES_SETTING(cg_fov, "68");
|
||||
SPADES_SETTING(cg_thirdperson, "0");
|
||||
|
||||
static float nextRandom() {
|
||||
return (float)rand() / (float)RAND_MAX;
|
||||
@ -58,6 +59,9 @@ namespace spades {
|
||||
if(!world->GetLocalPlayer()->IsAlive())
|
||||
return true;
|
||||
}
|
||||
if ((int)cg_thirdperson != 0 && world->GetNumPlayers() <= 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/RefCountedObject.h>
|
||||
#include <Core/Math.h>
|
||||
|
||||
namespace spades {
|
||||
namespace client {
|
||||
@ -29,6 +30,8 @@ namespace spades {
|
||||
virtual ~IModel(){}
|
||||
public:
|
||||
IModel(){}
|
||||
|
||||
virtual AABB3 GetBoundingBox() = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,14 @@ namespace spades {
|
||||
}
|
||||
}
|
||||
|
||||
size_t World::GetNumPlayers() {
|
||||
size_t numPlayers = 0;
|
||||
for (auto *p: players) {
|
||||
if (p) ++numPlayers;
|
||||
}
|
||||
return numPlayers;
|
||||
}
|
||||
|
||||
void World::Advance(float dt) {
|
||||
SPADES_MARK_FUNCTION();
|
||||
|
||||
|
@ -132,6 +132,8 @@ namespace spades {
|
||||
return players.size();
|
||||
}
|
||||
|
||||
size_t GetNumPlayers();
|
||||
|
||||
int GetLocalPlayerIndex() {
|
||||
return localPlayerIndex;
|
||||
}
|
||||
|
@ -716,13 +716,13 @@ namespace spades {
|
||||
max.x > o.min.x &&
|
||||
max.y > o.min.y;
|
||||
}
|
||||
|
||||
bool Contains(const Vector2& v) const {
|
||||
return *this && v;
|
||||
}
|
||||
bool Intersects(const AABB2& v) const {
|
||||
return *this && v;
|
||||
}
|
||||
|
||||
bool Contains(const Vector2& v) const {
|
||||
return *this && v;
|
||||
}
|
||||
bool Intersects(const AABB2& v) const {
|
||||
return *this && v;
|
||||
}
|
||||
|
||||
void operator += (const Vector2& vec) {
|
||||
if(vec.x < min.x) min.x = vec.x;
|
||||
@ -792,6 +792,10 @@ namespace spades {
|
||||
bool Intersects(const AABB3& v) const {
|
||||
return *this && v;
|
||||
}
|
||||
bool Contains(const AABB3& v) const {
|
||||
return v.min.x >= min.x && v.min.y >= min.y && v.min.z >= min.z &&
|
||||
v.max.x <= max.x && v.max.y <= max.y && v.max.z <= max.z;
|
||||
}
|
||||
|
||||
void operator += (const Vector3& vec) {
|
||||
if(vec.x < min.x) min.x = vec.x;
|
||||
|
@ -46,7 +46,6 @@ namespace spades {
|
||||
/** Adds dynamic light */
|
||||
virtual void RenderDynamicLightPass(std::vector<client::ModelRenderParam> params, std::vector<GLDynamicLight> lights) = 0;
|
||||
|
||||
virtual AABB3 GetBoundingBox() = 0;
|
||||
private:
|
||||
// members used when rendering by GLModelRenderer
|
||||
int renderId;
|
||||
|
@ -91,6 +91,28 @@ namespace spades {
|
||||
SWModel::~SWModel() {
|
||||
}
|
||||
|
||||
AABB3 SWModel::GetBoundingBox()
|
||||
{
|
||||
VoxelModel *m = rawModel;
|
||||
Vector3 minPos = {0, 0, 0};
|
||||
Vector3 maxPos = {
|
||||
(float)m->GetWidth(), (float)m->GetHeight(), (float)m->GetDepth()
|
||||
};
|
||||
auto origin = rawModel->GetOrigin() - .5f;
|
||||
minPos += origin; maxPos += origin;
|
||||
Vector3 maxDiff = {
|
||||
std::max(fabsf(minPos.x), fabsf(maxPos.x)),
|
||||
std::max(fabsf(minPos.y), fabsf(maxPos.y)),
|
||||
std::max(fabsf(minPos.z), fabsf(maxPos.z))
|
||||
};
|
||||
radius = maxDiff.GetLength();
|
||||
|
||||
AABB3 boundingBox;
|
||||
boundingBox.min = minPos;
|
||||
boundingBox.max = maxPos;
|
||||
return boundingBox;
|
||||
}
|
||||
|
||||
SWModelManager::~SWModelManager() {
|
||||
for(auto it = models.begin(); it != models.end(); it++)
|
||||
it->second->Release();
|
||||
|
@ -47,6 +47,8 @@ namespace spades {
|
||||
float GetRadius() { return radius; }
|
||||
Vector3 GetCenter() { return center; }
|
||||
VoxelModel *GetRawModel() { return rawModel; }
|
||||
|
||||
AABB3 GetBoundingBox();
|
||||
};
|
||||
|
||||
class SWModelManager {
|
||||
|
Loading…
x
Reference in New Issue
Block a user