Support for third person view and so on.

This commit is contained in:
yvt 2015-01-23 18:26:00 +09:00
parent df40c16c5a
commit 66627a4de2
11 changed files with 212 additions and 9 deletions

View File

@ -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...");

View File

@ -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;

View File

@ -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();

View File

@ -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;
}

View File

@ -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;
};
}
}

View File

@ -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();

View File

@ -132,6 +132,8 @@ namespace spades {
return players.size();
}
size_t GetNumPlayers();
int GetLocalPlayerIndex() {
return localPlayerIndex;
}

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -47,6 +47,8 @@ namespace spades {
float GetRadius() { return radius; }
Vector3 GetCenter() { return center; }
VoxelModel *GetRawModel() { return rawModel; }
AABB3 GetBoundingBox();
};
class SWModelManager {