Run clang-format over the entire code base.
Fix hidden header-inclusion-order dependency errors. Update .clang-format for v7.0.1.master
parent
6b1224ab07
commit
5cdaefad6a
|
@ -91,7 +91,7 @@ NamespaceIndentation: All
|
|||
#PenaltyBreakString: 1000
|
||||
#PenaltyExcessCharacter: 1000000
|
||||
#PenaltyReturnTypeOnItsOwnLine: 60
|
||||
#PointerAlignment: Right
|
||||
PointerAlignment: Right
|
||||
#RawStringFormats:
|
||||
# - Delimiter: pb
|
||||
# Language: TextProto
|
||||
|
|
28
src/Aabb.h
28
src/Aabb.h
|
@ -9,21 +9,23 @@
|
|||
struct Aabb {
|
||||
vector3d min, max;
|
||||
double radius;
|
||||
Aabb()
|
||||
: min(DBL_MAX, DBL_MAX, DBL_MAX)
|
||||
, max(-DBL_MAX, -DBL_MAX, -DBL_MAX)
|
||||
, radius(0.1)
|
||||
{ }
|
||||
void Update(const vector3d &p) {
|
||||
Aabb() :
|
||||
min(DBL_MAX, DBL_MAX, DBL_MAX),
|
||||
max(-DBL_MAX, -DBL_MAX, -DBL_MAX),
|
||||
radius(0.1)
|
||||
{}
|
||||
void Update(const vector3d &p)
|
||||
{
|
||||
if (max.x < p.x) max.x = p.x;
|
||||
if (max.y < p.y) max.y = p.y;
|
||||
if (max.z < p.z) max.z = p.z;
|
||||
if (min.x > p.x) min.x = p.x;
|
||||
if (min.y > p.y) min.y = p.y;
|
||||
if (min.z > p.z) min.z = p.z;
|
||||
if (p.Dot(p) > radius*radius) radius = p.Length();
|
||||
if (p.Dot(p) > radius * radius) radius = p.Length();
|
||||
}
|
||||
void Update(float x, float y, float z) {
|
||||
void Update(float x, float y, float z)
|
||||
{
|
||||
if (max.x < x) max.x = x;
|
||||
if (max.y < y) max.y = y;
|
||||
if (max.z < z) max.z = z;
|
||||
|
@ -32,12 +34,14 @@ struct Aabb {
|
|||
if (min.z > z) min.z = z;
|
||||
}
|
||||
template <typename T>
|
||||
bool IsIn (const vector3<T> &p) const {
|
||||
bool IsIn(const vector3<T> &p) const
|
||||
{
|
||||
return ((p.x >= min.x) && (p.x <= max.x) &&
|
||||
(p.y >= min.y) && (p.y <= max.y) &&
|
||||
(p.z >= min.z) && (p.z <= max.z));
|
||||
(p.y >= min.y) && (p.y <= max.y) &&
|
||||
(p.z >= min.z) && (p.z <= max.z));
|
||||
}
|
||||
bool Intersects(const Aabb &o) const {
|
||||
bool Intersects(const Aabb &o) const
|
||||
{
|
||||
return (min.x < o.max.x) && (max.x > o.min.x) &&
|
||||
(min.y < o.max.y) && (max.y > o.min.y) &&
|
||||
(min.z < o.max.z) && (max.z > o.min.z);
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "Pi.h"
|
||||
#include "WorldView.h"
|
||||
#include "Player.h"
|
||||
#include "AmbientSounds.h"
|
||||
#include "Frame.h"
|
||||
#include "Game.h"
|
||||
#include "Pi.h"
|
||||
#include "Planet.h"
|
||||
#include "Player.h"
|
||||
#include "Sound.h"
|
||||
#include "SpaceStation.h"
|
||||
#include "Game.h"
|
||||
#include "WorldView.h"
|
||||
#include "libs.h"
|
||||
|
||||
enum EAtmosphereNoiseChannels {
|
||||
eAtmoNoise1=0,
|
||||
eAtmoNoise1 = 0,
|
||||
eAtmoNoise2,
|
||||
eAtmoNoise3,
|
||||
eAtmoNoise4,
|
||||
eMaxNumAtmosphereSounds
|
||||
};
|
||||
|
||||
static const char* s_airflowTable[eMaxNumAtmosphereSounds] = {
|
||||
static const char *s_airflowTable[eMaxNumAtmosphereSounds] = {
|
||||
"airflow01",
|
||||
"airflow02",
|
||||
"airflow03",
|
||||
|
@ -29,10 +29,10 @@ static const char* s_airflowTable[eMaxNumAtmosphereSounds] = {
|
|||
|
||||
// start, inverse range
|
||||
static const float s_rangeTable[eMaxNumAtmosphereSounds][2] = {
|
||||
{0.0f, 1.0f / (1.0f - 0.0f)}, // 1
|
||||
{1.0f, 1.0f / (3.0f - 1.0f)}, // 2
|
||||
{2.0f, 1.0f / (7.0f - 3.0f)}, // 4
|
||||
{4.0f, 1.0f / (15.0f - 7.0f)} // 8
|
||||
{ 0.0f, 1.0f / (1.0f - 0.0f) }, // 1
|
||||
{ 1.0f, 1.0f / (3.0f - 1.0f) }, // 2
|
||||
{ 2.0f, 1.0f / (7.0f - 3.0f) }, // 4
|
||||
{ 4.0f, 1.0f / (15.0f - 7.0f) } // 8
|
||||
};
|
||||
|
||||
static const Uint32 NUM_SURFACE_LIFE_SOUNDS = 12;
|
||||
|
@ -79,22 +79,22 @@ void AmbientSounds::Update()
|
|||
|
||||
if (Pi::player->GetFlightState() == Ship::DOCKED) {
|
||||
if (s_starNoise.IsPlaying()) {
|
||||
const float target[2] = {0.0f,0.0f};
|
||||
const float dv_dt[2] = {1.0f,1.0f};
|
||||
const float target[2] = { 0.0f, 0.0f };
|
||||
const float dv_dt[2] = { 1.0f, 1.0f };
|
||||
s_starNoise.VolumeAnimate(target, dv_dt);
|
||||
s_starNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
|
||||
}
|
||||
for(int i=0; i<eMaxNumAtmosphereSounds; i++) {
|
||||
for (int i = 0; i < eMaxNumAtmosphereSounds; i++) {
|
||||
if (s_atmosphereNoises[i].IsPlaying()) {
|
||||
const float target[2] = {0.0f,0.0f};
|
||||
const float dv_dt[2] = {1.0f,1.0f};
|
||||
const float target[2] = { 0.0f, 0.0f };
|
||||
const float dv_dt[2] = { 1.0f, 1.0f };
|
||||
s_atmosphereNoises[i].VolumeAnimate(target, dv_dt);
|
||||
s_atmosphereNoises[i].SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
|
||||
}
|
||||
}
|
||||
if (s_planetSurfaceNoise.IsPlaying()) {
|
||||
const float target[2] = {0.0f,0.0f};
|
||||
const float dv_dt[2] = {1.0f,1.0f};
|
||||
const float target[2] = { 0.0f, 0.0f };
|
||||
const float dv_dt[2] = { 1.0f, 1.0f };
|
||||
s_planetSurfaceNoise.VolumeAnimate(target, dv_dt);
|
||||
s_planetSurfaceNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
|
||||
}
|
||||
|
@ -103,27 +103,27 @@ void AmbientSounds::Update()
|
|||
// just use a random station noise until we have a
|
||||
// concept of 'station size'
|
||||
s_stationNoise.Play(s_stationNoiseSounds[Pi::player->GetDockedWith()->GetSystemBody()->GetSeed() % NUM_STATION_SOUNDS],
|
||||
0.3f*v_env, 0.3f*v_env, Sound::OP_REPEAT);
|
||||
0.3f * v_env, 0.3f * v_env, Sound::OP_REPEAT);
|
||||
}
|
||||
} else if (Pi::player->GetFlightState() == Ship::LANDED) {
|
||||
/* Planet surface noise on rough-landing */
|
||||
if (s_starNoise.IsPlaying()) {
|
||||
const float target[2] = {0.0f,0.0f};
|
||||
const float dv_dt[2] = {1.0f,1.0f};
|
||||
const float target[2] = { 0.0f, 0.0f };
|
||||
const float dv_dt[2] = { 1.0f, 1.0f };
|
||||
s_starNoise.VolumeAnimate(target, dv_dt);
|
||||
s_starNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
|
||||
}
|
||||
for(int i=0; i<eMaxNumAtmosphereSounds; i++) {
|
||||
for (int i = 0; i < eMaxNumAtmosphereSounds; i++) {
|
||||
if (s_atmosphereNoises[i].IsPlaying()) {
|
||||
const float target[2] = {0.0f,0.0f};
|
||||
const float dv_dt[2] = {1.0f,1.0f};
|
||||
const float target[2] = { 0.0f, 0.0f };
|
||||
const float dv_dt[2] = { 1.0f, 1.0f };
|
||||
s_atmosphereNoises[i].VolumeAnimate(target, dv_dt);
|
||||
s_atmosphereNoises[i].SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
|
||||
}
|
||||
}
|
||||
if (s_stationNoise.IsPlaying()) {
|
||||
const float target[2] = {0.0f,0.0f};
|
||||
const float dv_dt[2] = {1.0f,1.0f};
|
||||
const float target[2] = { 0.0f, 0.0f };
|
||||
const float dv_dt[2] = { 1.0f, 1.0f };
|
||||
s_stationNoise.VolumeAnimate(target, dv_dt);
|
||||
s_stationNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
|
||||
}
|
||||
|
@ -134,40 +134,38 @@ void AmbientSounds::Update()
|
|||
assert(sbody);
|
||||
const char *sample = 0;
|
||||
|
||||
if (sbody->GetLifeAsFixed() > fixed(1,5)) {
|
||||
if (sbody->GetLifeAsFixed() > fixed(1, 5)) {
|
||||
sample = s_surfaceLifeSounds[sbody->GetSeed() % NUM_SURFACE_LIFE_SOUNDS];
|
||||
}
|
||||
else if (sbody->GetVolatileGasAsFixed() > fixed(1,2)) {
|
||||
} else if (sbody->GetVolatileGasAsFixed() > fixed(1, 2)) {
|
||||
sample = s_surfaceSounds[sbody->GetSeed() % NUM_SURFACE_DEAD_SOUNDS];
|
||||
}
|
||||
else if (sbody->GetVolatileGasAsFixed() > fixed(1,10)) {
|
||||
} else if (sbody->GetVolatileGasAsFixed() > fixed(1, 10)) {
|
||||
sample = "Wind";
|
||||
}
|
||||
|
||||
if (sample) {
|
||||
s_planetSurfaceNoise.Play(sample, 0.3f*v_env, 0.3f*v_env, Sound::OP_REPEAT);
|
||||
s_planetSurfaceNoise.Play(sample, 0.3f * v_env, 0.3f * v_env, Sound::OP_REPEAT);
|
||||
}
|
||||
}
|
||||
} else if (s_planetSurfaceNoise.IsPlaying()) {
|
||||
// s_planetSurfaceNoise.IsPlaying() - if we are out of the atmosphere then stop playing
|
||||
if (Pi::player->GetFrame()->IsRotFrame()) {
|
||||
const Body *astro = Pi::player->GetFrame()->GetBody();
|
||||
if (astro->IsType(Object::PLANET)) {
|
||||
const double dist = Pi::player->GetPosition().Length();
|
||||
double pressure, density;
|
||||
static_cast<const Planet*>(astro)->GetAtmosphericState(dist, &pressure, &density);
|
||||
if (pressure < 0.001) {
|
||||
// Stop playing surface noise once out of the atmosphere
|
||||
s_planetSurfaceNoise.Stop();
|
||||
}
|
||||
}
|
||||
} else if (s_planetSurfaceNoise.IsPlaying()) {
|
||||
// s_planetSurfaceNoise.IsPlaying() - if we are out of the atmosphere then stop playing
|
||||
if (Pi::player->GetFrame()->IsRotFrame()) {
|
||||
const Body *astro = Pi::player->GetFrame()->GetBody();
|
||||
if (astro->IsType(Object::PLANET)) {
|
||||
const double dist = Pi::player->GetPosition().Length();
|
||||
double pressure, density;
|
||||
static_cast<const Planet *>(astro)->GetAtmosphericState(dist, &pressure, &density);
|
||||
if (pressure < 0.001) {
|
||||
// Stop playing surface noise once out of the atmosphere
|
||||
s_planetSurfaceNoise.Stop();
|
||||
}
|
||||
}
|
||||
} else if (Pi::game->IsHyperspace()) {
|
||||
s_planetSurfaceNoise.Stop();
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
if (s_stationNoise.IsPlaying()) {
|
||||
const float target[2] = {0.0f,0.0f};
|
||||
const float dv_dt[2] = {1.0f,1.0f};
|
||||
const float target[2] = { 0.0f, 0.0f };
|
||||
const float dv_dt[2] = { 1.0f, 1.0f };
|
||||
s_stationNoise.VolumeAnimate(target, dv_dt);
|
||||
s_stationNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
|
||||
}
|
||||
|
@ -176,8 +174,8 @@ void AmbientSounds::Update()
|
|||
if (astroNoiseSeed != s->GetSeed()) {
|
||||
// change sound!
|
||||
astroNoiseSeed = s->GetSeed();
|
||||
const float target[2] = {0.0f,0.0f};
|
||||
const float dv_dt[2] = {0.1f,0.1f};
|
||||
const float target[2] = { 0.0f, 0.0f };
|
||||
const float dv_dt[2] = { 0.1f, 0.1f };
|
||||
s_starNoise.VolumeAnimate(target, dv_dt);
|
||||
s_starNoise.SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
|
||||
// XXX the way Sound::Event works isn't totally obvious.
|
||||
|
@ -194,32 +192,31 @@ void AmbientSounds::Update()
|
|||
const char *sample = 0;
|
||||
for (; sbody && !sample; sbody = f->GetSystemBody()) {
|
||||
switch (sbody->GetType()) {
|
||||
case SystemBody::TYPE_BROWN_DWARF: sample = "Brown_Dwarf_Substellar_Object"; break;
|
||||
case SystemBody::TYPE_STAR_M: sample = "M_Red_Star"; break;
|
||||
case SystemBody::TYPE_STAR_K: sample = "K_Star"; break;
|
||||
case SystemBody::TYPE_WHITE_DWARF: sample = "White_Dwarf_Star"; break;
|
||||
case SystemBody::TYPE_STAR_G: sample = "G_Star"; break;
|
||||
case SystemBody::TYPE_STAR_F: sample = "F_Star"; break;
|
||||
case SystemBody::TYPE_STAR_A: sample = "A_Star"; break;
|
||||
case SystemBody::TYPE_STAR_B: sample = "B_Hot_Blue_STAR"; break;
|
||||
case SystemBody::TYPE_STAR_O: sample = "Blue_Super_Giant"; break;
|
||||
case SystemBody::TYPE_PLANET_GAS_GIANT: {
|
||||
if (sbody->GetMassAsFixed() > fixed(400,1)) {
|
||||
sample = "Very_Large_Gas_Giant";
|
||||
} else if (sbody->GetMassAsFixed() > fixed(80,1)) {
|
||||
sample = "Large_Gas_Giant";
|
||||
} else if (sbody->GetMassAsFixed() > fixed(20,1)) {
|
||||
sample = "Medium_Gas_Giant";
|
||||
} else {
|
||||
sample = "Small_Gas_Giant";
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: sample = 0; break;
|
||||
case SystemBody::TYPE_BROWN_DWARF: sample = "Brown_Dwarf_Substellar_Object"; break;
|
||||
case SystemBody::TYPE_STAR_M: sample = "M_Red_Star"; break;
|
||||
case SystemBody::TYPE_STAR_K: sample = "K_Star"; break;
|
||||
case SystemBody::TYPE_WHITE_DWARF: sample = "White_Dwarf_Star"; break;
|
||||
case SystemBody::TYPE_STAR_G: sample = "G_Star"; break;
|
||||
case SystemBody::TYPE_STAR_F: sample = "F_Star"; break;
|
||||
case SystemBody::TYPE_STAR_A: sample = "A_Star"; break;
|
||||
case SystemBody::TYPE_STAR_B: sample = "B_Hot_Blue_STAR"; break;
|
||||
case SystemBody::TYPE_STAR_O: sample = "Blue_Super_Giant"; break;
|
||||
case SystemBody::TYPE_PLANET_GAS_GIANT: {
|
||||
if (sbody->GetMassAsFixed() > fixed(400, 1)) {
|
||||
sample = "Very_Large_Gas_Giant";
|
||||
} else if (sbody->GetMassAsFixed() > fixed(80, 1)) {
|
||||
sample = "Large_Gas_Giant";
|
||||
} else if (sbody->GetMassAsFixed() > fixed(20, 1)) {
|
||||
sample = "Medium_Gas_Giant";
|
||||
} else {
|
||||
sample = "Small_Gas_Giant";
|
||||
}
|
||||
} break;
|
||||
default: sample = 0; break;
|
||||
}
|
||||
if (sample) {
|
||||
s_starNoise.Play(sample, 0.0f, 0.0f, Sound::OP_REPEAT);
|
||||
s_starNoise.VolumeAnimate(.3f*v_env, .3f*v_env, .05f, .05f);
|
||||
s_starNoise.VolumeAnimate(.3f * v_env, .3f * v_env, .05f, .05f);
|
||||
} else {
|
||||
// go up orbital hierarchy tree to see if we can find a sound
|
||||
f = f->GetParent();
|
||||
|
@ -232,31 +229,31 @@ void AmbientSounds::Update()
|
|||
if (astro && Pi::player->GetFrame()->IsRotFrame() && (astro->IsType(Object::PLANET))) {
|
||||
double dist = Pi::player->GetPosition().Length();
|
||||
double pressure, density;
|
||||
static_cast<const Planet*>(astro)->GetAtmosphericState(dist, &pressure, &density);
|
||||
static_cast<const Planet *>(astro)->GetAtmosphericState(dist, &pressure, &density);
|
||||
// maximum volume at around 2km/sec at earth density, pressure
|
||||
const float pressureVolume = float(density * Pi::player->GetVelocity().Length() * 0.0005);
|
||||
//volume = Clamp(volume, 0.0f, 1.0f) * v_env;
|
||||
float volumes[eMaxNumAtmosphereSounds];
|
||||
for(int i=0; i<eMaxNumAtmosphereSounds; i++) {
|
||||
for (int i = 0; i < eMaxNumAtmosphereSounds; i++) {
|
||||
const float beg = s_rangeTable[i][0];
|
||||
const float inv = s_rangeTable[i][1];
|
||||
volumes[i] = Clamp((pressureVolume - beg) * inv, 0.0f, 1.0f) * v_env;
|
||||
}
|
||||
|
||||
for(int i=0; i<eMaxNumAtmosphereSounds; i++) {
|
||||
for (int i = 0; i < eMaxNumAtmosphereSounds; i++) {
|
||||
const float volume = volumes[i];
|
||||
if (s_atmosphereNoises[i].IsPlaying()) {
|
||||
const float target[2] = {volume, volume};
|
||||
const float dv_dt[2] = {1.0f,1.0f};
|
||||
const float target[2] = { volume, volume };
|
||||
const float dv_dt[2] = { 1.0f, 1.0f };
|
||||
s_atmosphereNoises[i].VolumeAnimate(target, dv_dt);
|
||||
} else {
|
||||
s_atmosphereNoises[i].Play(s_airflowTable[i], volume, volume, Sound::OP_REPEAT);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const float target[2] = {0.0f,0.0f};
|
||||
const float dv_dt[2] = {1.0f,1.0f};
|
||||
for(int i=0; i<eMaxNumAtmosphereSounds; i++) {
|
||||
const float target[2] = { 0.0f, 0.0f };
|
||||
const float dv_dt[2] = { 1.0f, 1.0f };
|
||||
for (int i = 0; i < eMaxNumAtmosphereSounds; i++) {
|
||||
s_atmosphereNoises[i].VolumeAnimate(target, dv_dt);
|
||||
s_atmosphereNoises[i].SetOp(Sound::OP_REPEAT | Sound::OP_STOP_AT_TARGET_VOLUME);
|
||||
}
|
||||
|
@ -270,9 +267,9 @@ void AmbientSounds::UpdateForCamType()
|
|||
float v_env = (cam == WorldView::CAM_EXTERNAL ? 1.0f : 0.5f) * Sound::GetSfxVolume();
|
||||
|
||||
if (s_stationNoise.IsPlaying())
|
||||
s_stationNoise.SetVolume(0.3f*v_env, 0.3f*v_env);
|
||||
s_stationNoise.SetVolume(0.3f * v_env, 0.3f * v_env);
|
||||
if (s_starNoise.IsPlaying())
|
||||
s_starNoise.SetVolume(0.3f*v_env, 0.3f*v_env);
|
||||
s_starNoise.SetVolume(0.3f * v_env, 0.3f * v_env);
|
||||
if (s_planetSurfaceNoise.IsPlaying())
|
||||
s_planetSurfaceNoise.SetVolume(0.3f*v_env, 0.3f*v_env);
|
||||
s_planetSurfaceNoise.SetVolume(0.3f * v_env, 0.3f * v_env);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ public:
|
|||
static void Init();
|
||||
static void Uninit();
|
||||
static void Update();
|
||||
|
||||
private:
|
||||
static void UpdateForCamType();
|
||||
};
|
||||
|
|
|
@ -10,21 +10,22 @@ namespace AnimationCurves {
|
|||
|
||||
// Animates a value with "approach style" over time (zooming).
|
||||
// The speeds must be positive. Function will not go further than target.
|
||||
template<class T>
|
||||
inline void Approach(T & cur, const T target, float frameTime, const T exponentialFactor=10, T linearFactor=1) {
|
||||
template <class T>
|
||||
inline void Approach(T &cur, const T target, float frameTime, const T exponentialFactor = 10, T linearFactor = 1)
|
||||
{
|
||||
//static_assert(static_cast<T>(-1) <0); // Assert type is signed
|
||||
if (frameTime>1) frameTime = 1; // Clamp in case game hangs for a second
|
||||
if (frameTime > 1) frameTime = 1; // Clamp in case game hangs for a second
|
||||
assert(exponentialFactor >= 0 && linearFactor >= 0);
|
||||
if (is_equal_exact(target, cur))
|
||||
return;
|
||||
const T delta(target - cur);
|
||||
if (delta < 0) linearFactor = -linearFactor;
|
||||
cur += (delta*exponentialFactor + linearFactor) * frameTime;
|
||||
cur += (delta * exponentialFactor + linearFactor) * frameTime;
|
||||
// clamp to target (independent of the direction of motion)
|
||||
const T newDelta(target - cur);
|
||||
if (newDelta*delta < 0) cur = target;
|
||||
if (newDelta * delta < 0) cur = target;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace AnimationCurves
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,29 +2,28 @@
|
|||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "Background.h"
|
||||
#include "Frame.h"
|
||||
#include "FileSystem.h"
|
||||
#include "Frame.h"
|
||||
#include "Game.h"
|
||||
#include "perlin.h"
|
||||
#include "Pi.h"
|
||||
#include "Player.h"
|
||||
#include "Space.h"
|
||||
#include "StringF.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "graphics/TextureBuilder.h"
|
||||
#include "StringF.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "perlin.h"
|
||||
|
||||
#include <SDL_stdinc.h>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace Graphics;
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
static const Uint32 BG_STAR_MAX = 500000;
|
||||
static const Uint32 BG_STAR_MIN = 50000;
|
||||
static RefCountedPtr<Graphics::Texture> s_defaultCubeMap;
|
||||
|
@ -39,487 +38,478 @@ namespace
|
|||
const char *itemMask = "ub";
|
||||
|
||||
Uint32 num_matching = 0;
|
||||
for (std::vector<FileSystem::FileInfo>::const_iterator it = fileList.begin(), itEnd = fileList.end(); it!=itEnd; ++it) {
|
||||
for (std::vector<FileSystem::FileInfo>::const_iterator it = fileList.begin(), itEnd = fileList.end(); it != itEnd; ++it) {
|
||||
if (starts_with((*it).GetName(), itemMask)) {
|
||||
++num_matching;
|
||||
}
|
||||
}
|
||||
return num_matching;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace Background
|
||||
{
|
||||
namespace Background {
|
||||
|
||||
#pragma pack(push, 4)
|
||||
struct MilkyWayVert {
|
||||
vector3f pos;
|
||||
Color4ub col;
|
||||
};
|
||||
struct MilkyWayVert {
|
||||
vector3f pos;
|
||||
Color4ub col;
|
||||
};
|
||||
|
||||
struct StarVert {
|
||||
vector3f pos;
|
||||
Color4ub col;
|
||||
};
|
||||
struct StarVert {
|
||||
vector3f pos;
|
||||
Color4ub col;
|
||||
};
|
||||
|
||||
struct SkyboxVert {
|
||||
vector3f pos;
|
||||
vector2f uv;
|
||||
};
|
||||
struct SkyboxVert {
|
||||
vector3f pos;
|
||||
vector2f uv;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
void BackgroundElement::SetIntensity(float intensity)
|
||||
{
|
||||
m_material->emissive = Color(intensity * 255, intensity * 255, intensity*255);
|
||||
}
|
||||
|
||||
UniverseBox::UniverseBox(Graphics::Renderer *renderer)
|
||||
{
|
||||
m_renderer = renderer;
|
||||
Init();
|
||||
}
|
||||
|
||||
UniverseBox::~UniverseBox()
|
||||
{
|
||||
}
|
||||
|
||||
void UniverseBox::Init()
|
||||
{
|
||||
// Load default cubemap
|
||||
if(!s_defaultCubeMap.Valid()) {
|
||||
TextureBuilder texture_builder = TextureBuilder::Cube("textures/skybox/default.dds");
|
||||
s_defaultCubeMap.Reset( texture_builder.GetOrCreateTexture(m_renderer,std::string("cube")) );
|
||||
}
|
||||
|
||||
// Create skybox geometry
|
||||
std::unique_ptr<Graphics::VertexArray> box(new VertexArray(ATTRIB_POSITION | ATTRIB_UV0, 36));
|
||||
const float vp = 1000.0f;
|
||||
// Top +Y
|
||||
box->Add(vector3f(-vp, vp, vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f( vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f( vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f( vp, vp, -vp), vector2f(1.0f, 1.0f));
|
||||
// Bottom -Y
|
||||
box->Add(vector3f(-vp, -vp, -vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f( vp, -vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f( vp, -vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f( vp, -vp, vp), vector2f(1.0f, 1.0f));
|
||||
// Front -Z
|
||||
box->Add(vector3f(-vp, vp, -vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f( vp, vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f( vp, vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f( vp, -vp, -vp), vector2f(1.0f, 1.0f));
|
||||
// Back +Z
|
||||
box->Add(vector3f( vp, vp, vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f( vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(-vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f( vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(-vp, -vp, vp), vector2f(1.0f, 1.0f));
|
||||
// Right +X
|
||||
box->Add(vector3f( vp, vp, -vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f( vp, -vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f( vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f( vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f( vp, -vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f( vp, -vp, vp), vector2f(1.0f, 1.0f));
|
||||
// Left -X
|
||||
box->Add(vector3f(-vp, vp, vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(-vp, vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(-vp, -vp, -vp), vector2f(1.0f, 1.0f));
|
||||
|
||||
Graphics::MaterialDescriptor desc;
|
||||
desc.effect = EFFECT_SKYBOX;
|
||||
m_material.Reset(m_renderer->CreateMaterial(desc));
|
||||
m_material->texture0 = nullptr;
|
||||
|
||||
//create buffer and upload data
|
||||
Graphics::VertexBufferDesc vbd;
|
||||
vbd.attrib[0].semantic = Graphics::ATTRIB_POSITION;
|
||||
vbd.attrib[0].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[1].semantic = Graphics::ATTRIB_UV0;
|
||||
vbd.attrib[1].format = Graphics::ATTRIB_FORMAT_FLOAT2;
|
||||
vbd.numVertices = box->GetNumVerts();
|
||||
vbd.usage = Graphics::BUFFER_USAGE_STATIC;
|
||||
|
||||
m_vertexBuffer.reset(m_renderer->CreateVertexBuffer(vbd));
|
||||
|
||||
SkyboxVert* vtxPtr = m_vertexBuffer->Map<SkyboxVert>(Graphics::BUFFER_MAP_WRITE);
|
||||
assert(m_vertexBuffer->GetDesc().stride == sizeof(SkyboxVert));
|
||||
for (Uint32 i = 0; i < box->GetNumVerts(); i++) {
|
||||
vtxPtr[i].pos = box->position[i];
|
||||
vtxPtr[i].uv = box->uv0[i];
|
||||
}
|
||||
m_vertexBuffer->Unmap();
|
||||
|
||||
SetIntensity(1.0f);
|
||||
|
||||
m_numCubemaps = GetNumSkyboxes();
|
||||
}
|
||||
|
||||
void UniverseBox::Draw(Graphics::RenderState *rs)
|
||||
{
|
||||
if(m_material->texture0)
|
||||
m_renderer->DrawBuffer(m_vertexBuffer.get(), rs, m_material.Get());
|
||||
}
|
||||
|
||||
void UniverseBox::LoadCubeMap(Random &rand)
|
||||
{
|
||||
if(m_numCubemaps>0) {
|
||||
const int new_ubox_index = rand.Int32(1, m_numCubemaps);
|
||||
if(new_ubox_index > 0) {
|
||||
// Load new one
|
||||
const std::string os = stringf("textures/skybox/ub%0{d}.dds", (new_ubox_index - 1));
|
||||
TextureBuilder texture_builder = TextureBuilder::Cube(os.c_str());
|
||||
m_cubemap.Reset( texture_builder.GetOrCreateTexture(m_renderer, std::string("cube")) );
|
||||
m_material->texture0 = m_cubemap.Get();
|
||||
}
|
||||
} else {
|
||||
// use default cubemap
|
||||
m_cubemap.Reset();
|
||||
m_material->texture0 = s_defaultCubeMap.Get();
|
||||
}
|
||||
}
|
||||
|
||||
Starfield::Starfield(Graphics::Renderer *renderer, Random &rand)
|
||||
{
|
||||
m_renderer = renderer;
|
||||
Init();
|
||||
Fill(rand);
|
||||
}
|
||||
|
||||
void Starfield::Init()
|
||||
{
|
||||
Graphics::MaterialDescriptor desc;
|
||||
desc.effect = Graphics::EFFECT_STARFIELD;
|
||||
desc.textures = 1;
|
||||
desc.vertexColors = true;
|
||||
m_material.Reset(m_renderer->CreateMaterial(desc));
|
||||
m_material->emissive = Color::WHITE;
|
||||
m_material->texture0 = Graphics::TextureBuilder::Billboard("textures/star_point.png").GetOrCreateTexture(m_renderer, "billboard");
|
||||
|
||||
Graphics::MaterialDescriptor descStreaks;
|
||||
descStreaks.effect = Graphics::EFFECT_VTXCOLOR;
|
||||
descStreaks.vertexColors = true;
|
||||
m_materialStreaks.Reset(m_renderer->CreateMaterial(descStreaks));
|
||||
m_materialStreaks->emissive = Color::WHITE;
|
||||
|
||||
IniConfig cfg;
|
||||
cfg.Read(FileSystem::gameDataFiles, "configs/Starfield.ini");
|
||||
// NB: limit the ranges of all values loaded from the file
|
||||
m_rMin = Clamp(cfg.Float("rMin", 0.2), 0.2f, 1.0f);
|
||||
m_rMax = Clamp(cfg.Float("rMax", 0.9), 0.2f, 1.0f);
|
||||
m_gMin = Clamp(cfg.Float("gMin", 0.2), 0.2f, 1.0f);
|
||||
m_gMax = Clamp(cfg.Float("gMax", 0.9), 0.2f, 1.0f);
|
||||
m_bMin = Clamp(cfg.Float("bMin", 0.2), 0.2f, 1.0f);
|
||||
m_bMax = Clamp(cfg.Float("bMax", 0.9), 0.2f, 1.0f);
|
||||
}
|
||||
|
||||
void Starfield::Fill(Random &rand)
|
||||
{
|
||||
const Uint32 NUM_BG_STARS = Clamp(Uint32(Pi::GetAmountBackgroundStars() * BG_STAR_MAX), BG_STAR_MIN, BG_STAR_MAX);
|
||||
m_hyperVtx.reset(new vector3f[BG_STAR_MAX * 3]);
|
||||
m_hyperCol.reset(new Color[BG_STAR_MAX * 3]);
|
||||
|
||||
// setup the animated stars buffer (streaks in Hyperspace)
|
||||
void BackgroundElement::SetIntensity(float intensity)
|
||||
{
|
||||
m_material->emissive = Color(intensity * 255, intensity * 255, intensity * 255);
|
||||
}
|
||||
|
||||
UniverseBox::UniverseBox(Graphics::Renderer *renderer)
|
||||
{
|
||||
m_renderer = renderer;
|
||||
Init();
|
||||
}
|
||||
|
||||
UniverseBox::~UniverseBox()
|
||||
{
|
||||
}
|
||||
|
||||
void UniverseBox::Init()
|
||||
{
|
||||
// Load default cubemap
|
||||
if (!s_defaultCubeMap.Valid()) {
|
||||
TextureBuilder texture_builder = TextureBuilder::Cube("textures/skybox/default.dds");
|
||||
s_defaultCubeMap.Reset(texture_builder.GetOrCreateTexture(m_renderer, std::string("cube")));
|
||||
}
|
||||
|
||||
// Create skybox geometry
|
||||
std::unique_ptr<Graphics::VertexArray> box(new VertexArray(ATTRIB_POSITION | ATTRIB_UV0, 36));
|
||||
const float vp = 1000.0f;
|
||||
// Top +Y
|
||||
box->Add(vector3f(-vp, vp, vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(vp, vp, -vp), vector2f(1.0f, 1.0f));
|
||||
// Bottom -Y
|
||||
box->Add(vector3f(-vp, -vp, -vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(vp, -vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(vp, -vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(vp, -vp, vp), vector2f(1.0f, 1.0f));
|
||||
// Front -Z
|
||||
box->Add(vector3f(-vp, vp, -vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(vp, vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(vp, vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(vp, -vp, -vp), vector2f(1.0f, 1.0f));
|
||||
// Back +Z
|
||||
box->Add(vector3f(vp, vp, vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f(vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(-vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(-vp, -vp, vp), vector2f(1.0f, 1.0f));
|
||||
// Right +X
|
||||
box->Add(vector3f(vp, vp, -vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f(vp, -vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(vp, vp, vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(vp, -vp, -vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(vp, -vp, vp), vector2f(1.0f, 1.0f));
|
||||
// Left -X
|
||||
box->Add(vector3f(-vp, vp, vp), vector2f(0.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(-vp, vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, vp, -vp), vector2f(1.0f, 0.0f));
|
||||
box->Add(vector3f(-vp, -vp, vp), vector2f(0.0f, 1.0f));
|
||||
box->Add(vector3f(-vp, -vp, -vp), vector2f(1.0f, 1.0f));
|
||||
|
||||
Graphics::MaterialDescriptor desc;
|
||||
desc.effect = EFFECT_SKYBOX;
|
||||
m_material.Reset(m_renderer->CreateMaterial(desc));
|
||||
m_material->texture0 = nullptr;
|
||||
|
||||
//create buffer and upload data
|
||||
Graphics::VertexBufferDesc vbd;
|
||||
vbd.attrib[0].semantic = Graphics::ATTRIB_POSITION;
|
||||
vbd.attrib[0].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[1].semantic = Graphics::ATTRIB_UV0;
|
||||
vbd.attrib[1].format = Graphics::ATTRIB_FORMAT_FLOAT2;
|
||||
vbd.numVertices = box->GetNumVerts();
|
||||
vbd.usage = Graphics::BUFFER_USAGE_STATIC;
|
||||
|
||||
m_vertexBuffer.reset(m_renderer->CreateVertexBuffer(vbd));
|
||||
|
||||
SkyboxVert *vtxPtr = m_vertexBuffer->Map<SkyboxVert>(Graphics::BUFFER_MAP_WRITE);
|
||||
assert(m_vertexBuffer->GetDesc().stride == sizeof(SkyboxVert));
|
||||
for (Uint32 i = 0; i < box->GetNumVerts(); i++) {
|
||||
vtxPtr[i].pos = box->position[i];
|
||||
vtxPtr[i].uv = box->uv0[i];
|
||||
}
|
||||
m_vertexBuffer->Unmap();
|
||||
|
||||
SetIntensity(1.0f);
|
||||
|
||||
m_numCubemaps = GetNumSkyboxes();
|
||||
}
|
||||
|
||||
void UniverseBox::Draw(Graphics::RenderState *rs)
|
||||
{
|
||||
if (m_material->texture0)
|
||||
m_renderer->DrawBuffer(m_vertexBuffer.get(), rs, m_material.Get());
|
||||
}
|
||||
|
||||
void UniverseBox::LoadCubeMap(Random &rand)
|
||||
{
|
||||
if (m_numCubemaps > 0) {
|
||||
const int new_ubox_index = rand.Int32(1, m_numCubemaps);
|
||||
if (new_ubox_index > 0) {
|
||||
// Load new one
|
||||
const std::string os = stringf("textures/skybox/ub%0{d}.dds", (new_ubox_index - 1));
|
||||
TextureBuilder texture_builder = TextureBuilder::Cube(os.c_str());
|
||||
m_cubemap.Reset(texture_builder.GetOrCreateTexture(m_renderer, std::string("cube")));
|
||||
m_material->texture0 = m_cubemap.Get();
|
||||
}
|
||||
} else {
|
||||
// use default cubemap
|
||||
m_cubemap.Reset();
|
||||
m_material->texture0 = s_defaultCubeMap.Get();
|
||||
}
|
||||
}
|
||||
|
||||
Starfield::Starfield(Graphics::Renderer *renderer, Random &rand)
|
||||
{
|
||||
m_renderer = renderer;
|
||||
Init();
|
||||
Fill(rand);
|
||||
}
|
||||
|
||||
void Starfield::Init()
|
||||
{
|
||||
Graphics::MaterialDescriptor desc;
|
||||
desc.effect = Graphics::EFFECT_STARFIELD;
|
||||
desc.textures = 1;
|
||||
desc.vertexColors = true;
|
||||
m_material.Reset(m_renderer->CreateMaterial(desc));
|
||||
m_material->emissive = Color::WHITE;
|
||||
m_material->texture0 = Graphics::TextureBuilder::Billboard("textures/star_point.png").GetOrCreateTexture(m_renderer, "billboard");
|
||||
|
||||
Graphics::MaterialDescriptor descStreaks;
|
||||
descStreaks.effect = Graphics::EFFECT_VTXCOLOR;
|
||||
descStreaks.vertexColors = true;
|
||||
m_materialStreaks.Reset(m_renderer->CreateMaterial(descStreaks));
|
||||
m_materialStreaks->emissive = Color::WHITE;
|
||||
|
||||
IniConfig cfg;
|
||||
cfg.Read(FileSystem::gameDataFiles, "configs/Starfield.ini");
|
||||
// NB: limit the ranges of all values loaded from the file
|
||||
m_rMin = Clamp(cfg.Float("rMin", 0.2), 0.2f, 1.0f);
|
||||
m_rMax = Clamp(cfg.Float("rMax", 0.9), 0.2f, 1.0f);
|
||||
m_gMin = Clamp(cfg.Float("gMin", 0.2), 0.2f, 1.0f);
|
||||
m_gMax = Clamp(cfg.Float("gMax", 0.9), 0.2f, 1.0f);
|
||||
m_bMin = Clamp(cfg.Float("bMin", 0.2), 0.2f, 1.0f);
|
||||
m_bMax = Clamp(cfg.Float("bMax", 0.9), 0.2f, 1.0f);
|
||||
}
|
||||
|
||||
void Starfield::Fill(Random &rand)
|
||||
{
|
||||
const Uint32 NUM_BG_STARS = Clamp(Uint32(Pi::GetAmountBackgroundStars() * BG_STAR_MAX), BG_STAR_MIN, BG_STAR_MAX);
|
||||
m_hyperVtx.reset(new vector3f[BG_STAR_MAX * 3]);
|
||||
m_hyperCol.reset(new Color[BG_STAR_MAX * 3]);
|
||||
|
||||
// setup the animated stars buffer (streaks in Hyperspace)
|
||||
{
|
||||
Graphics::VertexBufferDesc vbd;
|
||||
vbd.attrib[0].semantic = Graphics::ATTRIB_POSITION;
|
||||
vbd.attrib[0].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[1].semantic = Graphics::ATTRIB_DIFFUSE;
|
||||
vbd.attrib[1].format = Graphics::ATTRIB_FORMAT_UBYTE4;
|
||||
vbd.usage = Graphics::BUFFER_USAGE_DYNAMIC;
|
||||
vbd.numVertices = NUM_BG_STARS * 2;
|
||||
m_animBuffer.reset(m_renderer->CreateVertexBuffer(vbd));
|
||||
}
|
||||
|
||||
m_pointSprites.reset(new Graphics::Drawables::PointSprites);
|
||||
|
||||
assert(sizeof(StarVert) == 16);
|
||||
std::unique_ptr<vector3f[]> stars(new vector3f[NUM_BG_STARS]);
|
||||
std::unique_ptr<Color[]> colors(new Color[NUM_BG_STARS]);
|
||||
std::unique_ptr<float[]> sizes(new float[NUM_BG_STARS]);
|
||||
//fill the array
|
||||
Uint32 num = 0;
|
||||
if (Pi::game != nullptr && Pi::game->GetSpace() != nullptr && Pi::game->GetSpace()->GetStarSystem() != nullptr) {
|
||||
const SystemPath current = Pi::game->GetSpace()->GetStarSystem()->GetPath();
|
||||
|
||||
const double size = 1.0;
|
||||
const Uint8 colScale = size * 255;
|
||||
const Sint32 visibleRadius = 100; // lyrs
|
||||
const Sint32 visibleRadiusSqr = (visibleRadius * visibleRadius);
|
||||
const Sint32 sectorMin = -(visibleRadius / Sector::SIZE); // lyrs_radius / sector_size_in_lyrs
|
||||
const Sint32 sectorMax = visibleRadius / Sector::SIZE; // lyrs_radius / sector_size_in_lyrs
|
||||
for (Sint32 x = sectorMin; x < sectorMax; x++) {
|
||||
for (Sint32 y = sectorMin; y < sectorMax; y++) {
|
||||
for (Sint32 z = sectorMin; z < sectorMax; z++) {
|
||||
SystemPath sys(x, y, z);
|
||||
if (SystemPath::SectorDistanceSqr(sys, current) * Sector::SIZE >= visibleRadiusSqr)
|
||||
continue; // early out
|
||||
|
||||
// this is fairly expensive
|
||||
RefCountedPtr<const Sector> sec = Pi::game->GetGalaxy()->GetSector(sys);
|
||||
|
||||
// add as many systems as we can
|
||||
const size_t numSystems = std::min(sec->m_systems.size(), (size_t)(NUM_BG_STARS - num));
|
||||
for (size_t systemIndex = 0; systemIndex < numSystems; systemIndex++) {
|
||||
const Sector::System *ss = &(sec->m_systems[systemIndex]);
|
||||
const vector3f distance = Sector::SIZE * vector3f(current.sectorX, current.sectorY, current.sectorZ) - ss->GetFullPosition();
|
||||
if (distance.Length() >= visibleRadius)
|
||||
continue; // too far
|
||||
|
||||
// grab the approximate real colour
|
||||
Color col = StarSystem::starRealColors[ss->GetStarType(0)];
|
||||
col.r = Clamp(col.r, (Uint8)(m_rMin * 255), (Uint8)(m_rMax * 255));
|
||||
col.g = Clamp(col.g, (Uint8)(m_gMin * 255), (Uint8)(m_gMax * 255));
|
||||
col.b = Clamp(col.b, (Uint8)(m_bMin * 255), (Uint8)(m_bMax * 255));
|
||||
//const Color col(Color::PINK); // debug pink
|
||||
|
||||
// copy the data
|
||||
sizes[num] = size;
|
||||
stars[num] = distance.Normalized() * 1000.0f;
|
||||
colors[num] = col;
|
||||
|
||||
//need to keep data around for HS anim - this is stupid
|
||||
m_hyperVtx[NUM_BG_STARS * 2 + num] = stars[num];
|
||||
m_hyperCol[NUM_BG_STARS * 2 + num] = col * 0.8f;
|
||||
num++;
|
||||
}
|
||||
if (num >= NUM_BG_STARS) {
|
||||
x = sectorMax;
|
||||
y = sectorMax;
|
||||
z = sectorMax;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Output("num = %d\n", num);
|
||||
|
||||
// fill out the remaining target count with generated points
|
||||
if (num < NUM_BG_STARS) {
|
||||
for (Uint32 i = num; i < NUM_BG_STARS; i++) {
|
||||
const double size = rand.Double(0.2, 0.9);
|
||||
const Uint8 colScale = size * 255;
|
||||
|
||||
const Color col(
|
||||
rand.Double(m_rMin, m_rMax) * colScale,
|
||||
rand.Double(m_gMin, m_gMax) * colScale,
|
||||
rand.Double(m_bMin, m_bMax) * colScale,
|
||||
255);
|
||||
|
||||
// this is proper random distribution on a sphere's surface
|
||||
const float theta = float(rand.Double(0.0, 2.0 * M_PI));
|
||||
const float u = float(rand.Double(-1.0, 1.0));
|
||||
|
||||
sizes[i] = size;
|
||||
// squeeze the starfield a bit to get more density near horizon using matrix3x3f::Scale
|
||||
stars[i] = matrix3x3f::Scale(1.0, 0.4, 1.0) * (vector3f(sqrt(1.0f - u * u) * cos(theta), u, sqrt(1.0f - u * u) * sin(theta)).Normalized() * 1000.0f);
|
||||
colors[i] = col;
|
||||
|
||||
//need to keep data around for HS anim - this is stupid
|
||||
m_hyperVtx[NUM_BG_STARS * 2 + i] = stars[i];
|
||||
m_hyperCol[NUM_BG_STARS * 2 + i] = col;
|
||||
|
||||
num++;
|
||||
}
|
||||
}
|
||||
Output("final num = %d\n", num);
|
||||
|
||||
m_pointSprites->SetData(NUM_BG_STARS, stars.get(), colors.get(), sizes.get(), m_material.Get());
|
||||
|
||||
Graphics::RenderStateDesc rsd;
|
||||
rsd.depthTest = false;
|
||||
rsd.depthWrite = false;
|
||||
rsd.blendMode = Graphics::BLEND_ALPHA;
|
||||
m_renderState = m_renderer->CreateRenderState(rsd);
|
||||
}
|
||||
|
||||
void Starfield::Draw(Graphics::RenderState *rs)
|
||||
{
|
||||
// XXX would be nice to get rid of the Pi:: stuff here
|
||||
if (!Pi::game || Pi::player->GetFlightState() != Ship::HYPERSPACE) {
|
||||
m_pointSprites->Draw(m_renderer, m_renderState);
|
||||
} else {
|
||||
assert(sizeof(StarVert) == 16);
|
||||
assert(m_animBuffer->GetDesc().stride == sizeof(StarVert));
|
||||
auto vtxPtr = m_animBuffer->Map<StarVert>(Graphics::BUFFER_MAP_WRITE);
|
||||
|
||||
// roughly, the multiplier gets smaller as the duration gets larger.
|
||||
// the time-looking bits in this are completely arbitrary - I figured
|
||||
// it out by tweaking the numbers until it looked sort of right
|
||||
const double mult = 0.0015 / (Pi::player->GetHyperspaceDuration() / (60.0 * 60.0 * 24.0 * 7.0));
|
||||
|
||||
const double hyperspaceProgress = Pi::game->GetHyperspaceProgress();
|
||||
|
||||
const Sint32 NUM_STARS = m_animBuffer->GetDesc().numVertices / 2;
|
||||
|
||||
const vector3d pz = Pi::player->GetOrient().VectorZ(); //back vector
|
||||
for (int i = 0; i < NUM_STARS; i++) {
|
||||
vector3f v = m_hyperVtx[NUM_STARS * 2 + i] + vector3f(pz * hyperspaceProgress * mult);
|
||||
const Color &c = m_hyperCol[NUM_STARS * 2 + i];
|
||||
|
||||
vtxPtr[i * 2].pos = m_hyperVtx[i * 2] = m_hyperVtx[NUM_STARS * 2 + i] + v;
|
||||
vtxPtr[i * 2].col = m_hyperCol[i * 2] = c;
|
||||
|
||||
vtxPtr[i * 2 + 1].pos = m_hyperVtx[i * 2 + 1] = v;
|
||||
vtxPtr[i * 2 + 1].col = m_hyperCol[i * 2 + 1] = c;
|
||||
}
|
||||
m_animBuffer->Unmap();
|
||||
m_renderer->DrawBuffer(m_animBuffer.get(), rs, m_materialStreaks.Get(), Graphics::LINE_SINGLE);
|
||||
}
|
||||
}
|
||||
|
||||
MilkyWay::MilkyWay(Graphics::Renderer *renderer)
|
||||
{
|
||||
m_renderer = renderer;
|
||||
|
||||
//build milky way model in two strips (about 256 verts)
|
||||
std::unique_ptr<Graphics::VertexArray> bottom(new VertexArray(ATTRIB_POSITION | ATTRIB_DIFFUSE));
|
||||
std::unique_ptr<Graphics::VertexArray> top(new VertexArray(ATTRIB_POSITION | ATTRIB_DIFFUSE));
|
||||
|
||||
const Color dark(Color::BLANK);
|
||||
const Color bright(13, 13, 13, 13);
|
||||
|
||||
//bottom
|
||||
float theta;
|
||||
for (theta = 0.0; theta < 2.f * float(M_PI); theta += 0.1f) {
|
||||
bottom->Add(
|
||||
vector3f(100.0f * sin(theta), float(-40.0 - 30.0 * noise(vector3d(sin(theta), 1.0, cos(theta)))), 100.0f * cos(theta)),
|
||||
dark);
|
||||
bottom->Add(
|
||||
vector3f(100.0f * sin(theta), float(5.0 * noise(vector3d(sin(theta), 0.0, cos(theta)))), 100.0f * cos(theta)),
|
||||
bright);
|
||||
}
|
||||
theta = 2.f * float(M_PI);
|
||||
bottom->Add(
|
||||
vector3f(100.0f * sin(theta), float(-40.0 - 30.0 * noise(vector3d(sin(theta), 1.0, cos(theta)))), 100.0f * cos(theta)),
|
||||
dark);
|
||||
bottom->Add(
|
||||
vector3f(100.0f * sin(theta), float(5.0 * noise(vector3d(sin(theta), 0.0, cos(theta)))), 100.0f * cos(theta)),
|
||||
bright);
|
||||
//top
|
||||
for (theta = 0; theta < 2.f * float(M_PI); theta += 0.1f) {
|
||||
top->Add(
|
||||
vector3f(100.0f * sin(theta), float(5.0 * noise(vector3d(sin(theta), 0.0, cos(theta)))), 100.0f * cos(theta)),
|
||||
bright);
|
||||
top->Add(
|
||||
vector3f(100.0f * sin(theta), float(40.0 + 30.0 * noise(vector3d(sin(theta), -1.0, cos(theta)))), 100.0f * cos(theta)),
|
||||
dark);
|
||||
}
|
||||
theta = 2.f * float(M_PI);
|
||||
top->Add(
|
||||
vector3f(100.0f * sin(theta), float(5.0 * noise(vector3d(sin(theta), 0.0, cos(theta)))), 100.0f * cos(theta)),
|
||||
bright);
|
||||
top->Add(
|
||||
vector3f(100.0f * sin(theta), float(40.0 + 30.0 * noise(vector3d(sin(theta), -1.0, cos(theta)))), 100.0f * cos(theta)),
|
||||
dark);
|
||||
|
||||
Graphics::MaterialDescriptor desc;
|
||||
desc.effect = Graphics::EFFECT_STARFIELD;
|
||||
desc.vertexColors = true;
|
||||
m_material.Reset(m_renderer->CreateMaterial(desc));
|
||||
m_material->emissive = Color::WHITE;
|
||||
|
||||
Graphics::VertexBufferDesc vbd;
|
||||
vbd.attrib[0].semantic = Graphics::ATTRIB_POSITION;
|
||||
vbd.attrib[0].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[1].semantic = Graphics::ATTRIB_DIFFUSE;
|
||||
vbd.attrib[1].format = Graphics::ATTRIB_FORMAT_UBYTE4;
|
||||
vbd.usage = Graphics::BUFFER_USAGE_DYNAMIC;
|
||||
vbd.numVertices = NUM_BG_STARS*2;
|
||||
m_animBuffer.reset(m_renderer->CreateVertexBuffer(vbd));
|
||||
vbd.numVertices = bottom->GetNumVerts() + top->GetNumVerts();
|
||||
vbd.usage = Graphics::BUFFER_USAGE_STATIC;
|
||||
|
||||
//two strips in one buffer, but seems to work ok without degenerate triangles
|
||||
m_vertexBuffer.reset(renderer->CreateVertexBuffer(vbd));
|
||||
assert(m_vertexBuffer->GetDesc().stride == sizeof(MilkyWayVert));
|
||||
auto vtxPtr = m_vertexBuffer->Map<MilkyWayVert>(Graphics::BUFFER_MAP_WRITE);
|
||||
for (Uint32 i = 0; i < top->GetNumVerts(); i++) {
|
||||
vtxPtr->pos = top->position[i];
|
||||
vtxPtr->col = top->diffuse[i];
|
||||
vtxPtr++;
|
||||
}
|
||||
for (Uint32 i = 0; i < bottom->GetNumVerts(); i++) {
|
||||
vtxPtr->pos = bottom->position[i];
|
||||
vtxPtr->col = bottom->diffuse[i];
|
||||
vtxPtr++;
|
||||
}
|
||||
m_vertexBuffer->Unmap();
|
||||
}
|
||||
|
||||
m_pointSprites.reset( new Graphics::Drawables::PointSprites );
|
||||
|
||||
assert(sizeof(StarVert) == 16);
|
||||
std::unique_ptr<vector3f[]> stars( new vector3f[NUM_BG_STARS] );
|
||||
std::unique_ptr<Color[]> colors( new Color[NUM_BG_STARS] );
|
||||
std::unique_ptr<float[]> sizes( new float[NUM_BG_STARS] );
|
||||
//fill the array
|
||||
Uint32 num = 0;
|
||||
if (Pi::game != nullptr && Pi::game->GetSpace() != nullptr && Pi::game->GetSpace()->GetStarSystem() != nullptr)
|
||||
void MilkyWay::Draw(Graphics::RenderState *rs)
|
||||
{
|
||||
const SystemPath current = Pi::game->GetSpace()->GetStarSystem()->GetPath();
|
||||
|
||||
const double size = 1.0;
|
||||
const Uint8 colScale = size * 255;
|
||||
const Sint32 visibleRadius = 100; // lyrs
|
||||
const Sint32 visibleRadiusSqr = (visibleRadius*visibleRadius);
|
||||
const Sint32 sectorMin = -(visibleRadius / Sector::SIZE); // lyrs_radius / sector_size_in_lyrs
|
||||
const Sint32 sectorMax = visibleRadius / Sector::SIZE; // lyrs_radius / sector_size_in_lyrs
|
||||
for (Sint32 x = sectorMin; x < sectorMax; x++)
|
||||
{
|
||||
for (Sint32 y = sectorMin; y < sectorMax; y++)
|
||||
{
|
||||
for (Sint32 z = sectorMin; z < sectorMax; z++)
|
||||
{
|
||||
SystemPath sys(x, y, z);
|
||||
if (SystemPath::SectorDistanceSqr(sys, current) * Sector::SIZE >= visibleRadiusSqr)
|
||||
continue; // early out
|
||||
|
||||
// this is fairly expensive
|
||||
RefCountedPtr<const Sector> sec = Pi::game->GetGalaxy()->GetSector(sys);
|
||||
|
||||
// add as many systems as we can
|
||||
const size_t numSystems = std::min(sec->m_systems.size(), (size_t)(NUM_BG_STARS - num));
|
||||
for (size_t systemIndex = 0; systemIndex < numSystems; systemIndex++)
|
||||
{
|
||||
const Sector::System *ss = &(sec->m_systems[systemIndex]);
|
||||
const vector3f distance = Sector::SIZE * vector3f(current.sectorX, current.sectorY, current.sectorZ) - ss->GetFullPosition();
|
||||
if (distance.Length() >= visibleRadius)
|
||||
continue; // too far
|
||||
|
||||
// grab the approximate real colour
|
||||
Color col = StarSystem::starRealColors[ss->GetStarType(0)];
|
||||
col.r = Clamp(col.r, (Uint8)(m_rMin * 255), (Uint8)(m_rMax * 255));
|
||||
col.g = Clamp(col.g, (Uint8)(m_gMin * 255), (Uint8)(m_gMax * 255));
|
||||
col.b = Clamp(col.b, (Uint8)(m_bMin * 255), (Uint8)(m_bMax * 255));
|
||||
//const Color col(Color::PINK); // debug pink
|
||||
|
||||
// copy the data
|
||||
sizes[num] = size;
|
||||
stars[num] = distance.Normalized() * 1000.0f;
|
||||
colors[num] = col;
|
||||
|
||||
//need to keep data around for HS anim - this is stupid
|
||||
m_hyperVtx[NUM_BG_STARS * 2 + num] = stars[num];
|
||||
m_hyperCol[NUM_BG_STARS * 2 + num] = col * 0.8f;
|
||||
num++;
|
||||
}
|
||||
if (num >= NUM_BG_STARS)
|
||||
{
|
||||
x = sectorMax;
|
||||
y = sectorMax;
|
||||
z = sectorMax;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(m_vertexBuffer);
|
||||
assert(m_material);
|
||||
m_renderer->DrawBuffer(m_vertexBuffer.get(), rs, m_material.Get(), Graphics::TRIANGLE_STRIP);
|
||||
}
|
||||
Output("num = %d\n", num);
|
||||
|
||||
// fill out the remaining target count with generated points
|
||||
if(num < NUM_BG_STARS)
|
||||
Container::Container(Graphics::Renderer *renderer, Random &rand) :
|
||||
m_renderer(renderer),
|
||||
m_milkyWay(renderer),
|
||||
m_starField(renderer, rand),
|
||||
m_universeBox(renderer),
|
||||
m_drawFlags(DRAW_SKYBOX | DRAW_STARS)
|
||||
{
|
||||
for (Uint32 i = num; i < NUM_BG_STARS; i++)
|
||||
{
|
||||
const double size = rand.Double(0.2, 0.9);
|
||||
const Uint8 colScale = size * 255;
|
||||
|
||||
const Color col(
|
||||
rand.Double(m_rMin, m_rMax)*colScale,
|
||||
rand.Double(m_gMin, m_gMax)*colScale,
|
||||
rand.Double(m_bMin, m_bMax)*colScale,
|
||||
255);
|
||||
|
||||
// this is proper random distribution on a sphere's surface
|
||||
const float theta = float(rand.Double(0.0, 2.0*M_PI));
|
||||
const float u = float(rand.Double(-1.0, 1.0));
|
||||
|
||||
sizes[i] = size;
|
||||
// squeeze the starfield a bit to get more density near horizon using matrix3x3f::Scale
|
||||
stars[i] = matrix3x3f::Scale(1.0, 0.4, 1.0) * (vector3f(sqrt(1.0f - u * u) * cos(theta), u, sqrt(1.0f - u * u) * sin(theta)).Normalized() * 1000.0f);
|
||||
colors[i] = col;
|
||||
|
||||
//need to keep data around for HS anim - this is stupid
|
||||
m_hyperVtx[NUM_BG_STARS * 2 + i] = stars[i];
|
||||
m_hyperCol[NUM_BG_STARS * 2 + i] = col;
|
||||
|
||||
num++;
|
||||
}
|
||||
Graphics::RenderStateDesc rsd;
|
||||
rsd.depthTest = false;
|
||||
rsd.depthWrite = false;
|
||||
m_renderState = renderer->CreateRenderState(rsd);
|
||||
Refresh(rand);
|
||||
}
|
||||
Output("final num = %d\n", num);
|
||||
|
||||
m_pointSprites->SetData(NUM_BG_STARS, stars.get(), colors.get(), sizes.get(), m_material.Get());
|
||||
|
||||
Graphics::RenderStateDesc rsd;
|
||||
rsd.depthTest = false;
|
||||
rsd.depthWrite = false;
|
||||
rsd.blendMode = Graphics::BLEND_ALPHA;
|
||||
m_renderState = m_renderer->CreateRenderState(rsd);
|
||||
}
|
||||
|
||||
void Starfield::Draw(Graphics::RenderState *rs)
|
||||
{
|
||||
// XXX would be nice to get rid of the Pi:: stuff here
|
||||
if (!Pi::game || Pi::player->GetFlightState() != Ship::HYPERSPACE) {
|
||||
m_pointSprites->Draw(m_renderer, m_renderState);
|
||||
} else {
|
||||
assert(sizeof(StarVert) == 16);
|
||||
assert(m_animBuffer->GetDesc().stride == sizeof(StarVert));
|
||||
auto vtxPtr = m_animBuffer->Map<StarVert>(Graphics::BUFFER_MAP_WRITE);
|
||||
|
||||
// roughly, the multiplier gets smaller as the duration gets larger.
|
||||
// the time-looking bits in this are completely arbitrary - I figured
|
||||
// it out by tweaking the numbers until it looked sort of right
|
||||
const double mult = 0.0015 / (Pi::player->GetHyperspaceDuration() / (60.0*60.0*24.0*7.0));
|
||||
|
||||
const double hyperspaceProgress = Pi::game->GetHyperspaceProgress();
|
||||
|
||||
const Sint32 NUM_STARS = m_animBuffer->GetDesc().numVertices / 2;
|
||||
|
||||
const vector3d pz = Pi::player->GetOrient().VectorZ(); //back vector
|
||||
for (int i=0; i<NUM_STARS; i++) {
|
||||
vector3f v = m_hyperVtx[NUM_STARS * 2 + i] + vector3f(pz*hyperspaceProgress*mult);
|
||||
const Color &c = m_hyperCol[NUM_STARS * 2 + i];
|
||||
|
||||
vtxPtr[i*2].pos = m_hyperVtx[i*2] = m_hyperVtx[NUM_STARS * 2 + i] + v;
|
||||
vtxPtr[i*2].col = m_hyperCol[i*2] = c;
|
||||
|
||||
vtxPtr[i*2+1].pos = m_hyperVtx[i*2+1] = v;
|
||||
vtxPtr[i*2+1].col = m_hyperCol[i*2+1] = c;
|
||||
}
|
||||
m_animBuffer->Unmap();
|
||||
m_renderer->DrawBuffer(m_animBuffer.get(), rs, m_materialStreaks.Get(), Graphics::LINE_SINGLE);
|
||||
void Container::Refresh(Random &rand)
|
||||
{
|
||||
// always redo starfield, milkyway stays normal for now
|
||||
m_starField.Fill(rand);
|
||||
m_universeBox.LoadCubeMap(rand);
|
||||
}
|
||||
}
|
||||
|
||||
MilkyWay::MilkyWay(Graphics::Renderer *renderer)
|
||||
{
|
||||
m_renderer = renderer;
|
||||
|
||||
//build milky way model in two strips (about 256 verts)
|
||||
std::unique_ptr<Graphics::VertexArray> bottom(new VertexArray(ATTRIB_POSITION | ATTRIB_DIFFUSE));
|
||||
std::unique_ptr<Graphics::VertexArray> top(new VertexArray(ATTRIB_POSITION | ATTRIB_DIFFUSE));
|
||||
|
||||
const Color dark(Color::BLANK);
|
||||
const Color bright(13, 13, 13, 13);
|
||||
|
||||
//bottom
|
||||
float theta;
|
||||
for (theta=0.0; theta < 2.f*float(M_PI); theta+=0.1f) {
|
||||
bottom->Add(
|
||||
vector3f(100.0f*sin(theta), float(-40.0 - 30.0*noise(vector3d(sin(theta),1.0,cos(theta)))), 100.0f*cos(theta)),
|
||||
dark);
|
||||
bottom->Add(
|
||||
vector3f(100.0f*sin(theta), float(5.0*noise(vector3d(sin(theta),0.0,cos(theta)))), 100.0f*cos(theta)),
|
||||
bright);
|
||||
}
|
||||
theta = 2.f*float(M_PI);
|
||||
bottom->Add(
|
||||
vector3f(100.0f*sin(theta), float(-40.0 - 30.0*noise(vector3d(sin(theta),1.0,cos(theta)))), 100.0f*cos(theta)),
|
||||
dark);
|
||||
bottom->Add(
|
||||
vector3f(100.0f*sin(theta), float(5.0*noise(vector3d(sin(theta),0.0,cos(theta)))), 100.0f*cos(theta)),
|
||||
bright);
|
||||
//top
|
||||
for (theta=0; theta < 2.f*float(M_PI); theta+=0.1f) {
|
||||
top->Add(
|
||||
vector3f(100.0f*sin(theta), float(5.0*noise(vector3d(sin(theta),0.0,cos(theta)))), 100.0f*cos(theta)),
|
||||
bright);
|
||||
top->Add(
|
||||
vector3f(100.0f*sin(theta), float(40.0 + 30.0*noise(vector3d(sin(theta),-1.0,cos(theta)))), 100.0f*cos(theta)),
|
||||
dark);
|
||||
}
|
||||
theta = 2.f*float(M_PI);
|
||||
top->Add(
|
||||
vector3f(100.0f*sin(theta), float(5.0*noise(vector3d(sin(theta),0.0,cos(theta)))), 100.0f*cos(theta)),
|
||||
bright);
|
||||
top->Add(
|
||||
vector3f(100.0f*sin(theta), float(40.0 + 30.0*noise(vector3d(sin(theta),-1.0,cos(theta)))), 100.0f*cos(theta)),
|
||||
dark);
|
||||
|
||||
Graphics::MaterialDescriptor desc;
|
||||
desc.effect = Graphics::EFFECT_STARFIELD;
|
||||
desc.vertexColors = true;
|
||||
m_material.Reset(m_renderer->CreateMaterial(desc));
|
||||
m_material->emissive = Color::WHITE;
|
||||
|
||||
Graphics::VertexBufferDesc vbd;
|
||||
vbd.attrib[0].semantic = Graphics::ATTRIB_POSITION;
|
||||
vbd.attrib[0].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[1].semantic = Graphics::ATTRIB_DIFFUSE;
|
||||
vbd.attrib[1].format = Graphics::ATTRIB_FORMAT_UBYTE4;
|
||||
vbd.numVertices = bottom->GetNumVerts() + top->GetNumVerts();
|
||||
vbd.usage = Graphics::BUFFER_USAGE_STATIC;
|
||||
|
||||
//two strips in one buffer, but seems to work ok without degenerate triangles
|
||||
m_vertexBuffer.reset(renderer->CreateVertexBuffer(vbd));
|
||||
assert(m_vertexBuffer->GetDesc().stride == sizeof(MilkyWayVert));
|
||||
auto vtxPtr = m_vertexBuffer->Map<MilkyWayVert>(Graphics::BUFFER_MAP_WRITE);
|
||||
for (Uint32 i = 0; i < top->GetNumVerts(); i++) {
|
||||
vtxPtr->pos = top->position[i];
|
||||
vtxPtr->col = top->diffuse[i];
|
||||
vtxPtr++;
|
||||
}
|
||||
for (Uint32 i = 0; i < bottom->GetNumVerts(); i++) {
|
||||
vtxPtr->pos = bottom->position[i];
|
||||
vtxPtr->col = bottom->diffuse[i];
|
||||
vtxPtr++;
|
||||
}
|
||||
m_vertexBuffer->Unmap();
|
||||
}
|
||||
|
||||
void MilkyWay::Draw(Graphics::RenderState *rs)
|
||||
{
|
||||
assert(m_vertexBuffer);
|
||||
assert(m_material);
|
||||
m_renderer->DrawBuffer(m_vertexBuffer.get(), rs, m_material.Get(), Graphics::TRIANGLE_STRIP);
|
||||
}
|
||||
|
||||
Container::Container(Graphics::Renderer *renderer, Random &rand)
|
||||
: m_renderer(renderer)
|
||||
, m_milkyWay(renderer)
|
||||
, m_starField(renderer, rand)
|
||||
, m_universeBox(renderer)
|
||||
, m_drawFlags( DRAW_SKYBOX | DRAW_STARS )
|
||||
{
|
||||
Graphics::RenderStateDesc rsd;
|
||||
rsd.depthTest = false;
|
||||
rsd.depthWrite = false;
|
||||
m_renderState = renderer->CreateRenderState(rsd);
|
||||
Refresh(rand);
|
||||
}
|
||||
|
||||
void Container::Refresh(Random &rand)
|
||||
{
|
||||
// always redo starfield, milkyway stays normal for now
|
||||
m_starField.Fill(rand);
|
||||
m_universeBox.LoadCubeMap(rand);
|
||||
}
|
||||
|
||||
void Container::Draw(const matrix4x4d &transform)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
m_renderer->SetTransform(transform);
|
||||
if( DRAW_SKYBOX & m_drawFlags ) {
|
||||
m_universeBox.Draw(m_renderState);
|
||||
}
|
||||
if( DRAW_MILKY & m_drawFlags ) {
|
||||
m_milkyWay.Draw(m_renderState);
|
||||
}
|
||||
if( DRAW_STARS & m_drawFlags ) {
|
||||
void Container::Draw(const matrix4x4d &transform)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
m_renderer->SetTransform(transform);
|
||||
m_starField.Draw(m_renderState);
|
||||
if (DRAW_SKYBOX & m_drawFlags) {
|
||||
m_universeBox.Draw(m_renderState);
|
||||
}
|
||||
if (DRAW_MILKY & m_drawFlags) {
|
||||
m_milkyWay.Draw(m_renderState);
|
||||
}
|
||||
if (DRAW_STARS & m_drawFlags) {
|
||||
m_renderer->SetTransform(transform);
|
||||
m_starField.Draw(m_renderState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Container::SetIntensity(float intensity)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
intensity = Clamp(intensity, 0.0f, 1.0f);
|
||||
m_universeBox.SetIntensity(intensity);
|
||||
m_starField.SetIntensity(intensity);
|
||||
m_milkyWay.SetIntensity(intensity);
|
||||
}
|
||||
void Container::SetIntensity(float intensity)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
intensity = Clamp(intensity, 0.0f, 1.0f);
|
||||
m_universeBox.SetIntensity(intensity);
|
||||
m_starField.SetIntensity(intensity);
|
||||
m_milkyWay.SetIntensity(intensity);
|
||||
}
|
||||
|
||||
void Container::SetDrawFlags(const Uint32 flags)
|
||||
{
|
||||
m_drawFlags = flags;
|
||||
}
|
||||
void Container::SetDrawFlags(const Uint32 flags)
|
||||
{
|
||||
m_drawFlags = flags;
|
||||
}
|
||||
|
||||
} //namespace Background
|
||||
|
|
|
@ -4,26 +4,24 @@
|
|||
#ifndef _BACKGROUND_H
|
||||
#define _BACKGROUND_H
|
||||
|
||||
#include "libs.h"
|
||||
#include "Random.h"
|
||||
#include "galaxy/SystemPath.h"
|
||||
#include "graphics/Drawables.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/RenderState.h"
|
||||
#include "Random.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "libs.h"
|
||||
|
||||
namespace Graphics {
|
||||
class Renderer;
|
||||
class Material;
|
||||
}
|
||||
} // namespace Graphics
|
||||
|
||||
/*
|
||||
* Classes to draw background stars and the milky way
|
||||
*/
|
||||
|
||||
namespace Background
|
||||
{
|
||||
class BackgroundElement
|
||||
{
|
||||
namespace Background {
|
||||
class BackgroundElement {
|
||||
public:
|
||||
void SetIntensity(float intensity);
|
||||
|
||||
|
@ -40,13 +38,12 @@ namespace Background
|
|||
float m_bMax;
|
||||
};
|
||||
|
||||
class UniverseBox : public BackgroundElement
|
||||
{
|
||||
class UniverseBox : public BackgroundElement {
|
||||
public:
|
||||
UniverseBox(Graphics::Renderer *r);
|
||||
~UniverseBox();
|
||||
|
||||
void Draw(Graphics::RenderState*);
|
||||
void Draw(Graphics::RenderState *);
|
||||
void LoadCubeMap(Random &rand);
|
||||
|
||||
private:
|
||||
|
@ -58,12 +55,11 @@ namespace Background
|
|||
Uint32 m_numCubemaps;
|
||||
};
|
||||
|
||||
class Starfield : public BackgroundElement
|
||||
{
|
||||
class Starfield : public BackgroundElement {
|
||||
public:
|
||||
//does not Fill the starfield
|
||||
Starfield(Graphics::Renderer *r, Random &rand);
|
||||
void Draw(Graphics::RenderState*);
|
||||
void Draw(Graphics::RenderState *);
|
||||
//create or recreate the starfield
|
||||
void Fill(Random &rand);
|
||||
|
||||
|
@ -71,38 +67,33 @@ namespace Background
|
|||
void Init();
|
||||
|
||||
std::unique_ptr<Graphics::Drawables::PointSprites> m_pointSprites;
|
||||
Graphics::RenderState* m_renderState; // NB: we don't own RenderState pointers, just borrow them
|
||||
Graphics::RenderState *m_renderState; // NB: we don't own RenderState pointers, just borrow them
|
||||
|
||||
//hyperspace animation vertex data
|
||||
std::unique_ptr<vector3f[]> m_hyperVtx;// BG_STAR_MAX * 3
|
||||
std::unique_ptr<Color[]> m_hyperCol;// BG_STAR_MAX * 3
|
||||
std::unique_ptr<vector3f[]> m_hyperVtx; // BG_STAR_MAX * 3
|
||||
std::unique_ptr<Color[]> m_hyperCol; // BG_STAR_MAX * 3
|
||||
std::unique_ptr<Graphics::VertexBuffer> m_animBuffer;
|
||||
};
|
||||
|
||||
class MilkyWay : public BackgroundElement
|
||||
{
|
||||
class MilkyWay : public BackgroundElement {
|
||||
public:
|
||||
MilkyWay(Graphics::Renderer*);
|
||||
void Draw(Graphics::RenderState*);
|
||||
MilkyWay(Graphics::Renderer *);
|
||||
void Draw(Graphics::RenderState *);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Graphics::VertexBuffer> m_vertexBuffer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// contains starfield, milkyway, possibly other Background elements
|
||||
class Container
|
||||
{
|
||||
class Container {
|
||||
public:
|
||||
enum BackgroundDrawFlags
|
||||
{
|
||||
DRAW_STARS = 1<<0,
|
||||
DRAW_MILKY = 1<<1,
|
||||
DRAW_SKYBOX = 1<<2
|
||||
enum BackgroundDrawFlags {
|
||||
DRAW_STARS = 1 << 0,
|
||||
DRAW_MILKY = 1 << 1,
|
||||
DRAW_SKYBOX = 1 << 2
|
||||
};
|
||||
|
||||
Container(Graphics::Renderer*, Random &rand);
|
||||
Container(Graphics::Renderer *, Random &rand);
|
||||
void Draw(const matrix4x4d &transform);
|
||||
|
||||
void SetIntensity(float intensity);
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "Pi.h"
|
||||
#include "BaseSphere.h"
|
||||
#include "GeoSphere.h"
|
||||
#include "GasGiant.h"
|
||||
#include "GeoSphere.h"
|
||||
#include "Pi.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "libs.h"
|
||||
|
||||
BaseSphere::BaseSphere(const SystemBody *body) : m_sbody(body), m_terrain(Terrain::InstanceTerrain(body)) {}
|
||||
BaseSphere::BaseSphere(const SystemBody *body) :
|
||||
m_sbody(body),
|
||||
m_terrain(Terrain::InstanceTerrain(body)) {}
|
||||
|
||||
BaseSphere::~BaseSphere() {}
|
||||
|
||||
|
@ -52,8 +54,8 @@ void BaseSphere::DrawAtmosphereSurface(Graphics::Renderer *renderer,
|
|||
|
||||
renderer->SetTransform(modelView * matrix4x4d::ScaleMatrix(rad, rad, rad) * invrot);
|
||||
|
||||
if(!m_atmos)
|
||||
m_atmos.reset( new Drawables::Sphere3D(renderer, mat, rs, 4, 1.0f, ATTRIB_POSITION));
|
||||
if (!m_atmos)
|
||||
m_atmos.reset(new Drawables::Sphere3D(renderer, mat, rs, 4, 1.0f, ATTRIB_POSITION));
|
||||
m_atmos->Draw(renderer);
|
||||
|
||||
renderer->GetStats().AddToStatCount(Graphics::Stats::STAT_ATMOSPHERES, 1);
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
#include <SDL_stdinc.h>
|
||||
|
||||
#include "vector3.h"
|
||||
#include "Camera.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "terrain/Terrain.h"
|
||||
#include "vector3.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
|
@ -17,7 +17,7 @@ namespace Graphics {
|
|||
class Renderer;
|
||||
class RenderState;
|
||||
class Material;
|
||||
}
|
||||
} // namespace Graphics
|
||||
class SystemBody;
|
||||
|
||||
class BaseSphere {
|
||||
|
@ -25,8 +25,8 @@ public:
|
|||
BaseSphere(const SystemBody *body);
|
||||
virtual ~BaseSphere();
|
||||
|
||||
virtual void Update()=0;
|
||||
virtual void Render(Graphics::Renderer *renderer, const matrix4x4d &modelView, vector3d campos, const float radius, const std::vector<Camera::Shadow> &shadows)=0;
|
||||
virtual void Update() = 0;
|
||||
virtual void Render(Graphics::Renderer *renderer, const matrix4x4d &modelView, vector3d campos, const float radius, const std::vector<Camera::Shadow> &shadows) = 0;
|
||||
|
||||
virtual double GetHeight(const vector3d &p) const { return 0.0; }
|
||||
|
||||
|
@ -49,14 +49,14 @@ public:
|
|||
Sint32 maxPatchDepth;
|
||||
};
|
||||
|
||||
virtual void Reset()=0;
|
||||
virtual void Reset() = 0;
|
||||
|
||||
const SystemBody *GetSystemBody() const { return m_sbody; }
|
||||
Terrain* GetTerrain() const { return m_terrain.Get(); }
|
||||
Terrain *GetTerrain() const { return m_terrain.Get(); }
|
||||
|
||||
Graphics::RenderState* GetSurfRenderState() const { return m_surfRenderState; }
|
||||
Graphics::RenderState *GetSurfRenderState() const { return m_surfRenderState; }
|
||||
RefCountedPtr<Graphics::Material> GetSurfaceMaterial() const { return m_surfaceMaterial; }
|
||||
MaterialParameters& GetMaterialParameters() { return m_materialParameters; }
|
||||
MaterialParameters &GetMaterialParameters() { return m_materialParameters; }
|
||||
|
||||
protected:
|
||||
const SystemBody *m_sbody;
|
||||
|
@ -64,7 +64,7 @@ protected:
|
|||
// all variables for GetHeight(), GetColor()
|
||||
RefCountedPtr<Terrain> m_terrain;
|
||||
|
||||
virtual void SetUpMaterials()=0;
|
||||
virtual void SetUpMaterials() = 0;
|
||||
|
||||
Graphics::RenderState *m_surfRenderState;
|
||||
Graphics::RenderState *m_atmosRenderState;
|
||||
|
|
84
src/Beam.cpp
84
src/Beam.cpp
|
@ -1,32 +1,30 @@
|
|||
// Copyright © 2008-2016 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "Pi.h"
|
||||
#include "Beam.h"
|
||||
#include "Frame.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "Space.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "collider/collider.h"
|
||||
#include "CargoBody.h"
|
||||
#include "Planet.h"
|
||||
#include "Sfx.h"
|
||||
#include "Ship.h"
|
||||
#include "Pi.h"
|
||||
#include "Player.h"
|
||||
#include "Frame.h"
|
||||
#include "Game.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "LuaEvent.h"
|
||||
#include "LuaUtils.h"
|
||||
#include "Pi.h"
|
||||
#include "Planet.h"
|
||||
#include "Player.h"
|
||||
#include "Sfx.h"
|
||||
#include "Ship.h"
|
||||
#include "Space.h"
|
||||
#include "collider/collider.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "graphics/TextureBuilder.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "libs.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
static float lifetime = 0.1f;
|
||||
}
|
||||
|
||||
|
@ -53,8 +51,8 @@ void Beam::BuildModel()
|
|||
const float w = 0.5f;
|
||||
|
||||
vector3f one(0.f, -w, 0.f); //top left
|
||||
vector3f two(0.f, w, 0.f); //top right
|
||||
vector3f three(0.f, w, -1.f); //bottom right
|
||||
vector3f two(0.f, w, 0.f); //top right
|
||||
vector3f three(0.f, w, -1.f); //bottom right
|
||||
vector3f four(0.f, -w, -1.f); //bottom left
|
||||
|
||||
//uv coords
|
||||
|
@ -67,7 +65,7 @@ void Beam::BuildModel()
|
|||
s_glowVerts.reset(new Graphics::VertexArray(Graphics::ATTRIB_POSITION | Graphics::ATTRIB_UV0, 240));
|
||||
|
||||
//add four intersecting planes to create a volumetric effect
|
||||
for (int i=0; i < 4; i++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
s_sideVerts->Add(one, topLeft);
|
||||
s_sideVerts->Add(two, topRight);
|
||||
s_sideVerts->Add(three, botRight);
|
||||
|
@ -86,7 +84,7 @@ void Beam::BuildModel()
|
|||
static const float gw = 0.5f;
|
||||
float gz = -0.1f;
|
||||
|
||||
for (int i=0; i < 40; i++) {
|
||||
for (int i = 0; i < 40; i++) {
|
||||
s_glowVerts->Add(vector3f(-gw, -gw, gz), topLeft);
|
||||
s_glowVerts->Add(vector3f(-gw, gw, gz), topRight);
|
||||
s_glowVerts->Add(vector3f(gw, gw, gz), botRight);
|
||||
|
@ -113,7 +111,8 @@ void Beam::FreeModel()
|
|||
s_glowVerts.reset();
|
||||
}
|
||||
|
||||
Beam::Beam(): Body()
|
||||
Beam::Beam() :
|
||||
Body()
|
||||
{
|
||||
if (!s_sideMat) BuildModel();
|
||||
SetOrient(matrix3x3d::Identity());
|
||||
|
@ -174,10 +173,10 @@ void Beam::UpdateInterpTransform(double alpha)
|
|||
{
|
||||
m_interpOrient = GetOrient();
|
||||
const vector3d oldPos = GetPosition() - (m_baseVel * Pi::game->GetTimeStep());
|
||||
m_interpPos = alpha*GetPosition() + (1.0-alpha)*oldPos;
|
||||
m_interpPos = alpha * GetPosition() + (1.0 - alpha) * oldPos;
|
||||
}
|
||||
|
||||
void Beam::NotifyRemoved(const Body* const removedBody)
|
||||
void Beam::NotifyRemoved(const Body *const removedBody)
|
||||
{
|
||||
if (m_parent == removedBody)
|
||||
m_parent = nullptr;
|
||||
|
@ -199,7 +198,7 @@ float Beam::GetDamage() const
|
|||
|
||||
double Beam::GetRadius() const
|
||||
{
|
||||
return sqrt(m_length*m_length);
|
||||
return sqrt(m_length * m_length);
|
||||
}
|
||||
|
||||
static void MiningLaserSpawnTastyStuff(Frame *f, const SystemBody *asteroid, const vector3d &pos)
|
||||
|
@ -230,8 +229,8 @@ static void MiningLaserSpawnTastyStuff(Frame *f, const SystemBody *asteroid, con
|
|||
cargo->SetPosition(pos);
|
||||
const double x = Pi::rng.Double();
|
||||
vector3d dir = pos.Normalized();
|
||||
dir.ArbRotate(vector3d(x, 1-x, 0), Pi::rng.Double()-.5);
|
||||
cargo->SetVelocity(Pi::rng.Double(100.0,200.0) * dir);
|
||||
dir.ArbRotate(vector3d(x, 1 - x, 0), Pi::rng.Double() - .5);
|
||||
cargo->SetVelocity(Pi::rng.Double(100.0, 200.0) * dir);
|
||||
Pi::game->GetSpace()->AddBody(cargo);
|
||||
}
|
||||
|
||||
|
@ -243,21 +242,20 @@ void Beam::StaticUpdate(const float timeStep)
|
|||
return;
|
||||
|
||||
CollisionContact c;
|
||||
GetFrame()->GetCollisionSpace()->TraceRay(GetPosition(), m_dir.Normalized(), m_length, &c, static_cast<ModelBody*>(m_parent)->GetGeom());
|
||||
GetFrame()->GetCollisionSpace()->TraceRay(GetPosition(), m_dir.Normalized(), m_length, &c, static_cast<ModelBody *>(m_parent)->GetGeom());
|
||||
|
||||
if (c.userData1) {
|
||||
Object *o = static_cast<Object*>(c.userData1);
|
||||
Object *o = static_cast<Object *>(c.userData1);
|
||||
|
||||
if (o->IsType(Object::CITYONPLANET)) {
|
||||
Pi::game->GetSpace()->KillBody(this);
|
||||
}
|
||||
else if (o->IsType(Object::BODY)) {
|
||||
Body *hit = static_cast<Body*>(o);
|
||||
} else if (o->IsType(Object::BODY)) {
|
||||
Body *hit = static_cast<Body *>(o);
|
||||
if (hit != m_parent) {
|
||||
hit->OnDamage(m_parent, GetDamage(), c);
|
||||
m_active = false;
|
||||
if (hit->IsType(Object::SHIP))
|
||||
LuaEvent::Queue("onShipHit", dynamic_cast<Ship*>(hit), dynamic_cast<Body*>(m_parent));
|
||||
LuaEvent::Queue("onShipHit", dynamic_cast<Ship *>(hit), dynamic_cast<Body *>(m_parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +263,7 @@ void Beam::StaticUpdate(const float timeStep)
|
|||
if (m_mining) {
|
||||
// need to test for terrain hit
|
||||
if (GetFrame()->GetBody() && GetFrame()->GetBody()->IsType(Object::PLANET)) {
|
||||
Planet *const planet = static_cast<Planet*>(GetFrame()->GetBody());
|
||||
Planet *const planet = static_cast<Planet *>(GetFrame()->GetBody());
|
||||
const SystemBody *b = planet->GetSystemBody();
|
||||
vector3d pos = GetPosition();
|
||||
double terrainHeight = planet->GetTerrainHeight(pos.Normalized());
|
||||
|
@ -273,7 +271,7 @@ void Beam::StaticUpdate(const float timeStep)
|
|||
// hit the fucker
|
||||
if (b->GetType() == SystemBody::TYPE_PLANET_ASTEROID) {
|
||||
vector3d n = GetPosition().Normalized();
|
||||
MiningLaserSpawnTastyStuff(planet->GetFrame(), b, n*terrainHeight + 5.0*n);
|
||||
MiningLaserSpawnTastyStuff(planet->GetFrame(), b, n * terrainHeight + 5.0 * n);
|
||||
SfxManager::Add(this, TYPE_EXPLOSION);
|
||||
}
|
||||
m_active = false;
|
||||
|
@ -293,12 +291,20 @@ void Beam::Render(Graphics::Renderer *renderer, const Camera *camera, const vect
|
|||
|
||||
vector3f v1, v2;
|
||||
matrix4x4f m = matrix4x4f::Identity();
|
||||
v1.x = dir.y; v1.y = dir.z; v1.z = dir.x;
|
||||
v1.x = dir.y;
|
||||
v1.y = dir.z;
|
||||
v1.z = dir.x;
|
||||
v2 = v1.Cross(dir).Normalized();
|
||||
v1 = v2.Cross(dir);
|
||||
m[0] = v1.x; m[4] = v2.x; m[8] = dir.x;
|
||||
m[1] = v1.y; m[5] = v2.y; m[9] = dir.y;
|
||||
m[2] = v1.z; m[6] = v2.z; m[10] = dir.z;
|
||||
m[0] = v1.x;
|
||||
m[4] = v2.x;
|
||||
m[8] = dir.x;
|
||||
m[1] = v1.y;
|
||||
m[5] = v2.y;
|
||||
m[9] = dir.y;
|
||||
m[2] = v1.z;
|
||||
m[6] = v2.z;
|
||||
m[10] = dir.z;
|
||||
|
||||
m[12] = from.x;
|
||||
m[13] = from.y;
|
||||
|
@ -337,7 +343,7 @@ void Beam::Render(Graphics::Renderer *renderer, const Camera *camera, const vect
|
|||
}
|
||||
|
||||
// static
|
||||
void Beam::Add(Body *parent, const ProjectileData& prData, const vector3d &pos, const vector3d &baseVel, const vector3d &dir)
|
||||
void Beam::Add(Body *parent, const ProjectileData &prData, const vector3d &pos, const vector3d &baseVel, const vector3d &dir)
|
||||
{
|
||||
Beam *p = new Beam();
|
||||
p->m_parent = parent;
|
||||
|
|
10
src/Beam.h
10
src/Beam.h
|
@ -6,30 +6,30 @@
|
|||
#ifndef _BEAM_H
|
||||
#define _BEAM_H
|
||||
|
||||
#include "libs.h"
|
||||
#include "Body.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/RenderState.h"
|
||||
#include "libs.h"
|
||||
|
||||
class Frame;
|
||||
namespace Graphics {
|
||||
class Renderer;
|
||||
class VertexArray;
|
||||
}
|
||||
} // namespace Graphics
|
||||
struct ProjectileData;
|
||||
|
||||
class Beam: public Body {
|
||||
class Beam : public Body {
|
||||
public:
|
||||
OBJDEF(Beam, Body, PROJECTILE);
|
||||
|
||||
static void Add(Body *parent, const ProjectileData& prData, const vector3d &pos, const vector3d &baseVel, const vector3d &dir);
|
||||
static void Add(Body *parent, const ProjectileData &prData, const vector3d &pos, const vector3d &baseVel, const vector3d &dir);
|
||||
|
||||
Beam();
|
||||
virtual ~Beam();
|
||||
virtual void Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform) override final;
|
||||
void TimeStepUpdate(const float timeStep) override final;
|
||||
void StaticUpdate(const float timeStep) override final;
|
||||
virtual void NotifyRemoved(const Body* const removedBody) override final;
|
||||
virtual void NotifyRemoved(const Body *const removedBody) override final;
|
||||
virtual void PostLoadFixup(Space *space) override final;
|
||||
virtual void UpdateInterpTransform(double alpha) override final;
|
||||
|
||||
|
|
87
src/Body.cpp
87
src/Body.cpp
|
@ -1,35 +1,36 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "Body.h"
|
||||
#include "Frame.h"
|
||||
#include "Star.h"
|
||||
#include "Planet.h"
|
||||
#include "CargoBody.h"
|
||||
#include "SpaceStation.h"
|
||||
#include "Ship.h"
|
||||
#include "Frame.h"
|
||||
#include "Game.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "HyperspaceCloud.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "LuaEvent.h"
|
||||
#include "Missile.h"
|
||||
#include "Pi.h"
|
||||
#include "Planet.h"
|
||||
#include "Player.h"
|
||||
#include "Projectile.h"
|
||||
#include "Missile.h"
|
||||
#include "HyperspaceCloud.h"
|
||||
#include "Pi.h"
|
||||
#include "Ship.h"
|
||||
#include "Space.h"
|
||||
#include "Game.h"
|
||||
#include "LuaEvent.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "SpaceStation.h"
|
||||
#include "Star.h"
|
||||
#include "libs.h"
|
||||
|
||||
Body::Body() : PropertiedObject(Lua::manager)
|
||||
, m_flags(0)
|
||||
, m_interpPos(0.0)
|
||||
, m_interpOrient(matrix3x3d::Identity())
|
||||
, m_pos(0.0)
|
||||
, m_orient(matrix3x3d::Identity())
|
||||
, m_frame(0)
|
||||
, m_dead(false)
|
||||
, m_clipRadius(0.0)
|
||||
, m_physRadius(0.0)
|
||||
Body::Body() :
|
||||
PropertiedObject(Lua::manager),
|
||||
m_flags(0),
|
||||
m_interpPos(0.0),
|
||||
m_interpOrient(matrix3x3d::Identity()),
|
||||
m_pos(0.0),
|
||||
m_orient(matrix3x3d::Identity()),
|
||||
m_frame(0),
|
||||
m_dead(false),
|
||||
m_clipRadius(0.0),
|
||||
m_physRadius(0.0)
|
||||
{
|
||||
Properties().Set("label", m_label);
|
||||
}
|
||||
|
@ -70,8 +71,7 @@ void Body::LoadFromJson(const Json &jsonObj, Space *space)
|
|||
m_orient = bodyObj["orient"];
|
||||
m_physRadius = bodyObj["phys_radius"];
|
||||
m_clipRadius = bodyObj["clip_radius"];
|
||||
}
|
||||
catch (Json::type_error &) {
|
||||
} catch (Json::type_error &) {
|
||||
throw SavedGameCorruptException();
|
||||
}
|
||||
}
|
||||
|
@ -106,23 +106,32 @@ Body *Body::FromJson(const Json &jsonObj, Space *space)
|
|||
Object::Type type = Object::Type(jsonObj["body_type"]);
|
||||
switch (type) {
|
||||
case Object::STAR:
|
||||
b = new Star(); break;
|
||||
b = new Star();
|
||||
break;
|
||||
case Object::PLANET:
|
||||
b = new Planet(); break;
|
||||
b = new Planet();
|
||||
break;
|
||||
case Object::SPACESTATION:
|
||||
b = new SpaceStation(); break;
|
||||
b = new SpaceStation();
|
||||
break;
|
||||
case Object::SHIP:
|
||||
b = new Ship(); break;
|
||||
b = new Ship();
|
||||
break;
|
||||
case Object::PLAYER:
|
||||
b = new Player(); break;
|
||||
b = new Player();
|
||||
break;
|
||||
case Object::MISSILE:
|
||||
b = new Missile(); break;
|
||||
b = new Missile();
|
||||
break;
|
||||
case Object::PROJECTILE:
|
||||
b = new Projectile(); break;
|
||||
b = new Projectile();
|
||||
break;
|
||||
case Object::CARGOBODY:
|
||||
b = new CargoBody(); break;
|
||||
b = new CargoBody();
|
||||
break;
|
||||
case Object::HYPERSPACECLOUD:
|
||||
b = new HyperspaceCloud(); break;
|
||||
b = new HyperspaceCloud();
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
@ -181,16 +190,16 @@ vector3d Body::GetVelocityRelTo(const Body *relTo) const
|
|||
|
||||
void Body::OrientOnSurface(double radius, double latitude, double longitude)
|
||||
{
|
||||
vector3d up = vector3d(cos(latitude)*cos(longitude), sin(latitude)*cos(longitude), sin(longitude));
|
||||
vector3d up = vector3d(cos(latitude) * cos(longitude), sin(latitude) * cos(longitude), sin(longitude));
|
||||
SetPosition(radius * up);
|
||||
|
||||
vector3d right = up.Cross(vector3d(0,0,1)).Normalized();
|
||||
vector3d right = up.Cross(vector3d(0, 0, 1)).Normalized();
|
||||
SetOrient(matrix3x3d::FromVectors(right, up));
|
||||
}
|
||||
|
||||
void Body::SwitchToFrame(Frame *newFrame)
|
||||
{
|
||||
const vector3d vel = GetVelocityRelTo(newFrame); // do this first because it uses position
|
||||
const vector3d vel = GetVelocityRelTo(newFrame); // do this first because it uses position
|
||||
const vector3d fpos = m_frame->GetPositionRelTo(newFrame);
|
||||
const matrix3x3d forient = m_frame->GetOrientRelTo(newFrame);
|
||||
SetPosition(forient * GetPosition() + fpos);
|
||||
|
@ -208,7 +217,7 @@ void Body::UpdateFrame()
|
|||
// falling out of frames
|
||||
if (m_frame->GetRadius() < GetPosition().Length()) {
|
||||
Frame *newFrame = GetFrame()->GetParent();
|
||||
if (newFrame) { // don't fall out of root frame
|
||||
if (newFrame) { // don't fall out of root frame
|
||||
Output("%s leaves frame %s\n", GetLabel().c_str(), GetFrame()->GetLabel().c_str());
|
||||
SwitchToFrame(newFrame);
|
||||
return;
|
||||
|
@ -216,7 +225,7 @@ void Body::UpdateFrame()
|
|||
}
|
||||
|
||||
// entering into frames
|
||||
for (Frame* kid : m_frame->GetChildren()) {
|
||||
for (Frame *kid : m_frame->GetChildren()) {
|
||||
const vector3d pos = GetPositionRelTo(kid);
|
||||
if (pos.Length() >= kid->GetRadius()) continue;
|
||||
SwitchToFrame(kid);
|
||||
|
|
40
src/Body.h
40
src/Body.h
|
@ -4,27 +4,29 @@
|
|||
#ifndef _BODY_H
|
||||
#define _BODY_H
|
||||
|
||||
#include "vector3.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "Object.h"
|
||||
#include "Frame.h"
|
||||
#include "Object.h"
|
||||
#include "PropertiedObject.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "vector3.h"
|
||||
#include <string>
|
||||
|
||||
class ObjMesh;
|
||||
class Space;
|
||||
class Camera;
|
||||
namespace Graphics { class Renderer; }
|
||||
namespace Graphics {
|
||||
class Renderer;
|
||||
}
|
||||
struct CollisionContact;
|
||||
|
||||
class Body: public Object, public PropertiedObject {
|
||||
class Body : public Object, public PropertiedObject {
|
||||
public:
|
||||
OBJDEF(Body, Object, BODY);
|
||||
Body();
|
||||
virtual ~Body();
|
||||
void ToJson(Json &jsonObj, Space *space);
|
||||
static Body *FromJson(const Json &jsonObj, Space *space);
|
||||
virtual void PostLoadFixup(Space *space) {};
|
||||
virtual void PostLoadFixup(Space *space){};
|
||||
|
||||
virtual void SetPosition(const vector3d &p) { m_pos = p; }
|
||||
vector3d GetPosition() const { return m_pos; }
|
||||
|
@ -37,14 +39,18 @@ public:
|
|||
double GetPhysRadius() const { return m_physRadius; }
|
||||
void SetClipRadius(double r) { m_clipRadius = r; }
|
||||
double GetClipRadius() const { return m_clipRadius; }
|
||||
virtual double GetMass() const { assert(0); return 0; }
|
||||
virtual double GetMass() const
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return true if to do collision response and apply damage
|
||||
virtual bool OnCollision(Object *o, Uint32 flags, double relVel) { return false; }
|
||||
// Attacker may be null
|
||||
virtual bool OnDamage(Object *attacker, float kgDamage, const CollisionContact& contactData) { return false; }
|
||||
virtual bool OnDamage(Object *attacker, float kgDamage, const CollisionContact &contactData) { return false; }
|
||||
// Override to clear any pointers you hold to the body
|
||||
virtual void NotifyRemoved(const Body* const removedBody) {}
|
||||
virtual void NotifyRemoved(const Body *const removedBody) {}
|
||||
|
||||
// before all bodies have had TimeStepUpdate (their moving step),
|
||||
// StaticUpdate() is called. Good for special collision testing (Projectiles)
|
||||
|
@ -56,7 +62,7 @@ public:
|
|||
virtual void SetFrame(Frame *f) { m_frame = f; }
|
||||
Frame *GetFrame() const { return m_frame; }
|
||||
void SwitchToFrame(Frame *newFrame);
|
||||
void UpdateFrame(); // check for frame switching
|
||||
void UpdateFrame(); // check for frame switching
|
||||
|
||||
vector3d GetVelocityRelTo(const Body *) const;
|
||||
vector3d GetVelocityRelTo(const Frame *) const;
|
||||
|
@ -88,7 +94,8 @@ public:
|
|||
|
||||
// should set m_interpolatedTransform to the smoothly interpolated value
|
||||
// (interpolated by 0 <= alpha <=1) between the previous and current physics tick
|
||||
virtual void UpdateInterpTransform(double alpha) {
|
||||
virtual void UpdateInterpTransform(double alpha)
|
||||
{
|
||||
m_interpOrient = GetOrient();
|
||||
m_interpPos = GetPosition();
|
||||
}
|
||||
|
@ -96,9 +103,9 @@ public:
|
|||
// where to draw targeting indicators - usually equal to GetInterpolatedPositionRelTo
|
||||
virtual vector3d GetTargetIndicatorPosition(const Frame *relTo) const;
|
||||
|
||||
enum { FLAG_CAN_MOVE_FRAME = (1<<0),
|
||||
FLAG_LABEL_HIDDEN = (1<<1),
|
||||
FLAG_DRAW_LAST = (1<<2) }; // causes the body drawn after other bodies in the z-sort
|
||||
enum { FLAG_CAN_MOVE_FRAME = (1 << 0),
|
||||
FLAG_LABEL_HIDDEN = (1 << 1),
|
||||
FLAG_DRAW_LAST = (1 << 2) }; // causes the body drawn after other bodies in the z-sort
|
||||
|
||||
protected:
|
||||
virtual void SaveToJson(Json &jsonObj, Space *space);
|
||||
|
@ -108,12 +115,13 @@ protected:
|
|||
// Interpolated draw orientation-position
|
||||
vector3d m_interpPos;
|
||||
matrix3x3d m_interpOrient;
|
||||
|
||||
private:
|
||||
vector3d m_pos;
|
||||
matrix3x3d m_orient;
|
||||
Frame *m_frame; // frame of reference
|
||||
Frame *m_frame; // frame of reference
|
||||
std::string m_label;
|
||||
bool m_dead; // Checked in destructor to make sure body has been marked dead.
|
||||
bool m_dead; // Checked in destructor to make sure body has been marked dead.
|
||||
double m_clipRadius;
|
||||
double m_physRadius;
|
||||
};
|
||||
|
|
|
@ -4,22 +4,25 @@
|
|||
#ifndef _BYTERANGE_H
|
||||
#define _BYTERANGE_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
struct ByteRange
|
||||
{
|
||||
ByteRange(): begin(0), end(0) {}
|
||||
ByteRange(const char *begin_, const char *end_)
|
||||
: begin(begin_), end(end_)
|
||||
struct ByteRange {
|
||||
ByteRange() :
|
||||
begin(0),
|
||||
end(0) {}
|
||||
ByteRange(const char *begin_, const char *end_) :
|
||||
begin(begin_),
|
||||
end(end_)
|
||||
{
|
||||
assert(begin_ && end_);
|
||||
assert((end_ - begin_) >= 0);
|
||||
}
|
||||
ByteRange(const char *begin_, size_t size)
|
||||
: begin(begin_), end(begin_ + size)
|
||||
ByteRange(const char *begin_, size_t size) :
|
||||
begin(begin_),
|
||||
end(begin_ + size)
|
||||
{
|
||||
assert(begin_);
|
||||
}
|
||||
|
|
|
@ -13,17 +13,18 @@ static Uint32 crc32_reflect(Uint32 v, const int bits)
|
|||
Uint32 r = 0;
|
||||
for (int i = 1; i <= bits; i++) {
|
||||
if (v & 1)
|
||||
r = r | (1<<(bits-i));
|
||||
r = r | (1 << (bits - i));
|
||||
v >>= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
CRC32::CRC32() : m_checksum(0xffffffff)
|
||||
CRC32::CRC32() :
|
||||
m_checksum(0xffffffff)
|
||||
{
|
||||
if (! s_lookupTableGenerated) {
|
||||
if (!s_lookupTableGenerated) {
|
||||
for (int i = 0; i <= 0xff; i++) {
|
||||
s_lookupTable[i] = crc32_reflect(i,8) << 24;
|
||||
s_lookupTable[i] = crc32_reflect(i, 8) << 24;
|
||||
for (int j = 0; j < 8; j++)
|
||||
s_lookupTable[i] = (s_lookupTable[i] << 1) ^ (s_lookupTable[i] & (1 << 31) ? s_polynomial : 0);
|
||||
s_lookupTable[i] = crc32_reflect(s_lookupTable[i], 32);
|
||||
|
|
|
@ -3,18 +3,18 @@
|
|||
|
||||
#include "Camera.h"
|
||||
#include "Frame.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "Space.h"
|
||||
#include "Player.h"
|
||||
#include "Pi.h"
|
||||
#include "Sfx.h"
|
||||
#include "Game.h"
|
||||
#include "Pi.h"
|
||||
#include "Planet.h"
|
||||
#include "Player.h"
|
||||
#include "Sfx.h"
|
||||
#include "Space.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/TextureBuilder.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
|
||||
#include <SDL_stdinc.h>
|
||||
|
||||
|
@ -60,7 +60,7 @@ void CameraContext::BeginFrame()
|
|||
|
||||
// make sure old orient and interpolated orient (rendering orient) are not rubbish
|
||||
m_camFrame->ClearMovement();
|
||||
m_camFrame->UpdateInterpTransform(1.0); // update root-relative pos/orient
|
||||
m_camFrame->UpdateInterpTransform(1.0); // update root-relative pos/orient
|
||||
}
|
||||
|
||||
void CameraContext::EndFrame()
|
||||
|
@ -75,11 +75,10 @@ void CameraContext::EndFrame()
|
|||
|
||||
void CameraContext::ApplyDrawTransforms(Graphics::Renderer *r)
|
||||
{
|
||||
r->SetPerspectiveProjection(m_fovAng, m_width/m_height, m_zNear, m_zFar);
|
||||
r->SetPerspectiveProjection(m_fovAng, m_width / m_height, m_zNear, m_zFar);
|
||||
r->SetTransform(matrix4x4f::Identity());
|
||||
}
|
||||
|
||||
|
||||
Camera::Camera(RefCountedPtr<CameraContext> context, Graphics::Renderer *renderer) :
|
||||
m_context(context),
|
||||
m_renderer(renderer)
|
||||
|
@ -102,7 +101,7 @@ static void position_system_lights(Frame *camFrame, Frame *frame, std::vector<Ca
|
|||
if (body && !frame->IsRotFrame() && (body->GetSuperType() == SystemBody::SUPERTYPE_STAR)) {
|
||||
vector3d lpos = frame->GetPositionRelTo(camFrame);
|
||||
const double dist = lpos.Length() / AU;
|
||||
lpos *= 1.0/dist; // normalize
|
||||
lpos *= 1.0 / dist; // normalize
|
||||
|
||||
const Color &col = StarSystem::starRealColors[body->GetType()];
|
||||
|
||||
|
@ -112,7 +111,7 @@ static void position_system_lights(Frame *camFrame, Frame *frame, std::vector<Ca
|
|||
lights.push_back(Camera::LightSource(frame->GetBody(), light));
|
||||
}
|
||||
|
||||
for (Frame* kid : frame->GetChildren()) {
|
||||
for (Frame *kid : frame->GetChildren()) {
|
||||
position_system_lights(camFrame, kid, lights);
|
||||
}
|
||||
}
|
||||
|
@ -123,13 +122,13 @@ void Camera::Update()
|
|||
|
||||
// evaluate each body and determine if/where/how to draw it
|
||||
m_sortedBodies.clear();
|
||||
for (Body* b : Pi::game->GetSpace()->GetBodies()) {
|
||||
for (Body *b : Pi::game->GetSpace()->GetBodies()) {
|
||||
BodyAttrs attrs;
|
||||
attrs.body = b;
|
||||
attrs.billboard = false; // false by default
|
||||
|
||||
// determine position and transform for draw
|
||||
// Frame::GetFrameTransform(b->GetFrame(), camFrame, attrs.viewTransform); // doesn't use interp coords, so breaks in some cases
|
||||
// Frame::GetFrameTransform(b->GetFrame(), camFrame, attrs.viewTransform); // doesn't use interp coords, so breaks in some cases
|
||||
attrs.viewTransform = b->GetFrame()->GetInterpOrientRelTo(camFrame);
|
||||
attrs.viewTransform.SetTranslate(b->GetFrame()->GetInterpPositionRelTo(camFrame));
|
||||
attrs.viewCoords = attrs.viewTransform * b->GetInterpPosition();
|
||||
|
@ -159,19 +158,17 @@ void Camera::Update()
|
|||
attrs.billboardSize = std::max(1.0f, pixSize);
|
||||
if (b->IsType(Object::STAR)) {
|
||||
attrs.billboardColor = StarSystem::starRealColors[b->GetSystemBody()->GetType()];
|
||||
}
|
||||
else if (b->IsType(Object::PLANET)) {
|
||||
} else if (b->IsType(Object::PLANET)) {
|
||||
// XXX this should incorporate some lighting effect
|
||||
// (ie, colour of the illuminating star(s))
|
||||
attrs.billboardColor = b->GetSystemBody()->GetAlbedo();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
attrs.billboardColor = Color::WHITE;
|
||||
}
|
||||
|
||||
// this should always be the main star in the system - except for the star itself!
|
||||
if( !m_lightSources.empty() && !b->IsType(Object::STAR) ) {
|
||||
const Graphics::Light& light = m_lightSources[0].GetLight();
|
||||
if (!m_lightSources.empty() && !b->IsType(Object::STAR)) {
|
||||
const Graphics::Light &light = m_lightSources[0].GetLight();
|
||||
attrs.billboardColor *= light.GetDiffuse(); // colour the billboard a little with the Starlight
|
||||
}
|
||||
|
||||
|
@ -188,7 +185,7 @@ void Camera::Update()
|
|||
m_sortedBodies.sort();
|
||||
}
|
||||
|
||||
void Camera::Draw(const Body *excludeBody, ShipCockpit* cockpit)
|
||||
void Camera::Draw(const Body *excludeBody, ShipCockpit *cockpit)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
|
||||
|
@ -217,18 +214,16 @@ void Camera::Draw(const Body *excludeBody, ShipCockpit* cockpit)
|
|||
//check if camera is near a planet
|
||||
Body *camParentBody = camFrame->GetParent()->GetBody();
|
||||
if (camParentBody && camParentBody->IsType(Object::PLANET)) {
|
||||
Planet *planet = static_cast<Planet*>(camParentBody);
|
||||
Planet *planet = static_cast<Planet *>(camParentBody);
|
||||
const vector3f relpos(planet->GetInterpPositionRelTo(camFrame));
|
||||
double altitude(relpos.Length());
|
||||
double pressure, density;
|
||||
planet->GetAtmosphericState(altitude, &pressure, &density);
|
||||
if (pressure >= 0.001)
|
||||
{
|
||||
if (pressure >= 0.001) {
|
||||
//go through all lights to calculate something resembling light intensity
|
||||
float intensity = 0.f;
|
||||
const Player* pBody = Pi::game->GetPlayer();
|
||||
for( Uint32 i=0; i<m_lightSources.size() ; i++ )
|
||||
{
|
||||
const Player *pBody = Pi::game->GetPlayer();
|
||||
for (Uint32 i = 0; i < m_lightSources.size(); i++) {
|
||||
// Set up data for eclipses. All bodies are assumed to be spheres.
|
||||
const LightSource &it = m_lightSources[i];
|
||||
const vector3f lightDir(it.GetLight().GetPosition().Normalized());
|
||||
|
@ -266,8 +261,7 @@ void Camera::Draw(const Body *excludeBody, ShipCockpit* cockpit)
|
|||
m_renderer->SetTransform(matrix4x4d::Identity());
|
||||
m_billboardMaterial->diffuse = attrs->billboardColor;
|
||||
m_renderer->DrawPointSprites(1, &attrs->billboardPos, SfxManager::additiveAlphaState, m_billboardMaterial.get(), attrs->billboardSize);
|
||||
}
|
||||
else
|
||||
} else
|
||||
attrs->body->Render(m_renderer, this, attrs->viewCoords, attrs->viewTransform);
|
||||
}
|
||||
|
||||
|
@ -279,11 +273,12 @@ void Camera::Draw(const Body *excludeBody, ShipCockpit* cockpit)
|
|||
// Render cockpit
|
||||
// XXX only here because it needs a frame for lighting calc
|
||||
// should really be in WorldView, immediately after camera draw
|
||||
if(cockpit)
|
||||
if (cockpit)
|
||||
cockpit->RenderCockpit(m_renderer, this, camFrame);
|
||||
}
|
||||
|
||||
void Camera::CalcShadows(const int lightNum, const Body *b, std::vector<Shadow> &shadowsOut) const {
|
||||
void Camera::CalcShadows(const int lightNum, const Body *b, std::vector<Shadow> &shadowsOut) const
|
||||
{
|
||||
// Set up data for eclipses. All bodies are assumed to be spheres.
|
||||
const Body *lightBody = m_lightSources[lightNum].GetBody();
|
||||
if (!lightBody)
|
||||
|
@ -294,19 +289,21 @@ void Camera::CalcShadows(const int lightNum, const Body *b, std::vector<Shadow>
|
|||
const vector3d lightDir = bLightPos.Normalized();
|
||||
|
||||
double bRadius;
|
||||
if (b->IsType(Object::TERRAINBODY)) bRadius = b->GetSystemBody()->GetRadius();
|
||||
else bRadius = b->GetPhysRadius();
|
||||
if (b->IsType(Object::TERRAINBODY))
|
||||
bRadius = b->GetSystemBody()->GetRadius();
|
||||
else
|
||||
bRadius = b->GetPhysRadius();
|
||||
|
||||
// Look for eclipsing third bodies:
|
||||
for (const Body *b2 : Pi::game->GetSpace()->GetBodies()) {
|
||||
if ( b2 == b || b2 == lightBody || !(b2->IsType(Object::PLANET) || b2->IsType(Object::STAR)))
|
||||
if (b2 == b || b2 == lightBody || !(b2->IsType(Object::PLANET) || b2->IsType(Object::STAR)))
|
||||
continue;
|
||||
|
||||
double b2Radius = b2->GetSystemBody()->GetRadius();
|
||||
vector3d b2pos = b2->GetPositionRelTo(b);
|
||||
const double perpDist = lightDir.Dot(b2pos);
|
||||
|
||||
if ( perpDist <= 0 || perpDist > bLightPos.Length())
|
||||
if (perpDist <= 0 || perpDist > bLightPos.Length())
|
||||
// b2 isn't between b and lightBody; no eclipse
|
||||
continue;
|
||||
|
||||
|
@ -320,12 +317,12 @@ void Camera::CalcShadows(const int lightNum, const Body *b, std::vector<Shadow>
|
|||
// disc of radius srad centred at projectedCentre-p. To determine the light intensity at p, we
|
||||
// then just need to estimate the proportion of the light disc being occulted.
|
||||
const double srad = b2Radius / bRadius;
|
||||
const double lrad = (lightRadius/bLightPos.Length())*perpDist / bRadius;
|
||||
const double lrad = (lightRadius / bLightPos.Length()) * perpDist / bRadius;
|
||||
if (srad / lrad < 0.01) {
|
||||
// any eclipse would have negligible effect - ignore
|
||||
continue;
|
||||
}
|
||||
const vector3d projectedCentre = ( b2pos - perpDist*lightDir ) / bRadius;
|
||||
const vector3d projectedCentre = (b2pos - perpDist * lightDir) / bRadius;
|
||||
if (projectedCentre.Length() < 1 + srad + lrad) {
|
||||
// some part of b is (partially) eclipsed
|
||||
Camera::Shadow shadow = { projectedCentre, static_cast<float>(srad), static_cast<float>(lrad) };
|
||||
|
@ -334,7 +331,8 @@ void Camera::CalcShadows(const int lightNum, const Body *b, std::vector<Shadow>
|
|||
}
|
||||
}
|
||||
|
||||
float discCovered(const float dist, const float rad) {
|
||||
float discCovered(const float dist, const float rad)
|
||||
{
|
||||
// proportion of unit disc covered by a second disc of radius rad placed
|
||||
// dist from centre of first disc.
|
||||
//
|
||||
|
@ -343,10 +341,10 @@ float discCovered(const float dist, const float rad) {
|
|||
// xs = normalised leftwards distance from centre of second disc to intersection.
|
||||
// d = vertical distance to an intersection point
|
||||
// The clampings handle the cases where one disc contains the other.
|
||||
const float radsq = rad*rad;
|
||||
const float xl = Clamp((dist*dist + 1.f - radsq) / (2.f*std::max(0.001f,dist)), -1.f, 1.f);
|
||||
const float xs = Clamp((dist - xl)/std::max(0.001f,rad), -1.f, 1.f);
|
||||
const float d = sqrt(std::max(0.f, 1.f - xl*xl));
|
||||
const float radsq = rad * rad;
|
||||
const float xl = Clamp((dist * dist + 1.f - radsq) / (2.f * std::max(0.001f, dist)), -1.f, 1.f);
|
||||
const float xs = Clamp((dist - xl) / std::max(0.001f, rad), -1.f, 1.f);
|
||||
const float d = sqrt(std::max(0.f, 1.f - xl * xl));
|
||||
|
||||
const float th = Clamp(acosf(xl), 0.f, float(M_PI));
|
||||
const float th2 = Clamp(acosf(xs), 0.f, float(M_PI));
|
||||
|
@ -355,23 +353,25 @@ float discCovered(const float dist, const float rad) {
|
|||
|
||||
// covered area can be calculated as the sum of segments from the two
|
||||
// discs plus/minus some triangles, and it works out as follows:
|
||||
return Clamp((th + radsq*th2 - dist*d)/float(M_PI), 0.f, 1.f);
|
||||
return Clamp((th + radsq * th2 - dist * d) / float(M_PI), 0.f, 1.f);
|
||||
}
|
||||
|
||||
static std::vector<Camera::Shadow> shadows;
|
||||
|
||||
float Camera::ShadowedIntensity(const int lightNum, const Body *b) const {
|
||||
float Camera::ShadowedIntensity(const int lightNum, const Body *b) const
|
||||
{
|
||||
shadows.clear();
|
||||
shadows.reserve(16);
|
||||
CalcShadows(lightNum, b, shadows);
|
||||
float product = 1.0;
|
||||
for (std::vector<Camera::Shadow>::const_iterator it = shadows.begin(), itEnd = shadows.end(); it!=itEnd; ++it)
|
||||
for (std::vector<Camera::Shadow>::const_iterator it = shadows.begin(), itEnd = shadows.end(); it != itEnd; ++it)
|
||||
product *= 1.0 - discCovered(it->centre.Length() / it->lrad, it->srad / it->lrad);
|
||||
return product;
|
||||
}
|
||||
|
||||
// PrincipalShadows(b,n): returns the n biggest shadows on b in order of size
|
||||
void Camera::PrincipalShadows(const Body *b, const int n, std::vector<Shadow> &shadowsOut) const {
|
||||
void Camera::PrincipalShadows(const Body *b, const int n, std::vector<Shadow> &shadowsOut) const
|
||||
{
|
||||
shadows.clear();
|
||||
shadows.reserve(16);
|
||||
for (size_t i = 0; i < 4 && i < m_lightSources.size(); i++) {
|
||||
|
|
38
src/Camera.h
38
src/Camera.h
|
@ -4,17 +4,19 @@
|
|||
#ifndef _CAMERA_H
|
||||
#define _CAMERA_H
|
||||
|
||||
#include "graphics/Frustum.h"
|
||||
#include "graphics/Light.h"
|
||||
#include "RefCounted.h"
|
||||
#include "vector3.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "Background.h"
|
||||
#include "Body.h"
|
||||
#include "RefCounted.h"
|
||||
#include "graphics/Frustum.h"
|
||||
#include "graphics/Light.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "vector3.h"
|
||||
|
||||
class Frame;
|
||||
class ShipCockpit;
|
||||
namespace Graphics { class Renderer; }
|
||||
namespace Graphics {
|
||||
class Renderer;
|
||||
}
|
||||
|
||||
class CameraContext : public RefCounted {
|
||||
public:
|
||||
|
@ -22,11 +24,11 @@ public:
|
|||
CameraContext(float width, float height, float fovAng, float zNear, float zFar);
|
||||
~CameraContext();
|
||||
|
||||
float GetWidth() const { return m_width; }
|
||||
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; }
|
||||
float GetZNear() const { return m_zNear; }
|
||||
float GetZFar() const { return m_zFar; }
|
||||
|
||||
// frame to position the camera relative to
|
||||
void SetFrame(Frame *frame) { m_frame = frame; }
|
||||
|
@ -45,7 +47,11 @@ public:
|
|||
void EndFrame();
|
||||
|
||||
// valid between BeginFrame and EndFrame
|
||||
Frame *GetCamFrame() const { assert(m_camFrame); return m_camFrame; }
|
||||
Frame *GetCamFrame() const
|
||||
{
|
||||
assert(m_camFrame);
|
||||
return m_camFrame;
|
||||
}
|
||||
|
||||
// apply projection and modelview transforms to the renderer
|
||||
void ApplyDrawTransforms(Graphics::Renderer *r);
|
||||
|
@ -66,7 +72,6 @@ private:
|
|||
Frame *m_camFrame;
|
||||
};
|
||||
|
||||
|
||||
class Camera {
|
||||
public:
|
||||
Camera(RefCountedPtr<CameraContext> context, Graphics::Renderer *renderer);
|
||||
|
@ -74,12 +79,14 @@ public:
|
|||
const CameraContext *GetContext() const { return m_context.Get(); }
|
||||
|
||||
void Update();
|
||||
void Draw(const Body *excludeBody = nullptr, ShipCockpit* cockpit = nullptr);
|
||||
void Draw(const Body *excludeBody = nullptr, ShipCockpit *cockpit = nullptr);
|
||||
|
||||
// camera-specific light with attached source body
|
||||
class LightSource {
|
||||
public:
|
||||
LightSource(const Body *b, Graphics::Light &light) : m_body(b), m_light(light) {}
|
||||
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; }
|
||||
|
@ -94,7 +101,7 @@ public:
|
|||
float srad;
|
||||
float lrad;
|
||||
|
||||
bool operator< (const Shadow& other) const { return srad/lrad < other.srad/other.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;
|
||||
|
@ -132,7 +139,8 @@ private:
|
|||
Color billboardColor;
|
||||
|
||||
// for sorting. "should a be drawn before b?"
|
||||
friend bool operator<(const BodyAttrs &a, const BodyAttrs &b) {
|
||||
friend bool operator<(const BodyAttrs &a, const BodyAttrs &b)
|
||||
{
|
||||
// both drawing last; distance order
|
||||
if (a.bodyFlags & Body::FLAG_DRAW_LAST && b.bodyFlags & Body::FLAG_DRAW_LAST)
|
||||
return a.camDist > b.camDist;
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "CameraController.h"
|
||||
#include "Ship.h"
|
||||
#include "AnimationCurves.h"
|
||||
#include "Pi.h"
|
||||
#include "Game.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "MathUtil.h"
|
||||
#include "Pi.h"
|
||||
#include "Ship.h"
|
||||
|
||||
CameraController::CameraController(RefCountedPtr<CameraContext> camera, const Ship *ship) :
|
||||
m_camera(camera),
|
||||
m_ship(ship),
|
||||
m_pos(0.0),
|
||||
m_orient(matrix3x3d::Identity())
|
||||
m_camera(camera),
|
||||
m_ship(ship),
|
||||
m_pos(0.0),
|
||||
m_orient(matrix3x3d::Identity())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -39,9 +39,8 @@ void CameraController::Update()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
InternalCameraController::InternalCameraController(RefCountedPtr<CameraContext> camera, const Ship *ship)
|
||||
: MoveableCameraController(camera, ship),
|
||||
InternalCameraController::InternalCameraController(RefCountedPtr<CameraContext> camera, const Ship *ship) :
|
||||
MoveableCameraController(camera, ship),
|
||||
m_mode(MODE_FRONT),
|
||||
m_rotX(0),
|
||||
m_rotY(0),
|
||||
|
@ -56,12 +55,9 @@ static bool FillCameraPosOrient(const SceneGraph::Model *m, const char *tag, vec
|
|||
matrix3x3d fixOrient(matrix3x3d::Identity());
|
||||
|
||||
const SceneGraph::MatrixTransform *mt = m->FindTagByName(tag);
|
||||
if (!mt)
|
||||
{
|
||||
if (!mt) {
|
||||
fixOrient = fallbackOrient;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// camera points are have +Z pointing out of the ship, X left, so we
|
||||
// have to rotate 180 about Y to get them to -Z forward, X right like
|
||||
// the rest of the ship. this is not a bug, but rather a convenience to
|
||||
|
@ -113,7 +109,8 @@ void InternalCameraController::Update()
|
|||
CameraController::Update();
|
||||
}
|
||||
|
||||
void InternalCameraController::getRots(double &rX, double &rY) {
|
||||
void InternalCameraController::getRots(double &rX, double &rY)
|
||||
{
|
||||
rX = DEG2RAD(m_rotX);
|
||||
rY = DEG2RAD(m_rotY);
|
||||
}
|
||||
|
@ -191,18 +188,18 @@ void InternalCameraController::LoadFromJson(const Json &jsonObj)
|
|||
try {
|
||||
Json internalCameraObj = jsonObj["internal"];
|
||||
SetMode(internalCameraObj["mode"].get<Mode>());
|
||||
}
|
||||
catch (Json::type_error &) {
|
||||
} catch (Json::type_error &) {
|
||||
throw SavedGameCorruptException();
|
||||
}
|
||||
}
|
||||
|
||||
ExternalCameraController::ExternalCameraController(RefCountedPtr<CameraContext> camera, const Ship *ship) :
|
||||
MoveableCameraController(camera, ship),
|
||||
m_dist(200), m_distTo(m_dist),
|
||||
m_rotX(0),
|
||||
m_rotY(0),
|
||||
m_extOrient(matrix3x3d::Identity())
|
||||
MoveableCameraController(camera, ship),
|
||||
m_dist(200),
|
||||
m_distTo(m_dist),
|
||||
m_rotX(0),
|
||||
m_rotY(0),
|
||||
m_extOrient(matrix3x3d::Identity())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -307,9 +304,10 @@ void ExternalCameraController::LoadFromJson(const Json &jsonObj)
|
|||
}
|
||||
|
||||
SiderealCameraController::SiderealCameraController(RefCountedPtr<CameraContext> camera, const Ship *ship) :
|
||||
MoveableCameraController(camera, ship),
|
||||
m_dist(200), m_distTo(m_dist),
|
||||
m_sidOrient(matrix3x3d::Identity())
|
||||
MoveableCameraController(camera, ship),
|
||||
m_dist(200),
|
||||
m_distTo(m_dist),
|
||||
m_sidOrient(matrix3x3d::Identity())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -357,7 +355,7 @@ void SiderealCameraController::ZoomEvent(float amount)
|
|||
|
||||
void SiderealCameraController::ZoomEventUpdate(float frameTime)
|
||||
{
|
||||
AnimationCurves::Approach(m_dist, m_distTo, frameTime, 4.0, 50. / std::max(m_distTo, 1e-7)); // std::max() here just avoid dividing by 0.
|
||||
AnimationCurves::Approach(m_dist, m_distTo, frameTime, 4.0, 50. / std::max(m_distTo, 1e-7)); // std::max() here just avoid dividing by 0.
|
||||
m_dist = std::max(GetShip()->GetClipRadius(), m_dist);
|
||||
}
|
||||
|
||||
|
@ -383,7 +381,7 @@ void SiderealCameraController::Update()
|
|||
{
|
||||
const Ship *ship = GetShip();
|
||||
|
||||
m_sidOrient.Renormalize(); // lots of small rotations
|
||||
m_sidOrient.Renormalize(); // lots of small rotations
|
||||
matrix3x3d shipOrient = ship->GetInterpOrientRelTo(Pi::game->GetSpace()->GetRootFrame());
|
||||
|
||||
SetPosition(shipOrient.Transpose() * m_sidOrient.VectorZ() * m_dist);
|
||||
|
@ -417,10 +415,11 @@ void SiderealCameraController::LoadFromJson(const Json &jsonObj)
|
|||
}
|
||||
|
||||
FlyByCameraController::FlyByCameraController(RefCountedPtr<CameraContext> camera, const Ship *ship) :
|
||||
MoveableCameraController(camera, ship),
|
||||
m_dist(500), m_distTo(m_dist),
|
||||
m_roll(0),
|
||||
m_flybyOrient(matrix3x3d::Identity())
|
||||
MoveableCameraController(camera, ship),
|
||||
m_dist(500),
|
||||
m_distTo(m_dist),
|
||||
m_roll(0),
|
||||
m_flybyOrient(matrix3x3d::Identity())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -444,7 +443,7 @@ void FlyByCameraController::ZoomEvent(float amount)
|
|||
|
||||
void FlyByCameraController::ZoomEventUpdate(float frameTime)
|
||||
{
|
||||
AnimationCurves::Approach(m_dist, m_distTo, frameTime, 4.0, 50. / std::max(m_distTo, 1e-7)); // std::max() here just avoid dividing by 0.
|
||||
AnimationCurves::Approach(m_dist, m_distTo, frameTime, 4.0, 50. / std::max(m_distTo, 1e-7)); // std::max() here just avoid dividing by 0.
|
||||
m_dist = std::max(GetShip()->GetClipRadius(), m_dist);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,16 +4,15 @@
|
|||
#ifndef CAMERACONTROLLER_H
|
||||
#define CAMERACONTROLLER_H
|
||||
|
||||
#include "vector3.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "Lang.h"
|
||||
#include "Camera.h"
|
||||
#include "JsonFwd.h"
|
||||
#include "Lang.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "vector3.h"
|
||||
|
||||
class Ship;
|
||||
|
||||
class CameraController
|
||||
{
|
||||
class CameraController {
|
||||
public:
|
||||
enum Type { //can be used for serialization & identification
|
||||
INTERNAL,
|
||||
|
@ -29,8 +28,8 @@ public:
|
|||
|
||||
virtual Type GetType() const = 0;
|
||||
virtual const char *GetName() const { return ""; }
|
||||
virtual void SaveToJson(Json &jsonObj) { }
|
||||
virtual void LoadFromJson(const Json &jsonObj) { }
|
||||
virtual void SaveToJson(Json &jsonObj) {}
|
||||
virtual void LoadFromJson(const Json &jsonObj) {}
|
||||
virtual bool IsExternal() const { return false; }
|
||||
|
||||
// camera position relative to the body
|
||||
|
@ -56,23 +55,23 @@ class MoveableCameraController : public CameraController {
|
|||
public:
|
||||
MoveableCameraController(RefCountedPtr<CameraContext> camera, const Ship *ship) :
|
||||
CameraController(camera, ship) {}
|
||||
virtual void Reset() { }
|
||||
virtual void Reset() {}
|
||||
|
||||
virtual void RollLeft(float frameTime) { }
|
||||
virtual void RollRight(float frameTime) { }
|
||||
virtual void RotateDown(float frameTime) { }
|
||||
virtual void RotateLeft(float frameTime) { }
|
||||
virtual void RotateRight(float frameTime) { }
|
||||
virtual void RotateUp(float frameTime) { }
|
||||
virtual void RollLeft(float frameTime) {}
|
||||
virtual void RollRight(float frameTime) {}
|
||||
virtual void RotateDown(float frameTime) {}
|
||||
virtual void RotateLeft(float frameTime) {}
|
||||
virtual void RotateRight(float frameTime) {}
|
||||
virtual void RotateUp(float frameTime) {}
|
||||
/// Zooming with this method will interrupt any animation launched by ZoomEvent().
|
||||
virtual void ZoomIn(float frameTime) { }
|
||||
virtual void ZoomIn(float frameTime) {}
|
||||
/// Zooming with this method will interrupt any animation launched by ZoomEvent().
|
||||
virtual void ZoomOut(float frameTime) { }
|
||||
virtual void ZoomOut(float frameTime) {}
|
||||
/// Animated zoom trigger (on each event), primarily designed for mouse wheel.
|
||||
///\param amount The zoom delta to add or substract (>0: zoom out, <0: zoom in), indirectly controling the zoom animation speed.
|
||||
virtual void ZoomEvent(float amount) { }
|
||||
virtual void ZoomEvent(float amount) {}
|
||||
/// Animated zoom update (on each frame), primarily designed for mouse wheel.
|
||||
virtual void ZoomEventUpdate(float frameTime) { }
|
||||
virtual void ZoomEventUpdate(float frameTime) {}
|
||||
};
|
||||
|
||||
class InternalCameraController : public MoveableCameraController {
|
||||
|
@ -88,7 +87,7 @@ public:
|
|||
|
||||
InternalCameraController(RefCountedPtr<CameraContext> camera, const Ship *ship);
|
||||
virtual void Reset();
|
||||
virtual void Update();
|
||||
virtual void Update();
|
||||
|
||||
Type GetType() const { return INTERNAL; }
|
||||
const char *GetName() const { return m_name; }
|
||||
|
@ -102,18 +101,24 @@ public:
|
|||
void RotateRight(float frameTime);
|
||||
void RotateUp(float frameTime);
|
||||
|
||||
void getRots(double &rotX, double &rotY);
|
||||
void getRots(double &rotX, double &rotY);
|
||||
|
||||
private:
|
||||
private:
|
||||
Mode m_mode;
|
||||
const char *m_name;
|
||||
|
||||
vector3d m_frontPos; matrix3x3d m_frontOrient;
|
||||
vector3d m_rearPos; matrix3x3d m_rearOrient;
|
||||
vector3d m_leftPos; matrix3x3d m_leftOrient;
|
||||
vector3d m_rightPos; matrix3x3d m_rightOrient;
|
||||
vector3d m_topPos; matrix3x3d m_topOrient;
|
||||
vector3d m_bottomPos; matrix3x3d m_bottomOrient;
|
||||
vector3d m_frontPos;
|
||||
matrix3x3d m_frontOrient;
|
||||
vector3d m_rearPos;
|
||||
matrix3x3d m_rearOrient;
|
||||
vector3d m_leftPos;
|
||||
matrix3x3d m_leftOrient;
|
||||
vector3d m_rightPos;
|
||||
matrix3x3d m_rightOrient;
|
||||
vector3d m_topPos;
|
||||
matrix3x3d m_topOrient;
|
||||
vector3d m_bottomPos;
|
||||
matrix3x3d m_bottomOrient;
|
||||
|
||||
double m_rotX; //vertical rot
|
||||
double m_rotY; //horizontal rot
|
||||
|
@ -139,7 +144,8 @@ public:
|
|||
void ZoomEventUpdate(float frameTime);
|
||||
void Reset();
|
||||
bool IsExternal() const { return true; }
|
||||
void SetRotationAngles(double x, double y) {
|
||||
void SetRotationAngles(double x, double y)
|
||||
{
|
||||
m_rotX = x;
|
||||
m_rotY = y;
|
||||
}
|
||||
|
@ -156,7 +162,6 @@ private:
|
|||
matrix3x3d m_extOrient;
|
||||
};
|
||||
|
||||
|
||||
// Much like external camera, but does not turn when the ship turns
|
||||
class SiderealCameraController : public MoveableCameraController {
|
||||
public:
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "Ship.h"
|
||||
#include "CargoBody.h"
|
||||
#include "EnumStrings.h"
|
||||
#include "Game.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "LuaTable.h"
|
||||
#include "Pi.h"
|
||||
#include "Sfx.h"
|
||||
#include "Ship.h"
|
||||
#include "Space.h"
|
||||
#include "EnumStrings.h"
|
||||
#include "LuaTable.h"
|
||||
#include "collider/collider.h"
|
||||
#include "scenegraph/SceneGraph.h"
|
||||
#include "scenegraph/ModelSkin.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "scenegraph/SceneGraph.h"
|
||||
|
||||
void CargoBody::SaveToJson(Json &jsonObj, Space *space)
|
||||
{
|
||||
|
@ -69,7 +69,8 @@ void CargoBody::Init()
|
|||
Properties().Set("type", cargoname);
|
||||
}
|
||||
|
||||
CargoBody::CargoBody(const LuaRef& cargo, float selfdestructTimer): m_cargo(cargo)
|
||||
CargoBody::CargoBody(const LuaRef &cargo, float selfdestructTimer) :
|
||||
m_cargo(cargo)
|
||||
{
|
||||
SetModel("cargo");
|
||||
Init();
|
||||
|
@ -91,7 +92,7 @@ void CargoBody::TimeStepUpdate(const float timeStep)
|
|||
|
||||
if (m_hasSelfdestruct) {
|
||||
m_selfdestructTimer -= timeStep;
|
||||
if (m_selfdestructTimer <= 0){
|
||||
if (m_selfdestructTimer <= 0) {
|
||||
Pi::game->GetSpace()->KillBody(this);
|
||||
SfxManager::Add(this, TYPE_EXPLOSION);
|
||||
}
|
||||
|
@ -99,9 +100,9 @@ void CargoBody::TimeStepUpdate(const float timeStep)
|
|||
DynamicBody::TimeStepUpdate(timeStep);
|
||||
}
|
||||
|
||||
bool CargoBody::OnDamage(Object *attacker, float kgDamage, const CollisionContact& contactData)
|
||||
bool CargoBody::OnDamage(Object *attacker, float kgDamage, const CollisionContact &contactData)
|
||||
{
|
||||
m_hitpoints -= kgDamage*0.001f;
|
||||
m_hitpoints -= kgDamage * 0.001f;
|
||||
if (m_hitpoints < 0) {
|
||||
Pi::game->GetSpace()->KillBody(this);
|
||||
SfxManager::Add(this, TYPE_EXPLOSION);
|
||||
|
@ -114,7 +115,7 @@ bool CargoBody::OnCollision(Object *b, Uint32 flags, double relVel)
|
|||
// ignore collision if its about to be scooped
|
||||
if (b->IsType(Object::SHIP)) {
|
||||
int cargoscoop_cap = 0;
|
||||
static_cast<Ship*>(b)->Properties().Get("cargo_scoop_cap", cargoscoop_cap);
|
||||
static_cast<Ship *>(b)->Properties().Get("cargo_scoop_cap", cargoscoop_cap);
|
||||
if (cargoscoop_cap > 0)
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -4,26 +4,30 @@
|
|||
#ifndef _CARGOBODY_H
|
||||
#define _CARGOBODY_H
|
||||
|
||||
#include "libs.h"
|
||||
#include "DynamicBody.h"
|
||||
#include "LuaRef.h"
|
||||
#include "libs.h"
|
||||
|
||||
namespace Graphics { class Renderer; }
|
||||
namespace Graphics {
|
||||
class Renderer;
|
||||
}
|
||||
|
||||
class CargoBody: public DynamicBody {
|
||||
class CargoBody : public DynamicBody {
|
||||
public:
|
||||
OBJDEF(CargoBody, DynamicBody, CARGOBODY);
|
||||
CargoBody(const LuaRef& cargo, float selfdestructTimer=86400.0f); // default to 24 h lifetime
|
||||
CargoBody(const LuaRef &cargo, float selfdestructTimer = 86400.0f); // default to 24 h lifetime
|
||||
CargoBody() {}
|
||||
LuaRef GetCargoType() const { return m_cargo; }
|
||||
virtual void SetLabel(const std::string &label) override;
|
||||
virtual void Render(Graphics::Renderer *r, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform) override;
|
||||
virtual void TimeStepUpdate(const float timeStep) override;
|
||||
virtual bool OnCollision(Object *o, Uint32 flags, double relVel) override;
|
||||
virtual bool OnDamage(Object *attacker, float kgDamage, const CollisionContact& contactData) override;
|
||||
virtual bool OnDamage(Object *attacker, float kgDamage, const CollisionContact &contactData) override;
|
||||
|
||||
protected:
|
||||
virtual void SaveToJson(Json &jsonObj, Space *space) override;
|
||||
virtual void LoadFromJson(const Json &jsonObj, Space *space) override;
|
||||
|
||||
private:
|
||||
void Init();
|
||||
LuaRef m_cargo;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "CityOnPlanet.h"
|
||||
#include "FileSystem.h"
|
||||
#include "Frame.h"
|
||||
|
@ -13,21 +12,26 @@
|
|||
#include "graphics/Frustum.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Stats.h"
|
||||
#include "libs.h"
|
||||
#include "scenegraph/Model.h"
|
||||
#include "scenegraph/SceneGraph.h"
|
||||
#include "scenegraph/ModelSkin.h"
|
||||
#include "scenegraph/SceneGraph.h"
|
||||
#include <set>
|
||||
|
||||
static const unsigned int DEFAULT_NUM_BUILDINGS = 1000;
|
||||
static const double START_SEG_SIZE = CITY_ON_PLANET_RADIUS;
|
||||
static const double START_SEG_SIZE_NO_ATMO = CITY_ON_PLANET_RADIUS / 5.0f;
|
||||
static const double START_SEG_SIZE = CITY_ON_PLANET_RADIUS;
|
||||
static const double START_SEG_SIZE_NO_ATMO = CITY_ON_PLANET_RADIUS / 5.0f;
|
||||
|
||||
using SceneGraph::Model;
|
||||
|
||||
CityOnPlanet::citybuildinglist_t CityOnPlanet::s_buildingList =
|
||||
{
|
||||
"city_building", 800, 2000, 0, 0,
|
||||
};
|
||||
{
|
||||
"city_building",
|
||||
800,
|
||||
2000,
|
||||
0,
|
||||
0,
|
||||
};
|
||||
|
||||
CityOnPlanet::cityflavourdef_t CityOnPlanet::cityflavour[CITYFLAVOURS];
|
||||
|
||||
|
@ -36,30 +40,31 @@ void CityOnPlanet::AddStaticGeomsToCollisionSpace()
|
|||
// reset data structures
|
||||
m_enabledBuildings.clear();
|
||||
m_buildingCounts.resize(s_buildingList.numBuildings);
|
||||
for(Uint32 i=0; i<s_buildingList.numBuildings; i++) {
|
||||
for (Uint32 i = 0; i < s_buildingList.numBuildings; i++) {
|
||||
m_buildingCounts[i] = 0;
|
||||
}
|
||||
|
||||
// Generate the new building list
|
||||
int skipMask;
|
||||
switch (Pi::detail.cities) {
|
||||
case 0: skipMask = 0xf; break;
|
||||
case 1: skipMask = 0x7; break;
|
||||
case 2: skipMask = 0x3; break;
|
||||
case 3: skipMask = 0x1; break;
|
||||
default:
|
||||
skipMask = 0; break;
|
||||
case 0: skipMask = 0xf; break;
|
||||
case 1: skipMask = 0x7; break;
|
||||
case 2: skipMask = 0x3; break;
|
||||
case 3: skipMask = 0x1; break;
|
||||
default:
|
||||
skipMask = 0;
|
||||
break;
|
||||
}
|
||||
Uint32 numVisibleBuildings = 0;
|
||||
for (unsigned int i=0; i<m_buildings.size(); i++) {
|
||||
if (!(i&skipMask)) {
|
||||
for (unsigned int i = 0; i < m_buildings.size(); i++) {
|
||||
if (!(i & skipMask)) {
|
||||
++numVisibleBuildings;
|
||||
}
|
||||
}
|
||||
|
||||
// we know how many building we'll be adding, reserve space up front
|
||||
m_enabledBuildings.reserve(numVisibleBuildings);
|
||||
for (unsigned int i=0; i<m_buildings.size(); i++) {
|
||||
for (unsigned int i = 0; i < m_buildings.size(); i++) {
|
||||
if (i & skipMask) {
|
||||
} else {
|
||||
m_frame->AddStaticGeom(m_buildings[i].geom);
|
||||
|
@ -76,7 +81,7 @@ void CityOnPlanet::AddStaticGeomsToCollisionSpace()
|
|||
void CityOnPlanet::RemoveStaticGeomsFromCollisionSpace()
|
||||
{
|
||||
m_enabledBuildings.clear();
|
||||
for (unsigned int i=0; i<m_buildings.size(); i++) {
|
||||
for (unsigned int i = 0; i < m_buildings.size(); i++) {
|
||||
m_frame->RemoveStaticGeom(m_buildings[i].geom);
|
||||
}
|
||||
}
|
||||
|
@ -90,9 +95,9 @@ void CityOnPlanet::EnumerateNewBuildings(std::set<std::string> &filenames)
|
|||
for (FileSystem::FileEnumerator files(FileSystem::gameDataFiles, fullpath, FileSystem::FileEnumerator::Recurse); !files.Finished(); files.Next()) {
|
||||
const std::string &name = files.Current().GetName();
|
||||
if (ends_with_ci(name, ".model")) {
|
||||
filenames.insert(name.substr(0, name.length()-6));
|
||||
filenames.insert(name.substr(0, name.length() - 6));
|
||||
} else if (ends_with_ci(name, ".sgm")) {
|
||||
filenames.insert(name.substr(0, name.length()-4));
|
||||
filenames.insert(name.substr(0, name.length() - 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,14 +105,13 @@ void CityOnPlanet::EnumerateNewBuildings(std::set<std::string> &filenames)
|
|||
//static
|
||||
void CityOnPlanet::LookupBuildingListModels(citybuildinglist_t *list)
|
||||
{
|
||||
std::vector<Model*> models;
|
||||
std::vector<Model *> models;
|
||||
|
||||
//get test newmodels - to be replaced with building set definitions
|
||||
{
|
||||
std::set<std::string> filenames; // set so we get unique names
|
||||
EnumerateNewBuildings(filenames);
|
||||
for(auto it = filenames.begin(), itEnd = filenames.end(); it != itEnd; ++it)
|
||||
{
|
||||
for (auto it = filenames.begin(), itEnd = filenames.end(); it != itEnd; ++it) {
|
||||
// find/load the model
|
||||
Model *model = Pi::modelCache->FindModel(*it);
|
||||
|
||||
|
@ -129,7 +133,7 @@ void CityOnPlanet::LookupBuildingListModels(citybuildinglist_t *list)
|
|||
const Aabb &aabb = list->buildings[i].collMesh->GetAabb();
|
||||
const double maxx = std::max(fabs(aabb.max.x), fabs(aabb.min.x));
|
||||
const double maxy = std::max(fabs(aabb.max.z), fabs(aabb.min.z));
|
||||
list->buildings[i].xzradius = sqrt(maxx*maxx + maxy*maxy);
|
||||
list->buildings[i].xzradius = sqrt(maxx * maxx + maxy * maxy);
|
||||
Output(" - %s: %f\n", (*m)->GetName().c_str(), list->buildings[i].xzradius);
|
||||
}
|
||||
Output("End of buildings.\n");
|
||||
|
@ -147,11 +151,12 @@ void CityOnPlanet::Uninit()
|
|||
}
|
||||
|
||||
// Need a reliable way to sort the models rather than using their address in memory we use their name which should be unique.
|
||||
bool setcomp (SceneGraph::Model *mlhs, SceneGraph::Model *mrhs) {return mlhs->GetName()<mrhs->GetName();}
|
||||
bool(*fn_pt)(SceneGraph::Model *mlhs, SceneGraph::Model *mrhs) = setcomp;
|
||||
bool setcomp(SceneGraph::Model *mlhs, SceneGraph::Model *mrhs) { return mlhs->GetName() < mrhs->GetName(); }
|
||||
bool (*fn_pt)(SceneGraph::Model *mlhs, SceneGraph::Model *mrhs) = setcomp;
|
||||
|
||||
struct ModelNameComparator {
|
||||
bool operator()(SceneGraph::Model* lhs, SceneGraph::Model* rhs) {
|
||||
bool operator()(SceneGraph::Model *lhs, SceneGraph::Model *rhs)
|
||||
{
|
||||
return lhs->GetName() < rhs->GetName();
|
||||
}
|
||||
};
|
||||
|
@ -162,31 +167,31 @@ void CityOnPlanet::SetCityModelPatterns(const SystemPath &path)
|
|||
Uint32 _init[5] = { path.systemIndex, Uint32(path.sectorX), Uint32(path.sectorY), Uint32(path.sectorZ), UNIVERSE_SEED };
|
||||
Random rand(_init, 5);
|
||||
|
||||
typedef std::set<SceneGraph::Model*, ModelNameComparator> ModelSet;
|
||||
typedef std::set<SceneGraph::Model *, ModelNameComparator> ModelSet;
|
||||
typedef ModelSet::iterator TSetIter;
|
||||
ModelSet modelSet;
|
||||
{
|
||||
for (unsigned int j=0; j < s_buildingList.numBuildings; j++) {
|
||||
for (unsigned int j = 0; j < s_buildingList.numBuildings; j++) {
|
||||
SceneGraph::Model *m = s_buildingList.buildings[j].resolvedModel;
|
||||
modelSet.insert(m);
|
||||
}
|
||||
}
|
||||
|
||||
SceneGraph::ModelSkin skin;
|
||||
for (TSetIter it=modelSet.begin(), itEnd=modelSet.end(); it!=itEnd; ++it) {
|
||||
for (TSetIter it = modelSet.begin(), itEnd = modelSet.end(); it != itEnd; ++it) {
|
||||
SceneGraph::Model *m = (*it);
|
||||
if (!m->SupportsPatterns()) continue;
|
||||
skin.SetRandomColors(rand);
|
||||
skin.Apply(m);
|
||||
if(m->SupportsPatterns())
|
||||
m->SetPattern(rand.Int32(0, m->GetNumPatterns()-1));
|
||||
if (m->SupportsPatterns())
|
||||
m->SetPattern(rand.Int32(0, m->GetNumPatterns() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
CityOnPlanet::~CityOnPlanet()
|
||||
{
|
||||
// frame may be null (already removed from
|
||||
for (unsigned int i=0; i<m_buildings.size(); i++) {
|
||||
for (unsigned int i = 0; i < m_buildings.size(); i++) {
|
||||
m_frame->RemoveStaticGeom(m_buildings[i].geom);
|
||||
delete m_buildings[i].geom;
|
||||
}
|
||||
|
@ -206,26 +211,23 @@ CityOnPlanet::CityOnPlanet(Planet *planet, SpaceStation *station, const Uint32 s
|
|||
const matrix4x4d &m = station->GetOrient();
|
||||
const vector3d p = station->GetPosition();
|
||||
|
||||
const vector3d mx = m*vector3d(1,0,0);
|
||||
const vector3d mz = m*vector3d(0,0,1);
|
||||
const vector3d mx = m * vector3d(1, 0, 0);
|
||||
const vector3d mz = m * vector3d(0, 0, 1);
|
||||
|
||||
Random rand;
|
||||
rand.seed(seed);
|
||||
|
||||
|
||||
int population = planet->GetSystemBody()->GetPopulation();
|
||||
int cityradius;
|
||||
|
||||
if (planet->GetSystemBody()->HasAtmosphere())
|
||||
{
|
||||
if (planet->GetSystemBody()->HasAtmosphere()) {
|
||||
population *= 1000;
|
||||
cityradius = (population < 200) ? 200 : ((population > START_SEG_SIZE) ? START_SEG_SIZE : population);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
population *= 100;
|
||||
cityradius = (population < 250) ? 250 : ((population > START_SEG_SIZE_NO_ATMO) ? START_SEG_SIZE_NO_ATMO : population);
|
||||
}
|
||||
|
||||
|
||||
citybuildinglist_t *buildings = &s_buildingList;
|
||||
vector3d cent = p;
|
||||
const int cellsize_i = 80;
|
||||
|
@ -235,8 +237,8 @@ CityOnPlanet::CityOnPlanet(Planet *planet, SpaceStation *station, const Uint32 s
|
|||
static const int gmid = (cityradius / cellsize_i);
|
||||
static const int gsize = gmid * 2;
|
||||
|
||||
assert((START_SEG_SIZE/cellsize_i)<100);
|
||||
assert((START_SEG_SIZE_NO_ATMO/cellsize_i)<100);
|
||||
assert((START_SEG_SIZE / cellsize_i) < 100);
|
||||
assert((START_SEG_SIZE_NO_ATMO / cellsize_i) < 100);
|
||||
uint8_t cellgrid[200][200];
|
||||
std::memset(cellgrid, 0, sizeof(cellgrid));
|
||||
|
||||
|
@ -247,10 +249,8 @@ CityOnPlanet::CityOnPlanet(Planet *planet, SpaceStation *station, const Uint32 s
|
|||
const int z2 = ceil(aabb.max.z / cellsize);
|
||||
|
||||
// Clear the cells where the station is
|
||||
for (int x = 0; x <= gsize; x++)
|
||||
{
|
||||
for (int z = 0; z <= gsize; z++)
|
||||
{
|
||||
for (int x = 0; x <= gsize; x++) {
|
||||
for (int z = 0; z <= gsize; z++) {
|
||||
const int zz = z - gmid;
|
||||
const int xx = x - gmid;
|
||||
if (zz > z1 && zz < z2 && xx > x1 && xx < x2)
|
||||
|
@ -264,54 +264,50 @@ CityOnPlanet::CityOnPlanet(Planet *planet, SpaceStation *station, const Uint32 s
|
|||
orientcalc[1] = m * matrix4x4d::RotateYMatrix(M_PI * 0.5 * 1);
|
||||
orientcalc[2] = m * matrix4x4d::RotateYMatrix(M_PI * 0.5 * 2);
|
||||
orientcalc[3] = m * matrix4x4d::RotateYMatrix(M_PI * 0.5 * 3);
|
||||
|
||||
const double maxdist = pow(gmid+0.333, 2);
|
||||
for (int x = 0; x <= gsize; x++)
|
||||
{
|
||||
const double distx = pow((x - gmid),2);
|
||||
for (int z = 0; z <= gsize; z++)
|
||||
{
|
||||
if (cellgrid[x][z] > 0)
|
||||
{
|
||||
|
||||
const double maxdist = pow(gmid + 0.333, 2);
|
||||
for (int x = 0; x <= gsize; x++) {
|
||||
const double distx = pow((x - gmid), 2);
|
||||
for (int z = 0; z <= gsize; z++) {
|
||||
if (cellgrid[x][z] > 0) {
|
||||
// This cell has been allocated for something already
|
||||
continue;
|
||||
}
|
||||
const double distz = pow((z - gmid),2);
|
||||
const double distz = pow((z - gmid), 2);
|
||||
if ((distz + distx) > maxdist)
|
||||
continue;
|
||||
|
||||
// fewer and fewer buildings the further from center you get
|
||||
if ((distx + distz)*(1.0 / maxdist) > rand.Double())
|
||||
if ((distx + distz) * (1.0 / maxdist) > rand.Double())
|
||||
continue;
|
||||
|
||||
cent = p + mz*((z - gmid) * cellsize) + mx* ((x - gmid) * cellsize);
|
||||
cent = p + mz * ((z - gmid) * cellsize) + mx * ((x - gmid) * cellsize);
|
||||
cent = cent.Normalized();
|
||||
|
||||
|
||||
const double height = planet->GetTerrainHeight(cent);
|
||||
if ((height - bodyradius) < 0) // don't position below sealevel
|
||||
continue;
|
||||
|
||||
|
||||
cent = cent * height;
|
||||
|
||||
// quickly get a random building
|
||||
const citybuilding_t &bt = buildings->buildings[rand.Int32(buildings->numBuildings)];
|
||||
const CollMesh* cmesh = bt.collMesh.Get(); // collision mesh
|
||||
|
||||
const CollMesh *cmesh = bt.collMesh.Get(); // collision mesh
|
||||
|
||||
// rotate the building to face a random direction
|
||||
const int32_t orient = rand.Int32(4);
|
||||
Geom *geom = new Geom(cmesh->GetGeomTree(), orientcalc[orient], cent, this);
|
||||
|
||||
|
||||
// add it to the list of buildings to render
|
||||
m_buildings.push_back({ bt.instIndex, float(cmesh->GetRadius()), orient, cent, geom });
|
||||
}
|
||||
}
|
||||
|
||||
Aabb buildAABB;
|
||||
for (std::vector<BuildingDef>::const_iterator iter=m_buildings.begin(), itEND=m_buildings.end(); iter != itEND; ++iter)
|
||||
{
|
||||
for (std::vector<BuildingDef>::const_iterator iter = m_buildings.begin(), itEND = m_buildings.end(); iter != itEND; ++iter) {
|
||||
buildAABB.Update((*iter).pos - p);
|
||||
}
|
||||
m_realCentre = buildAABB.min + ((buildAABB.max - buildAABB.min)*0.5);
|
||||
m_realCentre = buildAABB.min + ((buildAABB.max - buildAABB.min) * 0.5);
|
||||
m_clipRadius = buildAABB.GetRadius();
|
||||
AddStaticGeomsToCollisionSpace();
|
||||
}
|
||||
|
@ -336,19 +332,19 @@ void CityOnPlanet::Render(Graphics::Renderer *r, const Graphics::Frustum &frustu
|
|||
}
|
||||
|
||||
rot[0] = viewTransform * rot[0];
|
||||
for (int i=1; i<4; i++) {
|
||||
rot[i] = rot[0] * matrix4x4d::RotateYMatrix(M_PI*0.5*double(i));
|
||||
for (int i = 1; i < 4; i++) {
|
||||
rot[i] = rot[0] * matrix4x4d::RotateYMatrix(M_PI * 0.5 * double(i));
|
||||
}
|
||||
for (int i=0; i<4; i++) {
|
||||
for (int e=0; e<16; e++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int e = 0; e < 16; e++) {
|
||||
rotf[i][e] = float(rot[i][e]);
|
||||
}
|
||||
}
|
||||
|
||||
// update any idle animations
|
||||
for(Uint32 i=0; i<s_buildingList.numBuildings; i++) {
|
||||
for (Uint32 i = 0; i < s_buildingList.numBuildings; i++) {
|
||||
SceneGraph::Animation *pAnim = s_buildingList.buildings[i].idle;
|
||||
if(pAnim) {
|
||||
if (pAnim) {
|
||||
pAnim->SetProgress(fmod(pAnim->GetProgress() + (Pi::game->GetTimeStep() / pAnim->GetDuration()), 1.0));
|
||||
pAnim->Interpolate();
|
||||
}
|
||||
|
@ -356,16 +352,15 @@ void CityOnPlanet::Render(Graphics::Renderer *r, const Graphics::Frustum &frustu
|
|||
|
||||
Uint32 uCount = 0;
|
||||
std::vector<Uint32> instCount;
|
||||
std::vector< std::vector<matrix4x4f> > transform;
|
||||
std::vector<std::vector<matrix4x4f>> transform;
|
||||
instCount.resize(s_buildingList.numBuildings);
|
||||
transform.resize(s_buildingList.numBuildings);
|
||||
memset(&instCount[0], 0, sizeof(Uint32) * s_buildingList.numBuildings);
|
||||
for(Uint32 i=0; i<s_buildingList.numBuildings; i++) {
|
||||
for (Uint32 i = 0; i < s_buildingList.numBuildings; i++) {
|
||||
transform[i].reserve(m_buildingCounts[i]);
|
||||
}
|
||||
|
||||
for (std::vector<BuildingDef>::const_iterator iter=m_enabledBuildings.begin(), itEND=m_enabledBuildings.end(); iter != itEND; ++iter)
|
||||
{
|
||||
for (std::vector<BuildingDef>::const_iterator iter = m_enabledBuildings.begin(), itEND = m_enabledBuildings.end(); iter != itEND; ++iter) {
|
||||
const vector3d pos = viewTransform * (*iter).pos;
|
||||
const vector3f posf(pos);
|
||||
if (!frustum.TestPoint(pos, (*iter).clipRadius))
|
||||
|
@ -376,14 +371,14 @@ void CityOnPlanet::Render(Graphics::Renderer *r, const Graphics::Frustum &frustu
|
|||
|
||||
// increment the instance count and store the transform
|
||||
instCount[(*iter).instIndex]++;
|
||||
transform[(*iter).instIndex].push_back( _rot );
|
||||
transform[(*iter).instIndex].push_back(_rot);
|
||||
|
||||
++uCount;
|
||||
}
|
||||
|
||||
// render the building models using instancing
|
||||
for(Uint32 i=0; i<s_buildingList.numBuildings; i++) {
|
||||
if(!transform[i].empty())
|
||||
for (Uint32 i = 0; i < s_buildingList.numBuildings; i++) {
|
||||
if (!transform[i].empty())
|
||||
s_buildingList.buildings[i].resolvedModel->Render(transform[i]);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,22 +4,28 @@
|
|||
#ifndef _CITYONPLANET_H
|
||||
#define _CITYONPLANET_H
|
||||
|
||||
#include "libs.h"
|
||||
#include "Random.h"
|
||||
#include "Object.h"
|
||||
#include "CollMesh.h"
|
||||
#include "Object.h"
|
||||
#include "Random.h"
|
||||
#include "collider/Geom.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "libs.h"
|
||||
|
||||
class Planet;
|
||||
class SpaceStation;
|
||||
class Frame;
|
||||
namespace Graphics { class Renderer; class Frustum; }
|
||||
namespace SceneGraph { class Model; class Animation; }
|
||||
namespace Graphics {
|
||||
class Renderer;
|
||||
class Frustum;
|
||||
} // namespace Graphics
|
||||
namespace SceneGraph {
|
||||
class Model;
|
||||
class Animation;
|
||||
} // namespace SceneGraph
|
||||
|
||||
#define CITY_ON_PLANET_RADIUS 5000.0
|
||||
|
||||
class CityOnPlanet: public Object {
|
||||
class CityOnPlanet : public Object {
|
||||
public:
|
||||
OBJDEF(CityOnPlanet, Object, CITYONPLANET);
|
||||
CityOnPlanet(Planet *planet, SpaceStation *station, const Uint32 seed);
|
||||
|
@ -30,6 +36,7 @@ public:
|
|||
static void Init();
|
||||
static void Uninit();
|
||||
static void SetCityModelPatterns(const SystemPath &path);
|
||||
|
||||
private:
|
||||
void AddStaticGeomsToCollisionSpace();
|
||||
void RemoveStaticGeomsFromCollisionSpace();
|
||||
|
|
|
@ -3,20 +3,21 @@
|
|||
|
||||
#ifndef _COLLMESH_H
|
||||
#define _COLLMESH_H
|
||||
#include "RefCounted.h"
|
||||
#include "Aabb.h"
|
||||
#include "collider/GeomTree.h"
|
||||
#include "RefCounted.h"
|
||||
#include "Serializer.h"
|
||||
#include "collider/GeomTree.h"
|
||||
|
||||
//This simply stores the collision GeomTrees
|
||||
//and AABB.
|
||||
class CollMesh : public RefCounted {
|
||||
public:
|
||||
CollMesh()
|
||||
: m_geomTree(0)
|
||||
, m_totalTris(0)
|
||||
{ }
|
||||
virtual ~CollMesh() {
|
||||
CollMesh() :
|
||||
m_geomTree(0),
|
||||
m_totalTris(0)
|
||||
{}
|
||||
virtual ~CollMesh()
|
||||
{
|
||||
for (auto it = m_dynGeomTrees.begin(); it != m_dynGeomTrees.end(); ++it)
|
||||
delete *it;
|
||||
delete m_geomTree;
|
||||
|
@ -24,19 +25,22 @@ public:
|
|||
inline Aabb &GetAabb() { return m_aabb; }
|
||||
|
||||
inline double GetRadius() const { return m_aabb.GetRadius(); }
|
||||
inline void SetRadius(double v) {
|
||||
inline void SetRadius(double v)
|
||||
{
|
||||
//0 radius = trouble
|
||||
m_aabb.radius = std::max(v, 0.1);
|
||||
}
|
||||
|
||||
inline GeomTree *GetGeomTree() const { return m_geomTree; }
|
||||
inline void SetGeomTree(GeomTree *t) {
|
||||
inline void SetGeomTree(GeomTree *t)
|
||||
{
|
||||
assert(t);
|
||||
m_geomTree = t;
|
||||
}
|
||||
|
||||
inline const std::vector<GeomTree*> &GetDynGeomTrees() const { return m_dynGeomTrees; }
|
||||
inline void AddDynGeomTree(GeomTree *t) {
|
||||
inline const std::vector<GeomTree *> &GetDynGeomTrees() const { return m_dynGeomTrees; }
|
||||
inline void AddDynGeomTree(GeomTree *t)
|
||||
{
|
||||
assert(t);
|
||||
m_dynGeomTrees.push_back(t);
|
||||
}
|
||||
|
@ -51,7 +55,7 @@ public:
|
|||
protected:
|
||||
Aabb m_aabb;
|
||||
GeomTree *m_geomTree;
|
||||
std::vector<GeomTree*> m_dynGeomTrees;
|
||||
std::vector<GeomTree *> m_dynGeomTrees;
|
||||
unsigned int m_totalTris;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,33 +5,33 @@
|
|||
#include "LuaUtils.h"
|
||||
#include <SDL_stdinc.h>
|
||||
|
||||
const Color4f Color4f::BLACK = Color4f(0.0f,0.0f,0.0f,1.0f);
|
||||
const Color4f Color4f::WHITE = Color4f(1.0f,1.0f,1.0f,1.0f);
|
||||
const Color4f Color4f::RED = Color4f(1.0f,0.0f,0.0f,1.0f);
|
||||
const Color4f Color4f::GREEN = Color4f(0.0f,1.0f,0.0f,1.0f);
|
||||
const Color4f Color4f::BLUE = Color4f(0.0f,0.0f,1.0f,1.0f);
|
||||
const Color4f Color4f::YELLOW = Color4f(1.0f,1.0f,0.0f,1.0f);
|
||||
const Color4f Color4f::GRAY = Color4f(0.5f,0.5f,0.5f,1.f);
|
||||
const Color4f Color4f::BLACK = Color4f(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
const Color4f Color4f::WHITE = Color4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
const Color4f Color4f::RED = Color4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
const Color4f Color4f::GREEN = Color4f(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
const Color4f Color4f::BLUE = Color4f(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
const Color4f Color4f::YELLOW = Color4f(1.0f, 1.0f, 0.0f, 1.0f);
|
||||
const Color4f Color4f::GRAY = Color4f(0.5f, 0.5f, 0.5f, 1.f);
|
||||
const Color4f Color4f::STEELBLUE = Color4f(0.27f, 0.51f, 0.71f, 1.f);
|
||||
const Color4f Color4f::BLANK = Color4f(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
const Color4ub Color::BLACK = Color(0, 0, 0, 255);
|
||||
const Color4ub Color::WHITE = Color(255, 255, 255, 255);
|
||||
const Color4ub Color::RED = Color(255, 0, 0, 255);
|
||||
const Color4ub Color::GREEN = Color(0, 255, 0, 255);
|
||||
const Color4ub Color::BLUE = Color(0, 0, 255, 255);
|
||||
const Color4ub Color::YELLOW = Color(255, 255, 0, 255);
|
||||
const Color4ub Color::GRAY = Color(128,128,128,255);
|
||||
const Color4ub Color::BLACK = Color(0, 0, 0, 255);
|
||||
const Color4ub Color::WHITE = Color(255, 255, 255, 255);
|
||||
const Color4ub Color::RED = Color(255, 0, 0, 255);
|
||||
const Color4ub Color::GREEN = Color(0, 255, 0, 255);
|
||||
const Color4ub Color::BLUE = Color(0, 0, 255, 255);
|
||||
const Color4ub Color::YELLOW = Color(255, 255, 0, 255);
|
||||
const Color4ub Color::GRAY = Color(128, 128, 128, 255);
|
||||
const Color4ub Color::STEELBLUE = Color(68, 130, 181, 255);
|
||||
const Color4ub Color::BLANK = Color(0, 0, 0, 0);
|
||||
const Color4ub Color::PINK = Color(252, 15, 192, 255); // debug pink
|
||||
const Color4ub Color::PINK = Color(252, 15, 192, 255); // debug pink
|
||||
|
||||
const Color3ub Color3ub::BLACK = Color3ub(0, 0, 0);
|
||||
const Color3ub Color3ub::WHITE = Color3ub(255, 255, 255);
|
||||
const Color3ub Color3ub::RED = Color3ub(255, 0, 0);
|
||||
const Color3ub Color3ub::GREEN = Color3ub(0, 255, 0);
|
||||
const Color3ub Color3ub::BLUE = Color3ub(0, 0, 255);
|
||||
const Color3ub Color3ub::YELLOW = Color3ub(255, 255, 0);
|
||||
const Color3ub Color3ub::BLACK = Color3ub(0, 0, 0);
|
||||
const Color3ub Color3ub::WHITE = Color3ub(255, 255, 255);
|
||||
const Color3ub Color3ub::RED = Color3ub(255, 0, 0);
|
||||
const Color3ub Color3ub::GREEN = Color3ub(0, 255, 0);
|
||||
const Color3ub Color3ub::BLUE = Color3ub(0, 0, 255);
|
||||
const Color3ub Color3ub::YELLOW = Color3ub(255, 255, 0);
|
||||
const Color3ub Color3ub::STEELBLUE = Color3ub(68, 130, 181);
|
||||
const Color3ub Color3ub::BLANK = Color3ub(0, 0, 0);
|
||||
|
||||
|
@ -80,10 +80,10 @@ Color4f Color4f::FromLuaTable(lua_State *l, int idx)
|
|||
void Color4ub::ToLuaTable(lua_State *l)
|
||||
{
|
||||
lua_newtable(l);
|
||||
pi_lua_settable(l, "r", 255.0/r);
|
||||
pi_lua_settable(l, "g", 255.0/g);
|
||||
pi_lua_settable(l, "b", 255.0/b);
|
||||
pi_lua_settable(l, "a", 255.0/a);
|
||||
pi_lua_settable(l, "r", 255.0 / r);
|
||||
pi_lua_settable(l, "g", 255.0 / g);
|
||||
pi_lua_settable(l, "b", 255.0 / b);
|
||||
pi_lua_settable(l, "a", 255.0 / a);
|
||||
}
|
||||
|
||||
Color4ub Color4ub::FromLuaTable(lua_State *l, int idx)
|
||||
|
@ -101,11 +101,11 @@ Color4ub Color4ub::FromLuaTable(lua_State *l, int idx)
|
|||
|
||||
LUA_DEBUG_END(l, 0);
|
||||
|
||||
return Color4ub(r*255, g*255, b*255, a*255);
|
||||
return Color4ub(r * 255, g * 255, b * 255, a * 255);
|
||||
}
|
||||
|
||||
Uint8 Color4ub::GetLuminance() const
|
||||
{
|
||||
// these weights are those used for the JPEG luma channel
|
||||
return (r*299 + g*587 + b*114) / 1000;
|
||||
return (r * 299 + g * 587 + b * 114) / 1000;
|
||||
}
|
||||
|
|
149
src/Color.h
149
src/Color.h
|
@ -9,15 +9,38 @@
|
|||
struct lua_State;
|
||||
|
||||
struct Color4f {
|
||||
float r,g,b,a;
|
||||
Color4f() : r(0.f), g(0.f), b(0.f), a(1.f) {}
|
||||
Color4f(float v_) : r(v_), g(v_), b(v_), a(v_) { }
|
||||
Color4f(float r_, float g_, float b_): r(r_), g(g_), b(b_), a(1.f) {}
|
||||
Color4f(float r_, float g_, float b_, float a_): r(r_), g(g_), b(b_), a(a_) {}
|
||||
float r, g, b, a;
|
||||
Color4f() :
|
||||
r(0.f),
|
||||
g(0.f),
|
||||
b(0.f),
|
||||
a(1.f) {}
|
||||
Color4f(float v_) :
|
||||
r(v_),
|
||||
g(v_),
|
||||
b(v_),
|
||||
a(v_) {}
|
||||
Color4f(float r_, float g_, float b_) :
|
||||
r(r_),
|
||||
g(g_),
|
||||
b(b_),
|
||||
a(1.f) {}
|
||||
Color4f(float r_, float g_, float b_, float a_) :
|
||||
r(r_),
|
||||
g(g_),
|
||||
b(b_),
|
||||
a(a_) {}
|
||||
operator float *() { return &r; }
|
||||
operator const float *() const { return &r; }
|
||||
Color4f &operator*=(const float v) { r*=v; g*=v; b*=v; a*=v; return *this; }
|
||||
friend Color4f operator*(const Color4f &c, const float v) { return Color4f(c.r*v, c.g*v, c.b*v, c.a*v); }
|
||||
Color4f &operator*=(const float v)
|
||||
{
|
||||
r *= v;
|
||||
g *= v;
|
||||
b *= v;
|
||||
a *= v;
|
||||
return *this;
|
||||
}
|
||||
friend Color4f operator*(const Color4f &c, const float v) { return Color4f(c.r * v, c.g * v, c.b * v, c.a * v); }
|
||||
|
||||
void ToLuaTable(lua_State *l);
|
||||
static Color4f FromLuaTable(lua_State *l, int idx);
|
||||
|
@ -37,31 +60,65 @@ struct Color4f {
|
|||
|
||||
namespace {
|
||||
static const float s_inv255 = 1.0f / 255.0f;
|
||||
#define INV255(n) (Uint8(float(n) * s_inv255))
|
||||
}
|
||||
#define INV255(n) (Uint8(float(n) * s_inv255))
|
||||
} // namespace
|
||||
|
||||
struct Color4ub {
|
||||
|
||||
Uint8 r, g, b, a;
|
||||
Color4ub(): r(0), g(0), b(0), a(255) {}
|
||||
Color4ub(Uint8 r_, Uint8 g_, Uint8 b_): r(r_), g(g_), b(b_), a(255) {}
|
||||
Color4ub(Uint8 r_, Uint8 g_, Uint8 b_, Uint8 a_): r(r_), g(g_), b(b_), a(a_) {}
|
||||
Color4ub(const Color4f &c): r(Uint8(c.r*255.f)), g(Uint8(c.g*255.f)), b(Uint8(c.b*255.f)), a(Uint8(c.a*255.f)) {}
|
||||
Color4ub(const Uint32 rgba): r((rgba >> 24) & 0xff), g((rgba >> 16) & 0xff), b((rgba >> 8) & 0xff), a(rgba & 0xff) {}
|
||||
Color4ub() :
|
||||
r(0),
|
||||
g(0),
|
||||
b(0),
|
||||
a(255) {}
|
||||
Color4ub(Uint8 r_, Uint8 g_, Uint8 b_) :
|
||||
r(r_),
|
||||
g(g_),
|
||||
b(b_),
|
||||
a(255) {}
|
||||
Color4ub(Uint8 r_, Uint8 g_, Uint8 b_, Uint8 a_) :
|
||||
r(r_),
|
||||
g(g_),
|
||||
b(b_),
|
||||
a(a_) {}
|
||||
Color4ub(const Color4f &c) :
|
||||
r(Uint8(c.r * 255.f)),
|
||||
g(Uint8(c.g * 255.f)),
|
||||
b(Uint8(c.b * 255.f)),
|
||||
a(Uint8(c.a * 255.f)) {}
|
||||
Color4ub(const Uint32 rgba) :
|
||||
r((rgba >> 24) & 0xff),
|
||||
g((rgba >> 16) & 0xff),
|
||||
b((rgba >> 8) & 0xff),
|
||||
a(rgba & 0xff) {}
|
||||
|
||||
operator unsigned char*() { return &r; }
|
||||
operator const unsigned char*() const { return &r; }
|
||||
Color4ub operator+(const Color4ub &c) const { return Color4ub(c.r+r, c.g+g, c.b+b, c.a+a); }
|
||||
Color4ub &operator*=(const float f) { r=Uint8(r*f); g=Uint8(g*f); b=Uint8(b*f); a=Uint8(a*f); return *this; }
|
||||
Color4ub &operator*=(const Color4ub &c) { r*=INV255(c.r); g*=INV255(c.g); b*=INV255(c.b); a*=INV255(c.a); return *this; }
|
||||
Color4ub operator*(const float f) const { return Color4ub(Uint8(f*r), Uint8(f*g), Uint8(f*b), Uint8(f*a)); }
|
||||
Color4ub operator*(const Color4ub &c) const { return Color4ub(INV255(c.r)*r, INV255(c.g)*g, INV255(c.b)*b, INV255(c.a)*a); }
|
||||
Color4ub operator/(const float f) const { return Color4ub(Uint8(r/f), Uint8(g/f), Uint8(b/f), Uint8(a/f)); }
|
||||
operator unsigned char *() { return &r; }
|
||||
operator const unsigned char *() const { return &r; }
|
||||
Color4ub operator+(const Color4ub &c) const { return Color4ub(c.r + r, c.g + g, c.b + b, c.a + a); }
|
||||
Color4ub &operator*=(const float f)
|
||||
{
|
||||
r = Uint8(r * f);
|
||||
g = Uint8(g * f);
|
||||
b = Uint8(b * f);
|
||||
a = Uint8(a * f);
|
||||
return *this;
|
||||
}
|
||||
Color4ub &operator*=(const Color4ub &c)
|
||||
{
|
||||
r *= INV255(c.r);
|
||||
g *= INV255(c.g);
|
||||
b *= INV255(c.b);
|
||||
a *= INV255(c.a);
|
||||
return *this;
|
||||
}
|
||||
Color4ub operator*(const float f) const { return Color4ub(Uint8(f * r), Uint8(f * g), Uint8(f * b), Uint8(f * a)); }
|
||||
Color4ub operator*(const Color4ub &c) const { return Color4ub(INV255(c.r) * r, INV255(c.g) * g, INV255(c.b) * b, INV255(c.a) * a); }
|
||||
Color4ub operator/(const float f) const { return Color4ub(Uint8(r / f), Uint8(g / f), Uint8(b / f), Uint8(a / f)); }
|
||||
|
||||
friend bool operator==(const Color4ub& aIn, const Color4ub& bIn) { return ((aIn.r == bIn.r) && (aIn.g == bIn.g) && (aIn.b == bIn.b) && (aIn.a == bIn.a)); }
|
||||
friend bool operator!=(const Color4ub& aIn, const Color4ub& bIn) { return ((aIn.r != bIn.r) || (aIn.g != bIn.g) || (aIn.b != bIn.b) || (aIn.a != bIn.a)); }
|
||||
friend bool operator==(const Color4ub &aIn, const Color4ub &bIn) { return ((aIn.r == bIn.r) && (aIn.g == bIn.g) && (aIn.b == bIn.b) && (aIn.a == bIn.a)); }
|
||||
friend bool operator!=(const Color4ub &aIn, const Color4ub &bIn) { return ((aIn.r != bIn.r) || (aIn.g != bIn.g) || (aIn.b != bIn.b) || (aIn.a != bIn.a)); }
|
||||
|
||||
Color4f ToColor4f() const { return Color4f(r/255.0f, g/255.0f, b/255.0f, a/255.0f); }
|
||||
Color4f ToColor4f() const { return Color4f(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); }
|
||||
|
||||
void ToLuaTable(lua_State *l);
|
||||
static Color4ub FromLuaTable(lua_State *l, int idx);
|
||||
|
@ -82,20 +139,38 @@ struct Color4ub {
|
|||
|
||||
struct Color3ub {
|
||||
Uint8 r, g, b;
|
||||
Color3ub(): r(0), g(0), b(0) {}
|
||||
Color3ub(Uint8 v_): r(v_), g(v_), b(v_) {}
|
||||
Color3ub(Uint8 r_, Uint8 g_, Uint8 b_): r(r_), g(g_), b(b_) {}
|
||||
Color3ub(const Color4f &c): r(Uint8(c.r*255.f)), g(Uint8(c.g*255.f)), b(Uint8(c.b*255.f)) {}
|
||||
Color3ub() :
|
||||
r(0),
|
||||
g(0),
|
||||
b(0) {}
|
||||
Color3ub(Uint8 v_) :
|
||||
r(v_),
|
||||
g(v_),
|
||||
b(v_) {}
|
||||
Color3ub(Uint8 r_, Uint8 g_, Uint8 b_) :
|
||||
r(r_),
|
||||
g(g_),
|
||||
b(b_) {}
|
||||
Color3ub(const Color4f &c) :
|
||||
r(Uint8(c.r * 255.f)),
|
||||
g(Uint8(c.g * 255.f)),
|
||||
b(Uint8(c.b * 255.f)) {}
|
||||
|
||||
operator unsigned char*() { return &r; }
|
||||
operator const unsigned char*() const { return &r; }
|
||||
Color3ub &operator*=(const Color3ub &c) { r*=INV255(c.r); g*=INV255(c.g); b*=INV255(c.b); return *this; }
|
||||
Color3ub operator+(const Color3ub &c) const { return Color3ub(c.r+r, c.g+g, c.b+b); }
|
||||
Color3ub operator*(const float f) const { return Color3ub(Uint8(f*r), Uint8(f*g), Uint8(f*b)); }
|
||||
Color3ub operator*(const Color3ub &c) const { return Color3ub(INV255(c.r)*r, INV255(c.g)*g, INV255(c.b)*b); }
|
||||
Color3ub operator/(const float f) const { return Color3ub(Uint8(r/f), Uint8(g/f), Uint8(b/f)); }
|
||||
operator unsigned char *() { return &r; }
|
||||
operator const unsigned char *() const { return &r; }
|
||||
Color3ub &operator*=(const Color3ub &c)
|
||||
{
|
||||
r *= INV255(c.r);
|
||||
g *= INV255(c.g);
|
||||
b *= INV255(c.b);
|
||||
return *this;
|
||||
}
|
||||
Color3ub operator+(const Color3ub &c) const { return Color3ub(c.r + r, c.g + g, c.b + b); }
|
||||
Color3ub operator*(const float f) const { return Color3ub(Uint8(f * r), Uint8(f * g), Uint8(f * b)); }
|
||||
Color3ub operator*(const Color3ub &c) const { return Color3ub(INV255(c.r) * r, INV255(c.g) * g, INV255(c.b) * b); }
|
||||
Color3ub operator/(const float f) const { return Color3ub(Uint8(r / f), Uint8(g / f), Uint8(b / f)); }
|
||||
|
||||
Color4f ToColor4f() const { return Color4f(r/255.0f, g/255.0f, b/255.0f); }
|
||||
Color4f ToColor4f() const { return Color4f(r / 255.0f, g / 255.0f, b / 255.0f); }
|
||||
|
||||
static const Color3ub BLACK;
|
||||
static const Color3ub WHITE;
|
||||
|
|
|
@ -4,18 +4,20 @@
|
|||
#ifndef _CUTSCENE_H
|
||||
#define _CUTSCENE_H
|
||||
|
||||
#include "libs.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/Light.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "libs.h"
|
||||
|
||||
namespace SceneGraph { class Model; }
|
||||
namespace SceneGraph {
|
||||
class Model;
|
||||
}
|
||||
class Shields;
|
||||
|
||||
class Cutscene {
|
||||
public:
|
||||
Cutscene(Graphics::Renderer *r, int width, int height)
|
||||
: m_aspectRatio(float(width)/float(height))
|
||||
, m_renderer(r)
|
||||
Cutscene(Graphics::Renderer *r, int width, int height) :
|
||||
m_aspectRatio(float(width) / float(height)),
|
||||
m_renderer(r)
|
||||
{
|
||||
}
|
||||
virtual ~Cutscene() {}
|
||||
|
|
101
src/DateTime.cpp
101
src/DateTime.cpp
|
@ -1,18 +1,19 @@
|
|||
#include "DateTime.h"
|
||||
|
||||
#include "libs.h"
|
||||
#include <stdio.h>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <stdio.h>
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
#include "libs.h"
|
||||
|
||||
static char month_days[2][12] = {
|
||||
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
||||
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
};
|
||||
|
||||
static bool is_leap_year(int year) {
|
||||
static bool is_leap_year(int year)
|
||||
{
|
||||
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
|
||||
}
|
||||
|
||||
|
@ -35,7 +36,8 @@ enum {
|
|||
//
|
||||
// divmod_euclid provides a division operation that always gives a non-negative remainder
|
||||
template <typename T>
|
||||
static std::pair<T,T> divmod_euclid(const T dividend, const T divisor) {
|
||||
static std::pair<T, T> divmod_euclid(const T dividend, const T divisor)
|
||||
{
|
||||
T quot = dividend / divisor, rem = dividend % divisor;
|
||||
if (rem < 0) {
|
||||
if (divisor > 0) {
|
||||
|
@ -50,11 +52,13 @@ static std::pair<T,T> divmod_euclid(const T dividend, const T divisor) {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
static std::pair<T,T> divmod_trunc(const T a, const T b) {
|
||||
static std::pair<T, T> divmod_trunc(const T a, const T b)
|
||||
{
|
||||
return std::make_pair(a / b, a % b);
|
||||
}
|
||||
|
||||
Time::DateTime::DateTime(int year, int month, int day, int hour, int minute, int second, int microsecond) {
|
||||
Time::DateTime::DateTime(int year, int month, int day, int hour, int minute, int second, int microsecond)
|
||||
{
|
||||
// minimum year is just a sanity check; the code should work for earlier years
|
||||
assert(year >= 1600 && year <= APPROX_MAX_YEAR);
|
||||
assert(month >= 1 && month <= 12);
|
||||
|
@ -66,35 +70,31 @@ Time::DateTime::DateTime(int year, int month, int day, int hour, int minute, int
|
|||
|
||||
const int yoffset = (year - 2001);
|
||||
// C99 and C++11 specify that integer division truncates toward zero
|
||||
const int nleap = (yoffset >= 0)
|
||||
? (yoffset/400 - yoffset/100 + yoffset/4)
|
||||
: ((yoffset-399)/400 - (yoffset-99)/100 + (yoffset-3)/4);
|
||||
const int nleap = (yoffset >= 0) ? (yoffset / 400 - yoffset / 100 + yoffset / 4) : ((yoffset - 399) / 400 - (yoffset - 99) / 100 + (yoffset - 3) / 4);
|
||||
|
||||
int days = 365*yoffset + nleap;
|
||||
int days = 365 * yoffset + nleap;
|
||||
|
||||
// month offset
|
||||
const bool leap = is_leap_year(year);
|
||||
for (int i = 1; i < month; ++i) {
|
||||
days += month_days[leap][i-1];
|
||||
days += month_days[leap][i - 1];
|
||||
}
|
||||
|
||||
// day offset
|
||||
days += (day - 1);
|
||||
|
||||
// final timestamp
|
||||
m_timestamp
|
||||
= days * Time::Day
|
||||
+ hour * Time::Hour
|
||||
+ minute * Time::Minute
|
||||
+ second * Time::Second
|
||||
+ microsecond * Time::Microsecond;
|
||||
m_timestamp = days * Time::Day + hour * Time::Hour + minute * Time::Minute + second * Time::Second + microsecond * Time::Microsecond;
|
||||
}
|
||||
|
||||
Time::DateTime::DateTime(double gameTime) : DateTime(3200,1,1,0,0,0) {
|
||||
Time::DateTime::DateTime(double gameTime) :
|
||||
DateTime(3200, 1, 1, 0, 0, 0)
|
||||
{
|
||||
*this += Time::TimeDelta(gameTime, Time::Second);
|
||||
}
|
||||
|
||||
void Time::DateTime::GetDateParts(int *out_year, int *out_month, int *out_day) const {
|
||||
void Time::DateTime::GetDateParts(int *out_year, int *out_month, int *out_day) const
|
||||
{
|
||||
if (out_year || out_month || out_day) {
|
||||
static_assert(Time::Day > (Sint64(1) << 32),
|
||||
"code below assumes that the 'date' part of a 64-bit timestamp fits in 32 bits");
|
||||
|
@ -106,13 +106,13 @@ void Time::DateTime::GetDateParts(int *out_year, int *out_month, int *out_day) c
|
|||
// computed such that n400 may be negative, but all other values must be positive
|
||||
|
||||
int n400, n100, n4, n1;
|
||||
std::tie(n400, days) = divmod_euclid(days, 365*400 + 97);
|
||||
std::tie(n400, days) = divmod_euclid(days, 365 * 400 + 97);
|
||||
// days must be non-negative after this, so we can use truncating division from here
|
||||
std::tie(n100, days) = divmod_trunc(days, 365*100 + 24);
|
||||
std::tie(n4, days) = divmod_trunc(days, 365*4 + 1);
|
||||
std::tie(n100, days) = divmod_trunc(days, 365 * 100 + 24);
|
||||
std::tie(n4, days) = divmod_trunc(days, 365 * 4 + 1);
|
||||
std::tie(n1, days) = divmod_trunc(days, 365);
|
||||
|
||||
int year = 2001 + 400*n400 + 100*n100 + 4*n4 + n1;
|
||||
int year = 2001 + 400 * n400 + 100 * n100 + 4 * n4 + n1;
|
||||
int day = days;
|
||||
|
||||
// the last day in a 400-year or a 4-year cycle are handled incorrectly,
|
||||
|
@ -134,30 +134,46 @@ void Time::DateTime::GetDateParts(int *out_year, int *out_month, int *out_day) c
|
|||
assert(month < 12);
|
||||
}
|
||||
|
||||
if (out_year) { *out_year = year; }
|
||||
if (out_month) { *out_month = month + 1; }
|
||||
if (out_day) { *out_day = day + 1; }
|
||||
if (out_year) {
|
||||
*out_year = year;
|
||||
}
|
||||
if (out_month) {
|
||||
*out_month = month + 1;
|
||||
}
|
||||
if (out_day) {
|
||||
*out_day = day + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Time::DateTime::GetTimeParts(int *out_hour, int *out_minute, int *out_second, int *out_microsecond) const {
|
||||
void Time::DateTime::GetTimeParts(int *out_hour, int *out_minute, int *out_second, int *out_microsecond) const
|
||||
{
|
||||
if (out_hour || out_minute || out_second || out_microsecond) {
|
||||
const Sint64 tstamp = divmod_euclid(m_timestamp, Sint64(Time::Day)).second;
|
||||
assert(tstamp >= 0);
|
||||
|
||||
if (out_microsecond) { *out_microsecond = (tstamp / Time::Microsecond) % 1000000; }
|
||||
if (out_microsecond) {
|
||||
*out_microsecond = (tstamp / Time::Microsecond) % 1000000;
|
||||
}
|
||||
|
||||
const int seconds = (tstamp / Time::Second);
|
||||
assert(seconds >= 0 && seconds < 24*60*60);
|
||||
assert(seconds >= 0 && seconds < 24 * 60 * 60);
|
||||
|
||||
if (out_hour) { *out_hour = (seconds / 3600); }
|
||||
if (out_minute) { *out_minute = (seconds / 60) % 60; }
|
||||
if (out_second) { *out_second = (seconds / 1) % 60; }
|
||||
if (out_hour) {
|
||||
*out_hour = (seconds / 3600);
|
||||
}
|
||||
if (out_minute) {
|
||||
*out_minute = (seconds / 60) % 60;
|
||||
}
|
||||
if (out_second) {
|
||||
*out_second = (seconds / 1) % 60;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double Time::DateTime::ToGameTime() const {
|
||||
const Time::DateTime base(3200,1,1, 0,0,0);
|
||||
double Time::DateTime::ToGameTime() const
|
||||
{
|
||||
const Time::DateTime base(3200, 1, 1, 0, 0, 0);
|
||||
Time::TimeDelta tstamp = (*this - base);
|
||||
if (*this < base) {
|
||||
// adjustment to give correct rounding for GetTotalSeconds()
|
||||
|
@ -166,7 +182,8 @@ double Time::DateTime::ToGameTime() const {
|
|||
return double(tstamp.GetTotalSeconds());
|
||||
}
|
||||
|
||||
std::string Time::DateTime::ToDateString() const {
|
||||
std::string Time::DateTime::ToDateString() const
|
||||
{
|
||||
char buf[32];
|
||||
int year, month, day;
|
||||
GetDateParts(&year, &month, &day);
|
||||
|
@ -174,7 +191,8 @@ std::string Time::DateTime::ToDateString() const {
|
|||
return std::string(buf);
|
||||
}
|
||||
|
||||
std::string Time::DateTime::ToTimeString() const {
|
||||
std::string Time::DateTime::ToTimeString() const
|
||||
{
|
||||
char buf[16];
|
||||
int hour, minute, second;
|
||||
GetTimeParts(&hour, &minute, &second);
|
||||
|
@ -182,7 +200,8 @@ std::string Time::DateTime::ToTimeString() const {
|
|||
return std::string(buf);
|
||||
}
|
||||
|
||||
std::string Time::DateTime::ToStringISO8601() const {
|
||||
std::string Time::DateTime::ToStringISO8601() const
|
||||
{
|
||||
char buf[64];
|
||||
int year, month, day, hour, minute, second;
|
||||
GetDateParts(&year, &month, &day);
|
||||
|
|
|
@ -29,23 +29,25 @@ namespace Time {
|
|||
// and the passage of time. For example, leap seconds are not supported at all.
|
||||
// But... I'm pretty sure we don't need leap seconds for Pioneer.
|
||||
|
||||
enum TimeUnit : Sint64 {
|
||||
Microsecond = 1ll,
|
||||
Millisecond = 1000ll * Microsecond,
|
||||
Second = 1000ll * Millisecond,
|
||||
Minute = 60ll * Second,
|
||||
Hour = 60ll * Minute,
|
||||
Day = 24ll * Hour,
|
||||
Week = 7ll * Day
|
||||
};
|
||||
enum TimeUnit : Sint64 {
|
||||
Microsecond = 1ll,
|
||||
Millisecond = 1000ll * Microsecond,
|
||||
Second = 1000ll * Millisecond,
|
||||
Minute = 60ll * Second,
|
||||
Hour = 60ll * Minute,
|
||||
Day = 24ll * Hour,
|
||||
Week = 7ll * Day
|
||||
};
|
||||
|
||||
class TimeDelta;
|
||||
class DateTime;
|
||||
class TimeDelta;
|
||||
class DateTime;
|
||||
|
||||
class TimeDelta {
|
||||
class TimeDelta {
|
||||
public:
|
||||
TimeDelta(): m_delta(0) {}
|
||||
explicit TimeDelta(Sint64 t, TimeUnit unit=Second): m_delta(t*unit) {}
|
||||
TimeDelta() :
|
||||
m_delta(0) {}
|
||||
explicit TimeDelta(Sint64 t, TimeUnit unit = Second) :
|
||||
m_delta(t * unit) {}
|
||||
|
||||
Sint64 GetTotalWeeks() const { return (m_delta / Week); }
|
||||
Sint64 GetTotalDays() const { return (m_delta / Day); }
|
||||
|
@ -55,8 +57,16 @@ class TimeDelta {
|
|||
Sint64 GetTotalMilliseconds() const { return (m_delta / Millisecond); }
|
||||
Sint64 GetTotalMicroseconds() const { return (m_delta / Microsecond); }
|
||||
|
||||
TimeDelta &operator+=(const TimeDelta &x) { m_delta += x.m_delta; return *this; }
|
||||
TimeDelta &operator-=(const TimeDelta &x) { m_delta -= x.m_delta; return *this; }
|
||||
TimeDelta &operator+=(const TimeDelta &x)
|
||||
{
|
||||
m_delta += x.m_delta;
|
||||
return *this;
|
||||
}
|
||||
TimeDelta &operator-=(const TimeDelta &x)
|
||||
{
|
||||
m_delta -= x.m_delta;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend TimeDelta operator+(const TimeDelta &a, const TimeDelta &b) { return TimeDelta(a.m_delta + b.m_delta, TimeUnit(1)); }
|
||||
friend TimeDelta operator-(const TimeDelta &a, const TimeDelta &b) { return TimeDelta(a.m_delta - b.m_delta, TimeUnit(1)); }
|
||||
|
@ -66,17 +76,19 @@ class TimeDelta {
|
|||
|
||||
friend DateTime operator+(const DateTime &a, const TimeDelta &b);
|
||||
friend DateTime operator-(const DateTime &a, const TimeDelta &b);
|
||||
|
||||
private:
|
||||
friend class DateTime;
|
||||
Sint64 m_delta;
|
||||
};
|
||||
};
|
||||
|
||||
class DateTime {
|
||||
class DateTime {
|
||||
public:
|
||||
DateTime(): m_timestamp(-Sint64(24*60*60) * Sint64(400*365 + 97) * Sint64(Second)) {}
|
||||
DateTime() :
|
||||
m_timestamp(-Sint64(24 * 60 * 60) * Sint64(400 * 365 + 97) * Sint64(Second)) {}
|
||||
// month = 1 to 12
|
||||
// day = 1 to N where N is the number of days in the specified month and year
|
||||
DateTime(int year, int month, int day, int hour=0, int minute=0, int second=0, int microsecond=0);
|
||||
DateTime(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int microsecond = 0);
|
||||
DateTime(double gameTime);
|
||||
|
||||
void GetDateParts(int *year, int *month, int *day) const;
|
||||
|
@ -89,15 +101,29 @@ class DateTime {
|
|||
std::string ToStringISO8601() const;
|
||||
|
||||
friend TimeDelta operator-(const DateTime &a, const DateTime &b)
|
||||
{ return TimeDelta(a.m_timestamp - b.m_timestamp, TimeUnit(1)); }
|
||||
{
|
||||
return TimeDelta(a.m_timestamp - b.m_timestamp, TimeUnit(1));
|
||||
}
|
||||
friend DateTime operator+(const DateTime &a, const TimeDelta &b)
|
||||
{ return DateTime(a.m_timestamp + b.m_delta); }
|
||||
{
|
||||
return DateTime(a.m_timestamp + b.m_delta);
|
||||
}
|
||||
friend DateTime operator-(const DateTime &a, const TimeDelta &b)
|
||||
{ return DateTime(a.m_timestamp - b.m_delta); }
|
||||
{
|
||||
return DateTime(a.m_timestamp - b.m_delta);
|
||||
}
|
||||
friend DateTime operator+(const TimeDelta &a, const DateTime &b) { return (b + a); }
|
||||
|
||||
DateTime &operator+=(const TimeDelta &x) { m_timestamp += x.m_delta; return *this; }
|
||||
DateTime &operator-=(const TimeDelta &x) { m_timestamp -= x.m_delta; return *this; }
|
||||
DateTime &operator+=(const TimeDelta &x)
|
||||
{
|
||||
m_timestamp += x.m_delta;
|
||||
return *this;
|
||||
}
|
||||
DateTime &operator-=(const TimeDelta &x)
|
||||
{
|
||||
m_timestamp -= x.m_delta;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend bool operator<(const DateTime &a, const DateTime &b) { return (a.m_timestamp < b.m_timestamp); }
|
||||
friend bool operator<=(const DateTime &a, const DateTime &b) { return (a.m_timestamp <= b.m_timestamp); }
|
||||
|
@ -109,7 +135,8 @@ class DateTime {
|
|||
Sint64 GetTimestamp() const { return m_timestamp; }
|
||||
|
||||
private:
|
||||
explicit DateTime(Sint64 tstamp): m_timestamp(tstamp) {}
|
||||
explicit DateTime(Sint64 tstamp) :
|
||||
m_timestamp(tstamp) {}
|
||||
|
||||
// The timestamp is the number of microseconds since the epoch (2001-01-01T00:00:00Z)
|
||||
//
|
||||
|
@ -131,7 +158,7 @@ class DateTime {
|
|||
//
|
||||
// (Incidentally, this is the way all integer timestamps work, at least all the ones I've ever seen)
|
||||
Sint64 m_timestamp; // (units: microseconds; 0 means 2001-01-01T00:00:00Z)
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace Time
|
||||
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
#include "ShipCpanel.h"
|
||||
#include "graphics/Graphics.h"
|
||||
|
||||
DeathView::DeathView(Game* game): View(), m_game(game)
|
||||
DeathView::DeathView(Game *game) :
|
||||
View(),
|
||||
m_game(game)
|
||||
{
|
||||
float size[2];
|
||||
GetSizeRequested(size);
|
||||
|
@ -19,8 +21,8 @@ DeathView::DeathView(Game* game): View(), m_game(game)
|
|||
Pi::renderer->GetNearFarRange(znear, zfar);
|
||||
|
||||
const float fovY = Pi::config->Float("FOVVertical");
|
||||
m_cameraContext.Reset(new CameraContext(Graphics::GetScreenWidth(), Graphics::GetScreenHeight(), fovY, znear, zfar));
|
||||
m_camera.reset(new Camera(m_cameraContext, Pi::renderer));
|
||||
m_cameraContext.Reset(new CameraContext(Graphics::GetScreenWidth(), Graphics::GetScreenHeight(), fovY, znear, zfar));
|
||||
m_camera.reset(new Camera(m_cameraContext, Pi::renderer));
|
||||
}
|
||||
|
||||
DeathView::~DeathView() {}
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
#ifndef DEATH_VIEW_H
|
||||
#define DEATH_VIEW_H
|
||||
|
||||
#include "libs.h"
|
||||
#include "View.h"
|
||||
#include "Camera.h"
|
||||
#include "RefCounted.h"
|
||||
#include "View.h"
|
||||
#include "libs.h"
|
||||
|
||||
class Game;
|
||||
|
||||
class DeathView : public View {
|
||||
public:
|
||||
DeathView(Game* game);
|
||||
DeathView(Game *game);
|
||||
virtual ~DeathView();
|
||||
|
||||
void Init();
|
||||
|
@ -28,7 +28,7 @@ private:
|
|||
RefCountedPtr<CameraContext> m_cameraContext;
|
||||
std::unique_ptr<Camera> m_camera;
|
||||
float m_cameraDist;
|
||||
Game* m_game;
|
||||
Game *m_game;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
class DeleteEmitter : public LuaWrappable {
|
||||
public:
|
||||
DeleteEmitter() {}
|
||||
virtual ~DeleteEmitter() {
|
||||
virtual ~DeleteEmitter()
|
||||
{
|
||||
onDelete.emit();
|
||||
}
|
||||
|
||||
|
@ -26,8 +27,8 @@ public:
|
|||
mutable sigc::signal<void> onDelete;
|
||||
|
||||
private:
|
||||
// sigc++ signals cannot be copied, but long-standing design flaw means
|
||||
// they don't have a private copy constructor. we protect them ourselves
|
||||
// sigc++ signals cannot be copied, but long-standing design flaw means
|
||||
// they don't have a private copy constructor. we protect them ourselves
|
||||
DeleteEmitter(const DeleteEmitter &) {}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "DynamicBody.h"
|
||||
#include "Space.h"
|
||||
#include "FixedGuns.h"
|
||||
#include "Frame.h"
|
||||
#include "Planet.h"
|
||||
#include "Pi.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "Pi.h"
|
||||
#include "Planet.h"
|
||||
#include "Propulsion.h"
|
||||
#include "FixedGuns.h"
|
||||
#include "Space.h"
|
||||
#include "libs.h"
|
||||
|
||||
static const float KINETIC_ENERGY_MULT = 0.00001f;
|
||||
const double DynamicBody::DEFAULT_DRAG_COEFF = 0.1; // 'smooth sphere'
|
||||
|
||||
DynamicBody::DynamicBody()
|
||||
: ModelBody()
|
||||
, m_propulsion(nullptr)
|
||||
, m_fixedGuns(nullptr)
|
||||
DynamicBody::DynamicBody() :
|
||||
ModelBody(),
|
||||
m_propulsion(nullptr),
|
||||
m_fixedGuns(nullptr)
|
||||
{
|
||||
m_dragCoeff = DEFAULT_DRAG_COEFF;
|
||||
m_flags = Body::FLAG_CAN_MOVE_FRAME;
|
||||
|
@ -34,19 +34,21 @@ DynamicBody::DynamicBody()
|
|||
m_isMoving = true;
|
||||
m_atmosForce = vector3d(0.0);
|
||||
m_gravityForce = vector3d(0.0);
|
||||
m_externalForce = vector3d(0.0); // do external forces calc instead?
|
||||
m_externalForce = vector3d(0.0); // do external forces calc instead?
|
||||
m_lastForce = vector3d(0.0);
|
||||
m_lastTorque = vector3d(0.0);
|
||||
m_aiMessage = AIError::AIERROR_NONE;
|
||||
m_decelerating = false;
|
||||
for ( int i=0; i < Feature::MAX_FEATURE; i++ ) m_features[i] = false;
|
||||
for (int i = 0; i < Feature::MAX_FEATURE; i++)
|
||||
m_features[i] = false;
|
||||
}
|
||||
|
||||
void DynamicBody::AddFeature( Feature f ) {
|
||||
void DynamicBody::AddFeature(Feature f)
|
||||
{
|
||||
m_features[f] = true;
|
||||
if(f == Feature::PROPULSION && m_propulsion == nullptr) {
|
||||
if (f == Feature::PROPULSION && m_propulsion == nullptr) {
|
||||
m_propulsion.Reset(new Propulsion());
|
||||
} else if(f == Feature::FIXED_GUNS && m_fixedGuns == nullptr) {
|
||||
} else if (f == Feature::FIXED_GUNS && m_fixedGuns == nullptr) {
|
||||
m_fixedGuns.Reset(new FixedGuns());
|
||||
}
|
||||
}
|
||||
|
@ -115,32 +117,37 @@ void DynamicBody::LoadFromJson(const Json &jsonObj, Space *space)
|
|||
|
||||
m_aiMessage = AIError::AIERROR_NONE;
|
||||
m_decelerating = false;
|
||||
for ( int i=0; i < Feature::MAX_FEATURE; i++ ) m_features[i] = false;
|
||||
for (int i = 0; i < Feature::MAX_FEATURE; i++)
|
||||
m_features[i] = false;
|
||||
}
|
||||
|
||||
void DynamicBody::PostLoadFixup(Space *space)
|
||||
{
|
||||
Body::PostLoadFixup(space);
|
||||
m_oldPos = GetPosition();
|
||||
// CalcExternalForce(); // too dangerous
|
||||
// CalcExternalForce(); // too dangerous
|
||||
}
|
||||
|
||||
const Propulsion *DynamicBody::GetPropulsion() const {
|
||||
const Propulsion *DynamicBody::GetPropulsion() const
|
||||
{
|
||||
assert(m_propulsion != nullptr);
|
||||
return m_propulsion.Get();
|
||||
}
|
||||
|
||||
Propulsion *DynamicBody::GetPropulsion() {
|
||||
Propulsion *DynamicBody::GetPropulsion()
|
||||
{
|
||||
assert(m_propulsion != nullptr);
|
||||
return m_propulsion.Get();
|
||||
}
|
||||
|
||||
const FixedGuns *DynamicBody::GetFixedGuns() const {
|
||||
const FixedGuns *DynamicBody::GetFixedGuns() const
|
||||
{
|
||||
assert(m_fixedGuns != nullptr);
|
||||
return m_fixedGuns.Get();
|
||||
}
|
||||
|
||||
FixedGuns *DynamicBody::GetFixedGuns() {
|
||||
FixedGuns *DynamicBody::GetFixedGuns()
|
||||
{
|
||||
assert(m_fixedGuns != nullptr);
|
||||
return m_fixedGuns.Get();
|
||||
}
|
||||
|
@ -154,7 +161,7 @@ void DynamicBody::SetMass(double mass)
|
|||
{
|
||||
m_mass = mass;
|
||||
// This is solid sphere mass distribution, my friend
|
||||
m_angInertia = (2/5.0)*m_mass*m_massRadius*m_massRadius;
|
||||
m_angInertia = (2 / 5.0) * m_mass * m_massRadius * m_massRadius;
|
||||
}
|
||||
|
||||
void DynamicBody::SetFrame(Frame *f)
|
||||
|
@ -169,53 +176,54 @@ double DynamicBody::CalcAtmosphericForce(double dragCoeff) const
|
|||
Body *body = GetFrame()->GetBody();
|
||||
if (!body || !GetFrame()->IsRotFrame() || !body->IsType(Object::PLANET))
|
||||
return 0.0;
|
||||
Planet *planet = static_cast<Planet*>(body);
|
||||
Planet *planet = static_cast<Planet *>(body);
|
||||
double dist = GetPosition().Length();
|
||||
double speed = m_vel.Length();
|
||||
double pressure, density;
|
||||
planet->GetAtmosphericState(dist, &pressure, &density);
|
||||
const double radius = GetClipRadius(); // bogus, preserving behaviour
|
||||
const double radius = GetClipRadius(); // bogus, preserving behaviour
|
||||
const double area = radius;
|
||||
// ^^^ yes that is as stupid as it looks
|
||||
return 0.5*density*speed*speed*area*dragCoeff;
|
||||
return 0.5 * density * speed * speed * area * dragCoeff;
|
||||
}
|
||||
|
||||
void DynamicBody::CalcExternalForce()
|
||||
{
|
||||
// gravity
|
||||
if (!GetFrame()) return; // no external force if not in a frame
|
||||
if (!GetFrame()) return; // no external force if not in a frame
|
||||
Body *body = GetFrame()->GetBody();
|
||||
if (body && !body->IsType(Object::SPACESTATION)) { // they ought to have mass though...
|
||||
if (body && !body->IsType(Object::SPACESTATION)) { // they ought to have mass though...
|
||||
vector3d b1b2 = GetPosition();
|
||||
double m1m2 = GetMass() * body->GetMass();
|
||||
double invrsqr = 1.0 / b1b2.LengthSqr();
|
||||
double force = G*m1m2 * invrsqr;
|
||||
double force = G * m1m2 * invrsqr;
|
||||
m_externalForce = -b1b2 * sqrt(invrsqr) * force;
|
||||
}
|
||||
else m_externalForce = vector3d(0.0);
|
||||
} else
|
||||
m_externalForce = vector3d(0.0);
|
||||
m_gravityForce = m_externalForce;
|
||||
|
||||
// atmospheric drag
|
||||
if (body && GetFrame()->IsRotFrame() && body->IsType(Object::PLANET))
|
||||
{
|
||||
if (body && GetFrame()->IsRotFrame() && body->IsType(Object::PLANET)) {
|
||||
vector3d dragDir = -m_vel.NormalizedSafe();
|
||||
vector3d fDrag = CalcAtmosphericForce(m_dragCoeff)*dragDir;
|
||||
vector3d fDrag = CalcAtmosphericForce(m_dragCoeff) * dragDir;
|
||||
|
||||
// make this a bit less daft at high time accel
|
||||
// only allow atmosForce to increase by .1g per frame
|
||||
vector3d f1g = m_atmosForce + dragDir * GetMass();
|
||||
if (fDrag.LengthSqr() > f1g.LengthSqr()) m_atmosForce = f1g;
|
||||
else m_atmosForce = fDrag;
|
||||
if (fDrag.LengthSqr() > f1g.LengthSqr())
|
||||
m_atmosForce = f1g;
|
||||
else
|
||||
m_atmosForce = fDrag;
|
||||
|
||||
m_externalForce += m_atmosForce;
|
||||
}
|
||||
else m_atmosForce = vector3d(0.0);
|
||||
} else
|
||||
m_atmosForce = vector3d(0.0);
|
||||
|
||||
// centrifugal and coriolis forces for rotating frames
|
||||
if (GetFrame()->IsRotFrame()) {
|
||||
vector3d angRot(0, GetFrame()->GetAngSpeed(), 0);
|
||||
m_externalForce -= m_mass * angRot.Cross(angRot.Cross(GetPosition())); // centrifugal
|
||||
m_externalForce -= 2 * m_mass * angRot.Cross(GetVelocity()); // coriolis
|
||||
m_externalForce -= m_mass * angRot.Cross(angRot.Cross(GetPosition())); // centrifugal
|
||||
m_externalForce -= 2 * m_mass * angRot.Cross(GetVelocity()); // coriolis
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,16 +246,16 @@ void DynamicBody::TimeStepUpdate(const float timeStep)
|
|||
|
||||
SetPosition(GetPosition() + m_vel * double(timeStep));
|
||||
|
||||
//if (this->IsType(Object::PLAYER))
|
||||
//Output("pos = %.1f,%.1f,%.1f, vel = %.1f,%.1f,%.1f, force = %.1f,%.1f,%.1f, external = %.1f,%.1f,%.1f\n",
|
||||
// pos.x, pos.y, pos.z, m_vel.x, m_vel.y, m_vel.z, m_force.x, m_force.y, m_force.z,
|
||||
// m_externalForce.x, m_externalForce.y, m_externalForce.z);
|
||||
//if (this->IsType(Object::PLAYER))
|
||||
//Output("pos = %.1f,%.1f,%.1f, vel = %.1f,%.1f,%.1f, force = %.1f,%.1f,%.1f, external = %.1f,%.1f,%.1f\n",
|
||||
// pos.x, pos.y, pos.z, m_vel.x, m_vel.y, m_vel.z, m_force.x, m_force.y, m_force.z,
|
||||
// m_externalForce.x, m_externalForce.y, m_externalForce.z);
|
||||
|
||||
m_lastForce = m_force;
|
||||
m_lastTorque = m_torque;
|
||||
m_force = vector3d(0.0);
|
||||
m_torque = vector3d(0.0);
|
||||
CalcExternalForce(); // regenerate for new pos/vel
|
||||
CalcExternalForce(); // regenerate for new pos/vel
|
||||
} else {
|
||||
m_oldAngDisplacement = vector3d(0.0);
|
||||
}
|
||||
|
@ -257,15 +265,15 @@ void DynamicBody::TimeStepUpdate(const float timeStep)
|
|||
|
||||
void DynamicBody::UpdateInterpTransform(double alpha)
|
||||
{
|
||||
m_interpPos = alpha*GetPosition() + (1.0-alpha)*m_oldPos;
|
||||
m_interpPos = alpha * GetPosition() + (1.0 - alpha) * m_oldPos;
|
||||
|
||||
double len = m_oldAngDisplacement.Length() * (1.0-alpha);
|
||||
double len = m_oldAngDisplacement.Length() * (1.0 - alpha);
|
||||
if (len > 1e-16) {
|
||||
vector3d axis = m_oldAngDisplacement.Normalized();
|
||||
matrix3x3d rot = matrix3x3d::Rotate(-len, axis); // rotate backwards
|
||||
matrix3x3d rot = matrix3x3d::Rotate(-len, axis); // rotate backwards
|
||||
m_interpOrient = rot * GetOrient();
|
||||
}
|
||||
else m_interpOrient = GetOrient();
|
||||
} else
|
||||
m_interpOrient = GetOrient();
|
||||
}
|
||||
|
||||
void DynamicBody::SetMassDistributionFromModel()
|
||||
|
@ -273,7 +281,7 @@ void DynamicBody::SetMassDistributionFromModel()
|
|||
CollMesh *m = GetCollMesh();
|
||||
// XXX totally arbitrarily pick to distribute mass over a half
|
||||
// bounding sphere area
|
||||
m_massRadius = m->GetRadius()*0.5f;
|
||||
m_massRadius = m->GetRadius() * 0.5f;
|
||||
SetMass(m_mass);
|
||||
}
|
||||
|
||||
|
@ -317,7 +325,7 @@ bool DynamicBody::OnCollision(Object *o, Uint32 flags, double relVel)
|
|||
|
||||
double kineticEnergy = 0;
|
||||
if (o->IsType(Object::DYNAMICBODY)) {
|
||||
kineticEnergy = KINETIC_ENERGY_MULT * static_cast<DynamicBody*>(o)->GetMass() * relVel * relVel;
|
||||
kineticEnergy = KINETIC_ENERGY_MULT * static_cast<DynamicBody *>(o)->GetMass() * relVel * relVel;
|
||||
} else {
|
||||
kineticEnergy = KINETIC_ENERGY_MULT * m_mass * relVel * relVel;
|
||||
}
|
||||
|
@ -325,10 +333,9 @@ bool DynamicBody::OnCollision(Object *o, Uint32 flags, double relVel)
|
|||
// damage (kineticEnergy is being passed as a damage value) is measured in kilograms
|
||||
// ignore damage less than a gram except for cargo, which is very fragile.
|
||||
CollisionContact dummy;
|
||||
if (this->IsType(Object::CARGOBODY)){
|
||||
if (this->IsType(Object::CARGOBODY)) {
|
||||
OnDamage(o, float(kineticEnergy), dummy);
|
||||
}
|
||||
else if (kineticEnergy > 1e-3){
|
||||
} else if (kineticEnergy > 1e-3) {
|
||||
OnDamage(o, float(kineticEnergy), dummy);
|
||||
}
|
||||
|
||||
|
@ -336,7 +343,8 @@ bool DynamicBody::OnCollision(Object *o, Uint32 flags, double relVel)
|
|||
}
|
||||
|
||||
// return parameters for orbit of any body, gives both elliptic and hyperbolic trajectories
|
||||
Orbit DynamicBody::ComputeOrbit() const {
|
||||
Orbit DynamicBody::ComputeOrbit() const
|
||||
{
|
||||
const Frame *frame = this->GetFrame()->GetNonRotFrame();
|
||||
const double mass = frame->GetSystemBody()->GetMass();
|
||||
|
||||
|
|
|
@ -6,17 +6,18 @@
|
|||
|
||||
#include "Body.h"
|
||||
#include "ModelBody.h"
|
||||
#include "vector3.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "Orbit.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "vector3.h"
|
||||
|
||||
class Propulsion;
|
||||
class FixedGuns;
|
||||
|
||||
class DynamicBody: public ModelBody {
|
||||
class DynamicBody : public ModelBody {
|
||||
private:
|
||||
friend class Propulsion;
|
||||
friend class FixedGuns;
|
||||
|
||||
public:
|
||||
OBJDEF(DynamicBody, ModelBody, DYNAMICBODY);
|
||||
DynamicBody();
|
||||
|
@ -32,7 +33,7 @@ public:
|
|||
void SetMassDistributionFromModel();
|
||||
void SetMoving(bool isMoving) { m_isMoving = isMoving; }
|
||||
bool IsMoving() const { return m_isMoving; }
|
||||
virtual double GetMass() const override { return m_mass; } // XXX don't override this
|
||||
virtual double GetMass() const override { return m_mass; } // XXX don't override this
|
||||
virtual void TimeStepUpdate(const float timeStep) override;
|
||||
double CalcAtmosphericForce(double dragCoeff) const;
|
||||
void CalcExternalForce();
|
||||
|
@ -62,12 +63,17 @@ public:
|
|||
* in line 83)
|
||||
*/
|
||||
enum AIError { // <enum scope='Ship' name=ShipAIError prefix=AIERROR_ public>
|
||||
AIERROR_NONE=0,
|
||||
AIERROR_NONE = 0,
|
||||
AIERROR_GRAV_TOO_HIGH,
|
||||
AIERROR_REFUSED_PERM,
|
||||
AIERROR_ORBIT_IMPOSSIBLE
|
||||
};
|
||||
AIError AIMessage(AIError msg=AIERROR_NONE) { AIError tmp = m_aiMessage; m_aiMessage = msg; return tmp; }
|
||||
AIError AIMessage(AIError msg = AIERROR_NONE)
|
||||
{
|
||||
AIError tmp = m_aiMessage;
|
||||
m_aiMessage = msg;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
enum Feature {
|
||||
PROPULSION = 0,
|
||||
|
@ -75,13 +81,14 @@ public:
|
|||
MAX_FEATURE = 2,
|
||||
};
|
||||
|
||||
bool Have( Feature f ) const { return m_features[f]; };
|
||||
bool Have(Feature f) const { return m_features[f]; };
|
||||
void SetDecelerating(bool decel) { m_decelerating = decel; }
|
||||
const Propulsion *GetPropulsion() const;
|
||||
Propulsion *GetPropulsion();
|
||||
const FixedGuns *GetFixedGuns() const;
|
||||
FixedGuns *GetFixedGuns();
|
||||
void AddFeature( Feature f );
|
||||
void AddFeature(Feature f);
|
||||
|
||||
protected:
|
||||
virtual void SaveToJson(Json &jsonObj, Space *space) override;
|
||||
virtual void LoadFromJson(const Json &jsonObj, Space *space) override;
|
||||
|
@ -91,6 +98,7 @@ protected:
|
|||
|
||||
bool m_decelerating;
|
||||
AIError m_aiMessage;
|
||||
|
||||
private:
|
||||
vector3d m_oldPos;
|
||||
vector3d m_oldAngDisplacement;
|
||||
|
|
312
src/Easing.h
312
src/Easing.h
|
@ -15,146 +15,196 @@
|
|||
|
||||
namespace Easing {
|
||||
|
||||
// args are:
|
||||
// t: time point to calculate
|
||||
// b: value at beginning of range
|
||||
// c: change over range (ie end-begin)
|
||||
// d: duration of range
|
||||
// args are:
|
||||
// t: time point to calculate
|
||||
// b: value at beginning of range
|
||||
// c: change over range (ie end-begin)
|
||||
// d: duration of range
|
||||
|
||||
template <typename T> struct Function { typedef T (*Type)(T t, T b, T c, T d); };
|
||||
template <typename T>
|
||||
struct Function {
|
||||
typedef T (*Type)(T t, T b, T c, T d);
|
||||
};
|
||||
|
||||
// p(t) = t
|
||||
namespace Linear {
|
||||
template <typename T>
|
||||
T EaseIn(T t, T b, T c, T d)
|
||||
{
|
||||
return c * t / d + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseOut(T t, T b, T c, T d)
|
||||
{
|
||||
return c * t / d + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseInOut(T t, T b, T c, T d)
|
||||
{
|
||||
return c * t / d + b;
|
||||
}
|
||||
} // namespace Linear
|
||||
|
||||
// p(t) = t
|
||||
namespace Linear {
|
||||
template <typename T> T EaseIn(T t, T b, T c, T d) {
|
||||
return c*t/d + b;
|
||||
}
|
||||
template <typename T> T EaseOut(T t, T b, T c, T d) {
|
||||
return c*t/d + b;
|
||||
}
|
||||
template <typename T> T EaseInOut(T t, T b, T c, T d) {
|
||||
return c*t/d + b;
|
||||
}
|
||||
}
|
||||
// p(t) = t^2
|
||||
namespace Quad {
|
||||
template <typename T>
|
||||
T EaseIn(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d;
|
||||
return c * t * t + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseOut(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d;
|
||||
return -c * t * (t - 2) + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseInOut(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d / 2;
|
||||
if (t < 1) return ((c / 2) * (t * t)) + b;
|
||||
return -c / 2 * ((t - 1) * (t - 3) - 1) + b;
|
||||
}
|
||||
} // namespace Quad
|
||||
|
||||
// p(t) = t^2
|
||||
namespace Quad {
|
||||
template <typename T> T EaseIn(T t, T b, T c, T d) {
|
||||
t/=d;
|
||||
return c*t*t + b;
|
||||
}
|
||||
template <typename T> T EaseOut(T t, T b, T c, T d) {
|
||||
t/=d;
|
||||
return -c *t*(t-2) + b;
|
||||
}
|
||||
template <typename T> T EaseInOut(T t, T b, T c, T d) {
|
||||
t/=d/2;
|
||||
if (t < 1) return ((c/2)*(t*t)) + b;
|
||||
return -c/2 * ((t-1)*(t-3)-1) + b;
|
||||
}
|
||||
}
|
||||
// p(t) = t^3
|
||||
namespace Cubic {
|
||||
template <typename T>
|
||||
T EaseIn(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d;
|
||||
return c * t * t * t + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseOut(T t, T b, T c, T d)
|
||||
{
|
||||
t = t / d - 1;
|
||||
return c * (t * t * t + 1) + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseInOut(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d / 2;
|
||||
if (t < 1) return c / 2 * t * t * t + b;
|
||||
t -= 2;
|
||||
return c / 2 * (t * t * t + 2) + b;
|
||||
}
|
||||
} // namespace Cubic
|
||||
|
||||
// p(t) = t^3
|
||||
namespace Cubic {
|
||||
template <typename T> T EaseIn(T t, T b, T c, T d) {
|
||||
t/=d;
|
||||
return c*t*t*t + b;
|
||||
}
|
||||
template <typename T> T EaseOut(T t, T b, T c, T d) {
|
||||
t=t/d-1;
|
||||
return c*(t*t*t + 1) + b;
|
||||
}
|
||||
template <typename T> T EaseInOut(T t, T b, T c, T d) {
|
||||
t/=d/2;
|
||||
if (t < 1) return c/2*t*t*t + b;
|
||||
t-=2;
|
||||
return c/2*(t*t*t + 2) + b;
|
||||
}
|
||||
}
|
||||
// p(t) = t^4
|
||||
namespace Quart {
|
||||
template <typename T>
|
||||
T EaseIn(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d;
|
||||
return c * t * t * t * t + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseOut(T t, T b, T c, T d)
|
||||
{
|
||||
t = t / d - 1;
|
||||
return -c * (t * t * t * t - 1) + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseInOut(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d / 2;
|
||||
if (t < 1) return c / 2 * t * t * t * t + b;
|
||||
t -= 2;
|
||||
return -c / 2 * (t * t * t * t - 2) + b;
|
||||
}
|
||||
} // namespace Quart
|
||||
|
||||
// p(t) = t^4
|
||||
namespace Quart {
|
||||
template <typename T> T EaseIn(T t, T b, T c, T d) {
|
||||
t/=d;
|
||||
return c*t*t*t*t + b;
|
||||
}
|
||||
template <typename T> T EaseOut(T t, T b, T c, T d) {
|
||||
t=t/d-1;
|
||||
return -c * (t*t*t*t - 1) + b;
|
||||
}
|
||||
template <typename T> T EaseInOut(T t, T b, T c, T d) {
|
||||
t/=d/2;
|
||||
if (t < 1) return c/2*t*t*t*t + b;
|
||||
t-=2;
|
||||
return -c/2 * (t*t*t*t - 2) + b;
|
||||
}
|
||||
}
|
||||
// p(t) = t^5
|
||||
namespace Quint {
|
||||
template <typename T>
|
||||
T EaseIn(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d;
|
||||
return c * t * t * t * t * t + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseOut(T t, T b, T c, T d)
|
||||
{
|
||||
t = t / d - 1;
|
||||
return c * (t * t * t * t * t + 1) + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseInOut(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d / 2;
|
||||
if (t < 1) return c / 2 * t * t * t * t * t + b;
|
||||
t -= 2;
|
||||
return c / 2 * (t * t * t * t * t + 2) + b;
|
||||
}
|
||||
} // namespace Quint
|
||||
|
||||
// p(t) = t^5
|
||||
namespace Quint {
|
||||
template <typename T> T EaseIn(T t, T b, T c, T d) {
|
||||
t/=d;
|
||||
return c*t*t*t*t*t + b;
|
||||
}
|
||||
template <typename T> T EaseOut(T t, T b, T c, T d) {
|
||||
t=t/d-1;
|
||||
return c*(t*t*t*t*t + 1) + b;
|
||||
}
|
||||
template <typename T> T EaseInOut(T t, T b, T c, T d) {
|
||||
t/=d/2;
|
||||
if (t < 1) return c/2*t*t*t*t*t + b;
|
||||
t-=2;
|
||||
return c/2*(t*t*t*t*t + 2) + b;
|
||||
}
|
||||
}
|
||||
// p(t) = sin(t*pi/2)
|
||||
namespace Sine {
|
||||
template <typename T>
|
||||
T EaseIn(T t, T b, T c, T d)
|
||||
{
|
||||
return -c * cos(t / d * (M_PI / 2)) + c + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseOut(T t, T b, T c, T d)
|
||||
{
|
||||
return c * sin(t / d * (M_PI / 2)) + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseInOut(T t, T b, T c, T d)
|
||||
{
|
||||
return -c / 2 * (cos(M_PI * t / d) - 1) + b;
|
||||
}
|
||||
} // namespace Sine
|
||||
|
||||
// p(t) = sin(t*pi/2)
|
||||
namespace Sine {
|
||||
template <typename T> T EaseIn(T t, T b, T c, T d) {
|
||||
return -c * cos(t/d * (M_PI/2)) + c + b;
|
||||
}
|
||||
template <typename T> T EaseOut(T t, T b, T c, T d) {
|
||||
return c * sin(t/d * (M_PI/2)) + b;
|
||||
}
|
||||
template <typename T> T EaseInOut(T t, T b, T c, T d) {
|
||||
return -c/2 * (cos(M_PI*t/d) - 1) + b;
|
||||
}
|
||||
}
|
||||
// p(t) = 2^(10*(t-1))
|
||||
namespace Expo {
|
||||
template <typename T>
|
||||
T EaseIn(T t, T b, T c, T d)
|
||||
{
|
||||
return (is_zero_general(t)) ? b : c * pow(2, 10 * (t / d - 1)) + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseOut(T t, T b, T c, T d)
|
||||
{
|
||||
return (is_equal_general(t, d)) ? b + c : c * (-pow(2, -10 * t / d) + 1) + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseInOut(T t, T b, T c, T d)
|
||||
{
|
||||
if (is_zero_general(t)) return b;
|
||||
if (is_equal_general(t, d)) return b + c;
|
||||
t /= d / 2;
|
||||
if (t < 1) return c / 2 * pow(2, 10 * (t - 1)) + b;
|
||||
return c / 2 * (-pow(2, -10 * --t) + 2) + b;
|
||||
}
|
||||
} // namespace Expo
|
||||
|
||||
// p(t) = 2^(10*(t-1))
|
||||
namespace Expo {
|
||||
template <typename T> T EaseIn(T t, T b, T c, T d) {
|
||||
return (is_zero_general(t)) ? b : c * pow(2, 10 * (t/d - 1)) + b;
|
||||
}
|
||||
template <typename T> T EaseOut(T t, T b, T c, T d) {
|
||||
return (is_equal_general(t,d)) ? b+c : c * (-pow(2, -10 * t/d) + 1) + b;
|
||||
}
|
||||
template <typename T> T EaseInOut(T t, T b, T c, T d) {
|
||||
if (is_zero_general(t)) return b;
|
||||
if (is_equal_general(t,d)) return b+c;
|
||||
t/=d/2;
|
||||
if (t < 1) return c/2 * pow(2, 10 * (t - 1)) + b;
|
||||
return c/2 * (-pow(2, -10 * --t) + 2) + b;
|
||||
}
|
||||
}
|
||||
// p(t) = 1-sqrt(1-t^2)
|
||||
namespace Circ {
|
||||
template <typename T>
|
||||
T EaseIn(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d;
|
||||
return -c * (sqrt(1 - t * t) - 1) + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseOut(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d;
|
||||
return c * (sqrt(1 - (t - 1) * (t - 1))) + b;
|
||||
}
|
||||
template <typename T>
|
||||
T EaseInOut(T t, T b, T c, T d)
|
||||
{
|
||||
t /= d / 2;
|
||||
if (t < 1) return -c / 2 * (sqrt(1 - t * t) - 1) + b;
|
||||
return c / 2 * (sqrt(1 - (t - 2) * (t - 2)) + 1) + b;
|
||||
}
|
||||
} // namespace Circ
|
||||
|
||||
// p(t) = 1-sqrt(1-t^2)
|
||||
namespace Circ {
|
||||
template <typename T> T EaseIn(T t, T b, T c, T d) {
|
||||
t/=d;
|
||||
return -c * (sqrt(1 - t*t) - 1) + b;
|
||||
}
|
||||
template <typename T> T EaseOut(T t, T b, T c, T d) {
|
||||
t/=d;
|
||||
return c * (sqrt(1 - (t-1)*(t-1))) + b;
|
||||
}
|
||||
template <typename T> T EaseInOut(T t, T b, T c, T d) {
|
||||
t/=d/2;
|
||||
if (t < 1) return -c/2 * (sqrt(1 - t*t) - 1) + b;
|
||||
return c/2 * (sqrt(1 - (t-2)*(t-2)) + 1) + b;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Easing
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,53 +3,53 @@
|
|||
|
||||
#include "enum_table.h"
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace EnumStrings {
|
||||
|
||||
static std::map< std::string, std::map<int,std::string> > enumStrings;
|
||||
static std::map< std::string, std::map<std::string,int> > enumValues;
|
||||
static std::map<std::string, std::map<int, std::string>> enumStrings;
|
||||
static std::map<std::string, std::map<std::string, int>> enumValues;
|
||||
|
||||
void Init()
|
||||
{
|
||||
for (const EnumTable *table = ENUM_TABLES; table->name; table++) {
|
||||
std::map<int,std::string> &stringMap = enumStrings[table->name];
|
||||
std::map<std::string,int> &valueMap = enumValues[table->name];
|
||||
void Init()
|
||||
{
|
||||
for (const EnumTable *table = ENUM_TABLES; table->name; table++) {
|
||||
std::map<int, std::string> &stringMap = enumStrings[table->name];
|
||||
std::map<std::string, int> &valueMap = enumValues[table->name];
|
||||
|
||||
for (const EnumItem *item = table->first; item->name; item++) {
|
||||
stringMap.insert(std::make_pair(item->value, item->name));
|
||||
valueMap.insert(std::make_pair(item->name, item->value));
|
||||
for (const EnumItem *item = table->first; item->name; item++) {
|
||||
stringMap.insert(std::make_pair(item->value, item->name));
|
||||
valueMap.insert(std::make_pair(item->name, item->value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *GetString(const char *ns, int value)
|
||||
{
|
||||
std::map< std::string, std::map<int,std::string> >::const_iterator tableIter = enumStrings.find(ns);
|
||||
if (tableIter == enumStrings.end())
|
||||
return 0;
|
||||
const char *GetString(const char *ns, int value)
|
||||
{
|
||||
std::map<std::string, std::map<int, std::string>>::const_iterator tableIter = enumStrings.find(ns);
|
||||
if (tableIter == enumStrings.end())
|
||||
return 0;
|
||||
|
||||
const std::map<int,std::string> &table = tableIter->second;
|
||||
std::map<int,std::string>::const_iterator e = table.find(value);
|
||||
if (e == table.end())
|
||||
return 0;
|
||||
const std::map<int, std::string> &table = tableIter->second;
|
||||
std::map<int, std::string>::const_iterator e = table.find(value);
|
||||
if (e == table.end())
|
||||
return 0;
|
||||
|
||||
return e->second.c_str();
|
||||
}
|
||||
return e->second.c_str();
|
||||
}
|
||||
|
||||
int GetValue(const char *ns, const char *name)
|
||||
{
|
||||
std::map< std::string, std::map<std::string,int> >::const_iterator tableIter = enumValues.find(ns);
|
||||
if (tableIter == enumValues.end())
|
||||
return -1;
|
||||
int GetValue(const char *ns, const char *name)
|
||||
{
|
||||
std::map<std::string, std::map<std::string, int>>::const_iterator tableIter = enumValues.find(ns);
|
||||
if (tableIter == enumValues.end())
|
||||
return -1;
|
||||
|
||||
const std::map<std::string,int> &table = tableIter->second;
|
||||
std::map<std::string,int>::const_iterator e = table.find(name);
|
||||
if (e == table.end())
|
||||
return -1;
|
||||
const std::map<std::string, int> &table = tableIter->second;
|
||||
std::map<std::string, int>::const_iterator e = table.find(name);
|
||||
if (e == table.end())
|
||||
return -1;
|
||||
|
||||
return e->second;
|
||||
}
|
||||
return e->second;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace EnumStrings
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
|
||||
namespace EnumStrings {
|
||||
|
||||
void Init();
|
||||
const char *GetString(const char *ns, int value);
|
||||
int GetValue(const char *ns, const char *name);
|
||||
void Init();
|
||||
const char *GetString(const char *ns, int value);
|
||||
int GetValue(const char *ns, const char *name);
|
||||
|
||||
}
|
||||
} // namespace EnumStrings
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,19 +4,19 @@
|
|||
#include "FaceParts.h"
|
||||
#include "FileSystem.h"
|
||||
#include "SDLWrappers.h"
|
||||
#include "utils.h"
|
||||
#include "libs.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace {
|
||||
static const int MAX_GENDERS = 6;
|
||||
static const int MAX_RACES = 16;
|
||||
static const int MAX_SPECIES = 10;
|
||||
static const Uint32 GENDER_SHIFT = 0;
|
||||
static const Uint32 GENDER_MASK = ((1u << MAX_GENDERS) - 1u) << GENDER_SHIFT;
|
||||
static const Uint32 RACE_SHIFT = GENDER_SHIFT + MAX_GENDERS;
|
||||
static const Uint32 RACE_MASK = ((1u << MAX_RACES) - 1u) << RACE_SHIFT;
|
||||
static const Uint32 GENDER_SHIFT = 0;
|
||||
static const Uint32 GENDER_MASK = ((1u << MAX_GENDERS) - 1u) << GENDER_SHIFT;
|
||||
static const Uint32 RACE_SHIFT = GENDER_SHIFT + MAX_GENDERS;
|
||||
static const Uint32 RACE_MASK = ((1u << MAX_RACES) - 1u) << RACE_SHIFT;
|
||||
static const Uint32 SPECIES_SHIFT = RACE_SHIFT + MAX_RACES;
|
||||
static const Uint32 SPECIES_MASK = ((1u << MAX_SPECIES) - 1u) << SPECIES_SHIFT;
|
||||
static const Uint32 SPECIES_MASK = ((1u << MAX_SPECIES) - 1u) << SPECIES_SHIFT;
|
||||
|
||||
// You can never have too many static_asserts, right?
|
||||
static_assert(((MAX_GENDERS + MAX_RACES + MAX_SPECIES) == 32), "unused bits in the face part selector");
|
||||
|
@ -29,15 +29,20 @@ namespace {
|
|||
Uint32 selector; // a bitmask indicating which species, races and genders can use this part
|
||||
SDLSurfacePtr part;
|
||||
|
||||
Part(): selector(0u) {}
|
||||
Part(const Uint32 sel, SDLSurfacePtr im): selector(sel), part(im) {}
|
||||
Part() :
|
||||
selector(0u) {}
|
||||
Part(const Uint32 sel, SDLSurfacePtr im) :
|
||||
selector(sel),
|
||||
part(im) {}
|
||||
};
|
||||
|
||||
struct SpeciesInfo {
|
||||
int num_races;
|
||||
int num_genders;
|
||||
|
||||
SpeciesInfo(int nraces, int ngenders): num_races(nraces), num_genders(ngenders) {}
|
||||
SpeciesInfo(int nraces, int ngenders) :
|
||||
num_races(nraces),
|
||||
num_genders(ngenders) {}
|
||||
};
|
||||
|
||||
class PartDb {
|
||||
|
@ -57,25 +62,40 @@ namespace {
|
|||
|
||||
void Clear();
|
||||
void Scan();
|
||||
|
||||
private:
|
||||
void ScanSpecies(const std::string &dir, int species_idx);
|
||||
void ScanParts(std::vector<Part> &output, const int species_idx, const int race_idx, const std::string &path, const char *prefix);
|
||||
void ScanGenderedParts(std::vector<Part> &output, const int species_idx, const int race_idx, const std::string &path, const char *prefix);
|
||||
};
|
||||
|
||||
static Uint32 _make_selector(int species, int race, int gender) {
|
||||
static Uint32 _make_selector(int species, int race, int gender)
|
||||
{
|
||||
assert(species < MAX_SPECIES);
|
||||
assert(race < MAX_RACES);
|
||||
assert(gender < MAX_GENDERS);
|
||||
|
||||
Uint32 mask = 0u;
|
||||
if (species < 0) { mask |= SPECIES_MASK; } else { mask |= (1u << (species + SPECIES_SHIFT)); }
|
||||
if (race < 0) { mask |= RACE_MASK; } else { mask |= (1u << (race + RACE_SHIFT)); }
|
||||
if (gender < 0) { mask |= GENDER_MASK; } else { mask |= (1u << (gender + GENDER_SHIFT)); }
|
||||
if (species < 0) {
|
||||
mask |= SPECIES_MASK;
|
||||
} else {
|
||||
mask |= (1u << (species + SPECIES_SHIFT));
|
||||
}
|
||||
if (race < 0) {
|
||||
mask |= RACE_MASK;
|
||||
} else {
|
||||
mask |= (1u << (race + RACE_SHIFT));
|
||||
}
|
||||
if (gender < 0) {
|
||||
mask |= GENDER_MASK;
|
||||
} else {
|
||||
mask |= (1u << (gender + GENDER_SHIFT));
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
static int _count_parts(const std::vector<Part> &parts, const Uint32 selector) {
|
||||
static int _count_parts(const std::vector<Part> &parts, const Uint32 selector)
|
||||
{
|
||||
int count = 0;
|
||||
for (const auto &part : parts) {
|
||||
if ((selector & part.selector) == selector) ++count;
|
||||
|
@ -83,10 +103,13 @@ namespace {
|
|||
return count;
|
||||
}
|
||||
|
||||
static SDL_Surface *_get_part(const std::vector<Part> &parts, const Uint32 selector, int index) {
|
||||
static SDL_Surface *_get_part(const std::vector<Part> &parts, const Uint32 selector, int index)
|
||||
{
|
||||
for (const auto &part : parts) {
|
||||
if ((selector & part.selector) == selector) {
|
||||
if (!index) { return part.part.Get(); }
|
||||
if (!index) {
|
||||
return part.part.Get();
|
||||
}
|
||||
--index;
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +123,7 @@ namespace {
|
|||
SDL_Rect destrec = { 0, 0, 0, 0 };
|
||||
// if the source is the full size, then ignore the offset
|
||||
if ((source->w == FaceParts::FACE_WIDTH) &&
|
||||
(source->h == FaceParts::FACE_HEIGHT)) {
|
||||
(source->h == FaceParts::FACE_HEIGHT)) {
|
||||
destrec.x = 0;
|
||||
destrec.y = 0;
|
||||
} else {
|
||||
|
@ -115,7 +138,8 @@ namespace {
|
|||
|
||||
namespace fs = FileSystem;
|
||||
|
||||
void PartDb::Clear() {
|
||||
void PartDb::Clear()
|
||||
{
|
||||
species.clear();
|
||||
heads.clear();
|
||||
eyes.clear();
|
||||
|
@ -129,7 +153,8 @@ void PartDb::Clear() {
|
|||
|
||||
static const char BACKGROUND_GENERAL_PATH[] = "facegen/backgrounds/general.png";
|
||||
|
||||
void PartDb::Scan() {
|
||||
void PartDb::Scan()
|
||||
{
|
||||
Clear();
|
||||
|
||||
background_general = LoadSurfaceFromFile(BACKGROUND_GENERAL_PATH);
|
||||
|
@ -151,7 +176,8 @@ void PartDb::Scan() {
|
|||
}
|
||||
}
|
||||
|
||||
void PartDb::ScanSpecies(const std::string &basedir, const int species_idx) {
|
||||
void PartDb::ScanSpecies(const std::string &basedir, const int species_idx)
|
||||
{
|
||||
int race_count = 0;
|
||||
const auto flags = fs::FileEnumerator::IncludeDirs | fs::FileEnumerator::ExcludeFiles;
|
||||
for (fs::FileEnumerator dirs(fs::gameDataFiles, basedir, flags); !dirs.Finished(); dirs.Next()) {
|
||||
|
@ -183,7 +209,8 @@ void PartDb::ScanSpecies(const std::string &basedir, const int species_idx) {
|
|||
species.push_back(SpeciesInfo(race_count, 2)); // XXX currently we hardcode genders = 2
|
||||
}
|
||||
|
||||
void PartDb::ScanParts(std::vector<Part> &output, const int species_idx, const int race_idx, const std::string &path, const char *prefix) {
|
||||
void PartDb::ScanParts(std::vector<Part> &output, const int species_idx, const int race_idx, const std::string &path, const char *prefix)
|
||||
{
|
||||
const Uint32 selector = _make_selector(species_idx, race_idx, -1);
|
||||
for (fs::FileEnumerator files(fs::gameDataFiles, path); !files.Finished(); files.Next()) {
|
||||
const std::string &name = files.Current().GetName();
|
||||
|
@ -198,7 +225,8 @@ void PartDb::ScanParts(std::vector<Part> &output, const int species_idx, const i
|
|||
}
|
||||
}
|
||||
|
||||
void PartDb::ScanGenderedParts(std::vector<Part> &output, const int species_idx, const int race_idx, const std::string &path, const char *prefix) {
|
||||
void PartDb::ScanGenderedParts(std::vector<Part> &output, const int species_idx, const int race_idx, const std::string &path, const char *prefix)
|
||||
{
|
||||
const int prefix_len = strlen(prefix);
|
||||
for (fs::FileEnumerator files(fs::gameDataFiles, path); !files.Finished(); files.Next()) {
|
||||
const std::string &name = files.Current().GetName();
|
||||
|
@ -243,53 +271,65 @@ void FaceParts::Uninit()
|
|||
s_partdb = nullptr;
|
||||
}
|
||||
|
||||
int FaceParts::NumSpecies() {
|
||||
int FaceParts::NumSpecies()
|
||||
{
|
||||
return s_partdb->species.size();
|
||||
}
|
||||
|
||||
int FaceParts::NumGenders(const int speciesIdx) {
|
||||
int FaceParts::NumGenders(const int speciesIdx)
|
||||
{
|
||||
assert(speciesIdx >= 0 && speciesIdx < NumSpecies());
|
||||
return s_partdb->species[speciesIdx].num_genders;
|
||||
}
|
||||
|
||||
int FaceParts::NumRaces(const int speciesIdx) {
|
||||
int FaceParts::NumRaces(const int speciesIdx)
|
||||
{
|
||||
assert(speciesIdx >= 0 && speciesIdx < NumSpecies());
|
||||
return s_partdb->species[speciesIdx].num_races;
|
||||
}
|
||||
|
||||
int FaceParts::NumHeads(const int speciesIdx, const int raceIdx, const int genderIdx) {
|
||||
int FaceParts::NumHeads(const int speciesIdx, const int raceIdx, const int genderIdx)
|
||||
{
|
||||
return _count_parts(s_partdb->heads, _make_selector(speciesIdx, raceIdx, genderIdx));
|
||||
}
|
||||
|
||||
int FaceParts::NumEyes(const int speciesIdx, const int raceIdx, const int genderIdx) {
|
||||
int FaceParts::NumEyes(const int speciesIdx, const int raceIdx, const int genderIdx)
|
||||
{
|
||||
return _count_parts(s_partdb->eyes, _make_selector(speciesIdx, raceIdx, genderIdx));
|
||||
}
|
||||
|
||||
int FaceParts::NumNoses(const int speciesIdx, const int raceIdx, const int genderIdx) {
|
||||
int FaceParts::NumNoses(const int speciesIdx, const int raceIdx, const int genderIdx)
|
||||
{
|
||||
return _count_parts(s_partdb->noses, _make_selector(speciesIdx, raceIdx, genderIdx));
|
||||
}
|
||||
|
||||
int FaceParts::NumMouths(const int speciesIdx, const int raceIdx, const int genderIdx) {
|
||||
int FaceParts::NumMouths(const int speciesIdx, const int raceIdx, const int genderIdx)
|
||||
{
|
||||
return _count_parts(s_partdb->mouths, _make_selector(speciesIdx, raceIdx, genderIdx));
|
||||
}
|
||||
|
||||
int FaceParts::NumHairstyles(const int speciesIdx, const int raceIdx, const int genderIdx) {
|
||||
int FaceParts::NumHairstyles(const int speciesIdx, const int raceIdx, const int genderIdx)
|
||||
{
|
||||
return _count_parts(s_partdb->hairstyles, _make_selector(speciesIdx, raceIdx, genderIdx));
|
||||
}
|
||||
|
||||
int FaceParts::NumClothes(const int speciesIdx, const int raceIdx, const int genderIdx) {
|
||||
int FaceParts::NumClothes(const int speciesIdx, const int raceIdx, const int genderIdx)
|
||||
{
|
||||
return _count_parts(s_partdb->clothes, _make_selector(speciesIdx, raceIdx, genderIdx));
|
||||
}
|
||||
|
||||
int FaceParts::NumAccessories(const int speciesIdx, const int raceIdx, const int genderIdx) {
|
||||
int FaceParts::NumAccessories(const int speciesIdx, const int raceIdx, const int genderIdx)
|
||||
{
|
||||
return _count_parts(s_partdb->accessories, _make_selector(speciesIdx, raceIdx, genderIdx));
|
||||
}
|
||||
|
||||
int FaceParts::NumArmour(const int speciesIdx, const int raceIdx, const int genderIdx) {
|
||||
int FaceParts::NumArmour(const int speciesIdx, const int raceIdx, const int genderIdx)
|
||||
{
|
||||
return _count_parts(s_partdb->armour, _make_selector(speciesIdx, raceIdx, genderIdx));
|
||||
}
|
||||
|
||||
static void _pick(Random &rng, int &inout_value, const int limit) {
|
||||
static void _pick(Random &rng, int &inout_value, const int limit)
|
||||
{
|
||||
assert(limit > 0);
|
||||
// we always run the RNG, even if the result is not needed, because that way
|
||||
// the output (index) for a particular component should be fixed for a given seed,
|
||||
|
@ -303,7 +343,8 @@ static void _pick(Random &rng, int &inout_value, const int limit) {
|
|||
}
|
||||
}
|
||||
|
||||
void FaceParts::PickFaceParts(FaceDescriptor &inout_face, const Uint32 seed) {
|
||||
void FaceParts::PickFaceParts(FaceDescriptor &inout_face, const Uint32 seed)
|
||||
{
|
||||
Random rand(seed);
|
||||
|
||||
_pick(rand, inout_face.species, NumSpecies());
|
||||
|
@ -320,13 +361,16 @@ void FaceParts::PickFaceParts(FaceDescriptor &inout_face, const Uint32 seed) {
|
|||
|
||||
const bool has_accessories = (rand.Int32() & 1);
|
||||
_pick(rand, inout_face.accessories, _count_parts(s_partdb->accessories, selector));
|
||||
if (!has_accessories) { inout_face.accessories = 0; }
|
||||
if (!has_accessories) {
|
||||
inout_face.accessories = 0;
|
||||
}
|
||||
|
||||
_pick(rand, inout_face.clothes, _count_parts(s_partdb->clothes, selector));
|
||||
_pick(rand, inout_face.armour, _count_parts(s_partdb->armour, selector));
|
||||
}
|
||||
|
||||
void FaceParts::BuildFaceImage(SDL_Surface *faceIm, const FaceDescriptor &face, bool armoured) {
|
||||
void FaceParts::BuildFaceImage(SDL_Surface *faceIm, const FaceDescriptor &face, bool armoured)
|
||||
{
|
||||
const Uint32 selector = _make_selector(face.species, face.race, face.gender);
|
||||
|
||||
_blit_image(faceIm, s_partdb->background_general.Get(), 0, 0);
|
||||
|
|
|
@ -55,6 +55,6 @@ namespace FaceParts {
|
|||
|
||||
void PickFaceParts(FaceDescriptor &inout_face, const Uint32 seed);
|
||||
void BuildFaceImage(SDL_Surface *faceIm, const FaceDescriptor &face, bool armoured);
|
||||
}
|
||||
} // namespace FaceParts
|
||||
|
||||
#endif
|
||||
|
|
260
src/Factions.cpp
260
src/Factions.cpp
|
@ -2,30 +2,30 @@
|
|||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "Factions.h"
|
||||
#include "galaxy/Sector.h"
|
||||
#include "galaxy/SystemPath.h"
|
||||
#include "galaxy/CustomSystem.h"
|
||||
#include "galaxy/Galaxy.h"
|
||||
#include "galaxy/Sector.h"
|
||||
#include "galaxy/SystemPath.h"
|
||||
|
||||
#include "enum_table.h"
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "Lang.h"
|
||||
#include "LuaConstants.h"
|
||||
#include "LuaFixed.h"
|
||||
#include "LuaUtils.h"
|
||||
#include "LuaVector.h"
|
||||
#include "LuaFixed.h"
|
||||
#include "LuaConstants.h"
|
||||
#include "Polit.h"
|
||||
#include "FileSystem.h"
|
||||
#include "Lang.h"
|
||||
#include "Pi.h"
|
||||
#include <set>
|
||||
#include "Polit.h"
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
const Uint32 Faction::BAD_FACTION_IDX = UINT_MAX;
|
||||
const Color Faction::BAD_FACTION_COLOUR = Color(204,204,204,128);
|
||||
const float Faction::FACTION_BASE_ALPHA = 0.40f;
|
||||
const Uint32 Faction::BAD_FACTION_IDX = UINT_MAX;
|
||||
const Color Faction::BAD_FACTION_COLOUR = Color(204, 204, 204, 128);
|
||||
const float Faction::FACTION_BASE_ALPHA = 0.40f;
|
||||
const double Faction::FACTION_CURRENT_YEAR = 3200;
|
||||
|
||||
//#define DUMP_FACTIONS
|
||||
|
@ -43,10 +43,11 @@ struct FactionBuilder {
|
|||
|
||||
static const char LuaFaction_TypeName[] = "Faction";
|
||||
|
||||
static FactionsDatabase* s_activeFactionsDatabase = nullptr;
|
||||
static FactionsDatabase *s_activeFactionsDatabase = nullptr;
|
||||
|
||||
static FactionBuilder *l_fac_check_builder(lua_State *L, int idx) {
|
||||
FactionBuilder *facbld = static_cast<FactionBuilder*>(
|
||||
static FactionBuilder *l_fac_check_builder(lua_State *L, int idx)
|
||||
{
|
||||
FactionBuilder *facbld = static_cast<FactionBuilder *>(
|
||||
luaL_checkudata(L, idx, LuaFaction_TypeName));
|
||||
assert(facbld->fac);
|
||||
return facbld;
|
||||
|
@ -61,10 +62,10 @@ static int l_fac_new(lua_State *L)
|
|||
{
|
||||
const char *name = luaL_checkstring(L, 2);
|
||||
|
||||
FactionBuilder *facbld = static_cast<FactionBuilder*>(lua_newuserdata(L, sizeof(*facbld)));
|
||||
FactionBuilder *facbld = static_cast<FactionBuilder *>(lua_newuserdata(L, sizeof(*facbld)));
|
||||
facbld->fac = new Faction(s_activeFactionsDatabase->GetGalaxy());
|
||||
facbld->registered = false;
|
||||
facbld->skip = false;
|
||||
facbld->skip = false;
|
||||
luaL_setmetatable(L, LuaFaction_TypeName);
|
||||
|
||||
facbld->fac->name = name;
|
||||
|
@ -73,27 +74,33 @@ static int l_fac_new(lua_State *L)
|
|||
}
|
||||
|
||||
#define LFAC_FIELD_SETTER_FIXED(luaname, fieldname) \
|
||||
static int l_fac_ ## luaname (lua_State *L) { \
|
||||
static int l_fac_##luaname(lua_State *L) \
|
||||
{ \
|
||||
Faction *fac = l_fac_check(L, 1); \
|
||||
const fixed *value = LuaFixed::CheckFromLua(L, 2); \
|
||||
fac->fieldname = *value; \
|
||||
lua_settop(L, 1); return 1; \
|
||||
lua_settop(L, 1); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define LFAC_FIELD_SETTER_FLOAT(luaname, fieldname) \
|
||||
static int l_fac_ ## luaname (lua_State *L) { \
|
||||
Faction *fac = l_fac_check(L, 1); \
|
||||
double value = luaL_checknumber(L, 2); \
|
||||
fac->fieldname = value; \
|
||||
lua_settop(L, 1); return 1; \
|
||||
#define LFAC_FIELD_SETTER_FLOAT(luaname, fieldname) \
|
||||
static int l_fac_##luaname(lua_State *L) \
|
||||
{ \
|
||||
Faction *fac = l_fac_check(L, 1); \
|
||||
double value = luaL_checknumber(L, 2); \
|
||||
fac->fieldname = value; \
|
||||
lua_settop(L, 1); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define LFAC_FIELD_SETTER_INT(luaname, fieldname) \
|
||||
static int l_fac_ ## luaname (lua_State *L) { \
|
||||
Faction *fac = l_fac_check(L, 1); \
|
||||
int value = luaL_checkinteger(L, 2); \
|
||||
fac->fieldname = value; \
|
||||
lua_settop(L, 1); return 1; \
|
||||
#define LFAC_FIELD_SETTER_INT(luaname, fieldname) \
|
||||
static int l_fac_##luaname(lua_State *L) \
|
||||
{ \
|
||||
Faction *fac = l_fac_check(L, 1); \
|
||||
int value = luaL_checkinteger(L, 2); \
|
||||
fac->fieldname = value; \
|
||||
lua_settop(L, 1); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
static int l_fac_description_short(lua_State *L)
|
||||
|
@ -118,7 +125,7 @@ static int l_fac_govtype_weight(lua_State *L)
|
|||
Faction *fac = l_fac_check(L, 1);
|
||||
const char *typeName = luaL_checkstring(L, 2);
|
||||
const Polit::GovType g = static_cast<Polit::GovType>(LuaConstants::GetConstant(L, "PolitGovType", typeName));
|
||||
const Sint32 weight = luaL_checkinteger(L, 3); // signed as we will need to compare with signed out of Random.Int32
|
||||
const Sint32 weight = luaL_checkinteger(L, 3); // signed as we will need to compare with signed out of Random.Int32
|
||||
|
||||
if (g < Polit::GOV_RAND_MIN || g > Polit::GOV_RAND_MAX) {
|
||||
pi_lua_warn(L,
|
||||
|
@ -142,7 +149,7 @@ static int l_fac_govtype_weight(lua_State *L)
|
|||
}
|
||||
|
||||
// sector(x,y,x) + system index + body index = location in a (custom?) system of homeworld
|
||||
static int l_fac_homeworld (lua_State *L)
|
||||
static int l_fac_homeworld(lua_State *L)
|
||||
{
|
||||
FactionBuilder *facbld = l_fac_check_builder(L, 1);
|
||||
Faction *fac = facbld->fac;
|
||||
|
@ -158,12 +165,12 @@ static int l_fac_homeworld (lua_State *L)
|
|||
fac->SetBestFitHomeworld(x, y, z, si, bi, +1);
|
||||
if (!fac->homeworld.HasValidSystem()) fac->SetBestFitHomeworld(x, y, z, si, bi, -1);
|
||||
|
||||
facbld->skip = !fac->homeworld.HasValidSystem(); // wasn't a valid system
|
||||
facbld->skip = !fac->homeworld.HasValidSystem(); // wasn't a valid system
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LFAC_FIELD_SETTER_FLOAT(foundingDate, foundingDate) // date faction came into existence
|
||||
LFAC_FIELD_SETTER_FLOAT(foundingDate, foundingDate) // date faction came into existence
|
||||
LFAC_FIELD_SETTER_FLOAT(expansionRate, expansionRate) // lightyears per year that the volume expands.
|
||||
|
||||
static int l_fac_military_name(lua_State *L)
|
||||
|
@ -199,7 +206,7 @@ static int l_fac_illegal_goods_probability(lua_State *L)
|
|||
Faction *fac = l_fac_check(L, 1);
|
||||
const char *typeName = luaL_checkstring(L, 2);
|
||||
const GalacticEconomy::Commodity e = static_cast<GalacticEconomy::Commodity>(
|
||||
LuaConstants::GetConstant(L, "CommodityType", typeName));
|
||||
LuaConstants::GetConstant(L, "CommodityType", typeName));
|
||||
const Uint32 probability = luaL_checkunsigned(L, 3);
|
||||
|
||||
if (probability > 100) {
|
||||
|
@ -223,7 +230,7 @@ static int l_fac_colour(lua_State *L)
|
|||
const float g = luaL_checknumber(L, 3);
|
||||
const float b = luaL_checknumber(L, 4);
|
||||
|
||||
fac->colour = Color(r*255,g*255,b*255);
|
||||
fac->colour = Color(r * 255, g * 255, b * 255);
|
||||
|
||||
lua_settop(L, 1);
|
||||
|
||||
|
@ -242,8 +249,7 @@ static int l_fac_claim(lua_State *L)
|
|||
|
||||
path.systemIndex = -99; // magic number, claim whole sector
|
||||
|
||||
if (lua_gettop(L) > 4)
|
||||
{
|
||||
if (lua_gettop(L) > 4) {
|
||||
path.systemIndex = luaL_checkinteger(L, 5);
|
||||
}
|
||||
fac->PushClaim(path);
|
||||
|
@ -267,12 +273,12 @@ static void ExportFactionToLua(const Faction *fac, const size_t index)
|
|||
outstr << "local f = Faction:new('" << fac->name << "')" << std::endl;
|
||||
outstr << "\t:description_short('" << fac->description_short << "')" << std::endl;
|
||||
outstr << "\t:description('" << fac->description << "')" << std::endl;
|
||||
if(fac->hasHomeworld) outstr << "\t:homeworld(" << fac->homeworld.sectorX << "," << fac->homeworld.sectorY << "," << fac->homeworld.sectorZ << "," << fac->homeworld.systemIndex << "," << fac->homeworld.bodyIndex << ")" << std::endl;
|
||||
if (fac->hasHomeworld) outstr << "\t:homeworld(" << fac->homeworld.sectorX << "," << fac->homeworld.sectorY << "," << fac->homeworld.sectorZ << "," << fac->homeworld.systemIndex << "," << fac->homeworld.bodyIndex << ")" << std::endl;
|
||||
outstr << "\t:foundingDate(" << fac->foundingDate << ")" << std::endl;
|
||||
outstr << "\t:expansionRate(" << fac->expansionRate << ")" << std::endl;
|
||||
if (!fac->military_name.empty()) outstr << "\t:military_name('" << fac->military_name << "')" << std::endl;
|
||||
if (!fac->police_name.empty()) outstr << "\t:police_name('" << fac->police_name << "')" << std::endl;
|
||||
if (!fac->police_ship.empty()) outstr << "\t:police_ship('" << fac->police_ship << "')" << std::endl;
|
||||
if (!fac->military_name.empty()) outstr << "\t:military_name('" << fac->military_name << "')" << std::endl;
|
||||
if (!fac->police_name.empty()) outstr << "\t:police_name('" << fac->police_name << "')" << std::endl;
|
||||
if (!fac->police_ship.empty()) outstr << "\t:police_ship('" << fac->police_ship << "')" << std::endl;
|
||||
outstr << "\t:colour(" << float(fac->colour.r) / 255.f << "," << float(fac->colour.g) / 255.f << "," << float(fac->colour.b) / 255.f << ")" << std::endl;
|
||||
outstr << std::endl;
|
||||
|
||||
|
@ -296,7 +302,8 @@ static void ExportFactionToLua(const Faction *fac, const size_t index)
|
|||
}
|
||||
outstr << std::endl;
|
||||
|
||||
outstr << "f:add_to_factions('" << fac->name << "')\n\n" << std::endl;
|
||||
outstr << "f:add_to_factions('" << fac->name << "')\n\n"
|
||||
<< std::endl;
|
||||
|
||||
FILE *f = nullptr;
|
||||
FileSystem::FileSourceFS newFS(FileSystem::GetDataDir());
|
||||
|
@ -373,21 +380,21 @@ static int l_fac_gc(lua_State *L)
|
|||
}
|
||||
|
||||
static luaL_Reg LuaFaction_meta[] = {
|
||||
{ "new", &l_fac_new },
|
||||
{ "description_short", &l_fac_description_short },
|
||||
{ "description", &l_fac_description },
|
||||
{ "govtype_weight", &l_fac_govtype_weight },
|
||||
{ "homeworld", &l_fac_homeworld },
|
||||
{ "foundingDate", &l_fac_foundingDate },
|
||||
{ "expansionRate", &l_fac_expansionRate },
|
||||
{ "military_name", &l_fac_military_name },
|
||||
{ "police_name", &l_fac_police_name },
|
||||
{ "police_ship", &l_fac_police_ship },
|
||||
{ "new", &l_fac_new },
|
||||
{ "description_short", &l_fac_description_short },
|
||||
{ "description", &l_fac_description },
|
||||
{ "govtype_weight", &l_fac_govtype_weight },
|
||||
{ "homeworld", &l_fac_homeworld },
|
||||
{ "foundingDate", &l_fac_foundingDate },
|
||||
{ "expansionRate", &l_fac_expansionRate },
|
||||
{ "military_name", &l_fac_military_name },
|
||||
{ "police_name", &l_fac_police_name },
|
||||
{ "police_ship", &l_fac_police_ship },
|
||||
{ "illegal_goods_probability", &l_fac_illegal_goods_probability },
|
||||
{ "colour", &l_fac_colour },
|
||||
{ "add_to_factions", &l_fac_add_to_factions },
|
||||
{ "claim", &l_fac_claim }, // claim possession of a starsystem or sector
|
||||
{ "__gc", &l_fac_gc },
|
||||
{ "colour", &l_fac_colour },
|
||||
{ "add_to_factions", &l_fac_add_to_factions },
|
||||
{ "claim", &l_fac_claim }, // claim possession of a starsystem or sector
|
||||
{ "__gc", &l_fac_gc },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
@ -405,7 +412,6 @@ FactionsDatabase::~FactionsDatabase()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void register_class(lua_State *L, const char *tname, luaL_Reg *meta)
|
||||
{
|
||||
LUA_DEBUG_START(L);
|
||||
|
@ -451,12 +457,12 @@ void FactionsDatabase::Init()
|
|||
|
||||
Output("Number of factions added: " SIZET_FMT "\n", m_factions.size());
|
||||
ClearHomeSectors();
|
||||
m_galaxy->FlushCaches(); // clear caches of anything we used for faction generation
|
||||
m_galaxy->FlushCaches(); // clear caches of anything we used for faction generation
|
||||
while (!m_missingFactionsMap.empty()) {
|
||||
const std::string& factionName = m_missingFactionsMap.begin()->first;
|
||||
std::list<CustomSystem*>& csl = m_missingFactionsMap.begin()->second;
|
||||
const std::string &factionName = m_missingFactionsMap.begin()->first;
|
||||
std::list<CustomSystem *> &csl = m_missingFactionsMap.begin()->second;
|
||||
while (!csl.empty()) {
|
||||
CustomSystem* cs = csl.front();
|
||||
CustomSystem *cs = csl.front();
|
||||
// FIXME: How to signal missing faction?
|
||||
fprintf(stderr, "Custom system %s referenced unknown faction %s\n", cs->name.c_str(), factionName.c_str());
|
||||
csl.pop_front();
|
||||
|
@ -474,7 +480,7 @@ void FactionsDatabase::PostInit()
|
|||
SetHomeSectors();
|
||||
|
||||
#ifdef DUMP_FACTIONS // useful for dumping the factions from an autogenerated script
|
||||
for (size_t i = 0; i<m_factions.size(); i++)
|
||||
for (size_t i = 0; i < m_factions.size(); i++)
|
||||
ExportFactionToLua(m_factions[i], i);
|
||||
#endif
|
||||
}
|
||||
|
@ -499,20 +505,20 @@ bool FactionsDatabase::IsInitialized() const
|
|||
return m_initialized;
|
||||
}
|
||||
|
||||
void FactionsDatabase::RegisterCustomSystem(CustomSystem *cs, const std::string& factionName)
|
||||
void FactionsDatabase::RegisterCustomSystem(CustomSystem *cs, const std::string &factionName)
|
||||
{
|
||||
m_missingFactionsMap[factionName].push_back(cs);
|
||||
}
|
||||
|
||||
void FactionsDatabase::AddFaction(Faction* faction)
|
||||
void FactionsDatabase::AddFaction(Faction *faction)
|
||||
{
|
||||
// add the faction to the various faction data structures
|
||||
m_factions.push_back(faction);
|
||||
m_factions_byName[faction->name] = faction;
|
||||
auto it = m_missingFactionsMap.find(faction->name);
|
||||
if (it != m_missingFactionsMap.end()) {
|
||||
std::list<CustomSystem*>& csl = it->second;
|
||||
for (CustomSystem* cs : csl) {
|
||||
std::list<CustomSystem *> &csl = it->second;
|
||||
for (CustomSystem *cs : csl) {
|
||||
cs->faction = faction;
|
||||
}
|
||||
m_missingFactionsMap.erase(it);
|
||||
|
@ -520,17 +526,17 @@ void FactionsDatabase::AddFaction(Faction* faction)
|
|||
m_spatial_index.Add(faction);
|
||||
|
||||
if (faction->hasHomeworld) m_homesystems.insert(faction->homeworld.SystemOnly());
|
||||
faction->idx = m_factions.size()-1;
|
||||
faction->idx = m_factions.size() - 1;
|
||||
}
|
||||
|
||||
const Faction *FactionsDatabase::GetFaction(const Uint32 index) const
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
assert( index < m_factions.size() );
|
||||
assert(index < m_factions.size());
|
||||
return m_factions[index];
|
||||
}
|
||||
|
||||
const Faction* FactionsDatabase::GetFaction(const std::string& factionName) const
|
||||
const Faction *FactionsDatabase::GetFaction(const std::string &factionName) const
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
auto it = m_factions_byName.find(factionName);
|
||||
|
@ -553,7 +559,7 @@ bool FactionsDatabase::MayAssignFactions() const
|
|||
return m_may_assign_factions;
|
||||
}
|
||||
|
||||
const Faction* FactionsDatabase::GetNearestClaimant(const Sector::System* sys) const
|
||||
const Faction *FactionsDatabase::GetNearestClaimant(const Sector::System *sys) const
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
// firstly if this a custom StarSystem it may already have a faction assigned
|
||||
|
@ -562,12 +568,11 @@ const Faction* FactionsDatabase::GetNearestClaimant(const Sector::System* sys) c
|
|||
}
|
||||
|
||||
// if it didn't, or it wasn't a custom StarStystem, then we go ahead and assign it a faction allegiance like normal below...
|
||||
const Faction* result = &m_no_faction;
|
||||
const Faction *result = &m_no_faction;
|
||||
double closestFactionDist = HUGE_VAL;
|
||||
ConstFactionList& candidates = m_spatial_index.CandidateFactions(sys);
|
||||
ConstFactionList &candidates = m_spatial_index.CandidateFactions(sys);
|
||||
|
||||
for (ConstFactionIterator it = candidates.begin(); it != candidates.end(); ++it)
|
||||
{
|
||||
for (ConstFactionIterator it = candidates.begin(); it != candidates.end(); ++it) {
|
||||
if ((*it)->IsClaimed(sys->GetPath()))
|
||||
return *it; // this is a very specific claim, no further checks for distance from another factions homeworld is needed.
|
||||
if ((*it)->IsCloserAndContains(closestFactionDist, sys))
|
||||
|
@ -576,7 +581,7 @@ const Faction* FactionsDatabase::GetNearestClaimant(const Sector::System* sys) c
|
|||
return result;
|
||||
}
|
||||
|
||||
bool FactionsDatabase::IsHomeSystem(const SystemPath& sysPath) const
|
||||
bool FactionsDatabase::IsHomeSystem(const SystemPath &sysPath) const
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
return m_homesystems.find(sysPath.SystemOnly()) != m_homesystems.end();
|
||||
|
@ -590,8 +595,7 @@ bool Faction::IsClaimed(SystemPath path) const
|
|||
SystemPath sector = path;
|
||||
sector.systemIndex = -99;
|
||||
|
||||
for (auto clam = m_ownedsystemlist.begin(); clam != m_ownedsystemlist.end(); clam++)
|
||||
{
|
||||
for (auto clam = m_ownedsystemlist.begin(); clam != m_ownedsystemlist.end(); clam++) {
|
||||
if (*clam == sector || *clam == path)
|
||||
return true;
|
||||
}
|
||||
|
@ -604,7 +608,7 @@ bool Faction::IsClaimed(SystemPath path) const
|
|||
if it is, then the passed distance will also be updated to be the distance
|
||||
from the factions homeworld to the sysPath.
|
||||
*/
|
||||
const bool Faction::IsCloserAndContains(double& closestFactionDist, const Sector::System* sys) const
|
||||
const bool Faction::IsCloserAndContains(double &closestFactionDist, const Sector::System *sys) const
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
/* Treat factions without homeworlds as if they are of effectively infinite radius,
|
||||
|
@ -613,21 +617,22 @@ const bool Faction::IsCloserAndContains(double& closestFactionDist, const Sector
|
|||
a better claim.
|
||||
*/
|
||||
float distance = HUGE_VAL;
|
||||
bool inside = true;
|
||||
bool inside = true;
|
||||
|
||||
/* Factions that have a homeworld... */
|
||||
if (hasHomeworld)
|
||||
{
|
||||
if (hasHomeworld) {
|
||||
/* ...automatically gain the allegiance of worlds within the same sector... */
|
||||
if (sys->InSameSector(homeworld)) { distance = 0; }
|
||||
if (sys->InSameSector(homeworld)) {
|
||||
distance = 0;
|
||||
}
|
||||
|
||||
/* ...otherwise we need to calculate whether the world is inside the
|
||||
the faction border, and how far away it is. */
|
||||
else {
|
||||
RefCountedPtr<const Sector> homeSec = GetHomeSector();
|
||||
const Sector::System* homeSys = &homeSec->m_systems[homeworld.systemIndex];
|
||||
const Sector::System *homeSys = &homeSec->m_systems[homeworld.systemIndex];
|
||||
distance = Sector::System::DistanceBetween(homeSys, sys);
|
||||
inside = distance < Radius();
|
||||
inside = distance < Radius();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -637,7 +642,7 @@ const bool Faction::IsCloserAndContains(double& closestFactionDist, const Sector
|
|||
closestFactionDist = distance;
|
||||
return true;
|
||||
|
||||
/* otherwise this isn't the faction we were looking for */
|
||||
/* otherwise this isn't the faction we were looking for */
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -648,23 +653,23 @@ const Color Faction::AdjustedColour(fixed population, bool inRange) const
|
|||
PROFILE_SCOPED()
|
||||
Color result;
|
||||
// Unexplored: population = -1, Uninhabited: population = 0.
|
||||
result = population <= 0 ? BAD_FACTION_COLOUR : colour;
|
||||
result.a = population > 0 ? (FACTION_BASE_ALPHA + (M_E + (logf(population.ToFloat() / 1.25))) / ((2 * M_E) + FACTION_BASE_ALPHA)) * 255 : FACTION_BASE_ALPHA * 255;
|
||||
result.a = inRange ? 255 : result.a;
|
||||
result = population <= 0 ? BAD_FACTION_COLOUR : colour;
|
||||
result.a = population > 0 ? (FACTION_BASE_ALPHA + (M_E + (logf(population.ToFloat() / 1.25))) / ((2 * M_E) + FACTION_BASE_ALPHA)) * 255 : FACTION_BASE_ALPHA * 255;
|
||||
result.a = inRange ? 255 : result.a;
|
||||
return result;
|
||||
}
|
||||
|
||||
const Polit::GovType Faction::PickGovType(Random &rand) const
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
if( !govtype_weights.empty()) {
|
||||
if (!govtype_weights.empty()) {
|
||||
// if we roll a number between one and the total weighting...
|
||||
Sint32 roll = rand.Int32(1, govtype_weights_total);
|
||||
Sint32 cumulativeWeight = 0;
|
||||
|
||||
// ...the first govType with a cumulative weight >= the roll should be our pick
|
||||
GovWeightIterator it = govtype_weights.begin();
|
||||
while(roll > (cumulativeWeight + it->second)) {
|
||||
while (roll > (cumulativeWeight + it->second)) {
|
||||
cumulativeWeight += it->second;
|
||||
++it;
|
||||
}
|
||||
|
@ -688,8 +693,7 @@ void Faction::SetBestFitHomeworld(Sint32 x, Sint32 y, Sint32 z, Sint32 si, Uint3
|
|||
// or hit the edge of inhabited space
|
||||
Uint32 i = 0;
|
||||
RefCountedPtr<StarSystem> sys;
|
||||
while (si < 0 && (abs(x) != 90 && abs(y) != 90 && abs(z) != 90)
|
||||
&& ( x != 0 && y != 0 && z != 0 )) {
|
||||
while (si < 0 && (abs(x) != 90 && abs(y) != 90 && abs(z) != 90) && (x != 0 && y != 0 && z != 0)) {
|
||||
|
||||
SystemPath path(x, y, z);
|
||||
// search for a suitable homeworld in the current sector
|
||||
|
@ -705,8 +709,7 @@ void Faction::SetBestFitHomeworld(Sint32 x, Sint32 y, Sint32 z, Sint32 si, Uint3
|
|||
if (stationCount.find(station->GetParent()->GetPath()) == stationCount.end()) {
|
||||
// new parent
|
||||
stationCount[station->GetParent()->GetPath()] = 1;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// increment count
|
||||
stationCount[station->GetParent()->GetPath()]++;
|
||||
}
|
||||
|
@ -726,21 +729,38 @@ void Faction::SetBestFitHomeworld(Sint32 x, Sint32 y, Sint32 z, Sint32 si, Uint3
|
|||
}
|
||||
|
||||
// set the co-ordinates of the next sector to examine, cycling through x, y and z
|
||||
if (si < 0 && i%3==0) { if (x >= 0) { x = x + axisChange; } else { x = x - axisChange; }; }
|
||||
else if (si < 0 && i%3==1) { if (y >= 0) { y = y + axisChange; } else { y = y - axisChange; }; }
|
||||
else if (si < 0 && i%3==2) { if (z >= 0) { z = z + axisChange; } else { z = z - axisChange; }; }
|
||||
if (si < 0 && i % 3 == 0) {
|
||||
if (x >= 0) {
|
||||
x = x + axisChange;
|
||||
} else {
|
||||
x = x - axisChange;
|
||||
};
|
||||
} else if (si < 0 && i % 3 == 1) {
|
||||
if (y >= 0) {
|
||||
y = y + axisChange;
|
||||
} else {
|
||||
y = y - axisChange;
|
||||
};
|
||||
} else if (si < 0 && i % 3 == 2) {
|
||||
if (z >= 0) {
|
||||
z = z + axisChange;
|
||||
} else {
|
||||
z = z - axisChange;
|
||||
};
|
||||
}
|
||||
i++;
|
||||
}
|
||||
homeworld = SystemPath(x, y, z, si, bi);
|
||||
}
|
||||
|
||||
RefCountedPtr<const Sector> Faction::GetHomeSector() const {
|
||||
RefCountedPtr<const Sector> Faction::GetHomeSector() const
|
||||
{
|
||||
if (!m_homesector) // This will later be replaced by a Sector from the cache
|
||||
m_homesector = m_galaxy->GetSector(homeworld);
|
||||
return m_homesector;
|
||||
}
|
||||
|
||||
Faction::Faction(Galaxy* galaxy) :
|
||||
Faction::Faction(Galaxy *galaxy) :
|
||||
idx(BAD_FACTION_IDX),
|
||||
name(Lang::NO_CENTRAL_GOVERNANCE),
|
||||
hasHomeworld(false),
|
||||
|
@ -756,7 +776,7 @@ Faction::Faction(Galaxy* galaxy) :
|
|||
|
||||
// ------ Factions Spatial Indexing ------
|
||||
|
||||
void FactionsDatabase::Octsapling::Add(const Faction* faction)
|
||||
void FactionsDatabase::Octsapling::Add(const Faction *faction)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
/* The general principle here is to put the faction in every octbox cell that a system
|
||||
|
@ -794,30 +814,30 @@ void FactionsDatabase::Octsapling::Add(const Faction* faction)
|
|||
/* put the faction in all the octbox cells needed in a hideously inexact way that
|
||||
will generate duplicates in each cell in many cases
|
||||
*/
|
||||
octbox[xmin][ymin][zmin].push_back(faction); // 0,0,0
|
||||
octbox[xmax][ymin][zmin].push_back(faction); // 1,0,0
|
||||
octbox[xmax][ymax][zmin].push_back(faction); // 1,1,0
|
||||
octbox[xmax][ymax][zmax].push_back(faction); // 1,1,1
|
||||
octbox[xmin][ymin][zmin].push_back(faction); // 0,0,0
|
||||
octbox[xmax][ymin][zmin].push_back(faction); // 1,0,0
|
||||
octbox[xmax][ymax][zmin].push_back(faction); // 1,1,0
|
||||
octbox[xmax][ymax][zmax].push_back(faction); // 1,1,1
|
||||
|
||||
octbox[xmin][ymax][zmin].push_back(faction); // 0,1,0
|
||||
octbox[xmin][ymax][zmax].push_back(faction); // 0,1,1
|
||||
octbox[xmin][ymin][zmax].push_back(faction); // 0,0,1
|
||||
octbox[xmax][ymin][zmax].push_back(faction); // 1,0,1
|
||||
octbox[xmin][ymax][zmin].push_back(faction); // 0,1,0
|
||||
octbox[xmin][ymax][zmax].push_back(faction); // 0,1,1
|
||||
octbox[xmin][ymin][zmax].push_back(faction); // 0,0,1
|
||||
octbox[xmax][ymin][zmax].push_back(faction); // 1,0,1
|
||||
|
||||
/* prune any duplicates from the octbox cells making things slightly saner
|
||||
*/
|
||||
PruneDuplicates(0,0,0);
|
||||
PruneDuplicates(1,0,0);
|
||||
PruneDuplicates(1,1,0);
|
||||
PruneDuplicates(1,1,1);
|
||||
PruneDuplicates(0, 0, 0);
|
||||
PruneDuplicates(1, 0, 0);
|
||||
PruneDuplicates(1, 1, 0);
|
||||
PruneDuplicates(1, 1, 1);
|
||||
|
||||
PruneDuplicates(0,1,0);
|
||||
PruneDuplicates(0,1,1);
|
||||
PruneDuplicates(0,0,1);
|
||||
PruneDuplicates(1,0,1);
|
||||
PruneDuplicates(0, 1, 0);
|
||||
PruneDuplicates(0, 1, 1);
|
||||
PruneDuplicates(0, 0, 1);
|
||||
PruneDuplicates(1, 0, 1);
|
||||
|
||||
} else {
|
||||
/* ...other factions, such as ones with no homeworlds, and more annoyingly ones
|
||||
/* ...other factions, such as ones with no homeworlds, and more annoyingly ones
|
||||
whose homeworlds don't exist yet because they're custom systems have to go in
|
||||
*every* octbox cell
|
||||
*/
|
||||
|
@ -836,10 +856,10 @@ void FactionsDatabase::Octsapling::Add(const Faction* faction)
|
|||
void FactionsDatabase::Octsapling::PruneDuplicates(const int bx, const int by, const int bz)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
octbox[bx][by][bz].erase(std::unique( octbox[bx][by][bz].begin(), octbox[bx][by][bz].end() ), octbox[bx][by][bz].end() );
|
||||
octbox[bx][by][bz].erase(std::unique(octbox[bx][by][bz].begin(), octbox[bx][by][bz].end()), octbox[bx][by][bz].end());
|
||||
}
|
||||
|
||||
const std::vector<const Faction*>& FactionsDatabase::Octsapling::CandidateFactions(const Sector::System* sys) const
|
||||
const std::vector<const Faction *> &FactionsDatabase::Octsapling::CandidateFactions(const Sector::System *sys) const
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
/* answer the factions that we've put in the same octobox cell as the one the
|
||||
|
|
127
src/Factions.h
127
src/Factions.h
|
@ -4,66 +4,67 @@
|
|||
#ifndef _FACTIONS_H
|
||||
#define _FACTIONS_H
|
||||
|
||||
#include "galaxy/Sector.h"
|
||||
#include "galaxy/Economy.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "Polit.h"
|
||||
#include "vector3.h"
|
||||
#include "fixed.h"
|
||||
#include "DeleteEmitter.h"
|
||||
#include "Polit.h"
|
||||
#include "fixed.h"
|
||||
#include "galaxy/Economy.h"
|
||||
#include "galaxy/Sector.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "vector3.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class Galaxy;
|
||||
class CustomSystem;
|
||||
|
||||
class Faction : public DeleteEmitter {
|
||||
friend class FactionsDatabase;
|
||||
|
||||
public:
|
||||
static const Uint32 BAD_FACTION_IDX; // used by the no faction object to denote it's not a proper faction
|
||||
static const Color BAD_FACTION_COLOUR; // factionColour to use on failing to find an appropriate faction
|
||||
static const float FACTION_BASE_ALPHA; // Alpha to use on factionColour of systems with unknown population
|
||||
static const Uint32 BAD_FACTION_IDX; // used by the no faction object to denote it's not a proper faction
|
||||
static const Color BAD_FACTION_COLOUR; // factionColour to use on failing to find an appropriate faction
|
||||
static const float FACTION_BASE_ALPHA; // Alpha to use on factionColour of systems with unknown population
|
||||
|
||||
Faction(Galaxy* galaxy);
|
||||
Faction(Galaxy *galaxy);
|
||||
|
||||
Uint32 idx; // faction index
|
||||
std::string name; // Formal name "Federation", "Empire", "Bob's Rib-shack consortium of delicious worlds (tm)", etc.
|
||||
std::string description_short; // short description
|
||||
std::string description; // detailed description describing formation, current status, etc
|
||||
Uint32 idx; // faction index
|
||||
std::string name; // Formal name "Federation", "Empire", "Bob's Rib-shack consortium of delicious worlds (tm)", etc.
|
||||
std::string description_short; // short description
|
||||
std::string description; // detailed description describing formation, current status, etc
|
||||
|
||||
// government types with weighting
|
||||
typedef std::pair<Polit::GovType, Sint32> GovWeight;
|
||||
typedef std::vector<GovWeight> GovWeightVec;
|
||||
typedef GovWeightVec::const_iterator GovWeightIterator;
|
||||
GovWeightVec govtype_weights;
|
||||
Sint32 govtype_weights_total;
|
||||
typedef std::vector<GovWeight> GovWeightVec;
|
||||
typedef GovWeightVec::const_iterator GovWeightIterator;
|
||||
GovWeightVec govtype_weights;
|
||||
Sint32 govtype_weights_total;
|
||||
|
||||
bool hasHomeworld;
|
||||
SystemPath homeworld; // sector(x,y,x) + system index + body index = location in a (custom?) system of homeworld
|
||||
double foundingDate; // date faction came into existence
|
||||
double expansionRate; // lightyears per year that the volume expands.
|
||||
std::string military_name; // "Space Defense Force", "Imperial Will Enforcement Division"...
|
||||
bool hasHomeworld;
|
||||
SystemPath homeworld; // sector(x,y,x) + system index + body index = location in a (custom?) system of homeworld
|
||||
double foundingDate; // date faction came into existence
|
||||
double expansionRate; // lightyears per year that the volume expands.
|
||||
std::string military_name; // "Space Defense Force", "Imperial Will Enforcement Division"...
|
||||
//military logo
|
||||
std::string police_name; // "Police", "Polizia Locale"...
|
||||
std::string police_ship; // "kanara", "varada"...
|
||||
std::string police_name; // "Police", "Polizia Locale"...
|
||||
std::string police_ship; // "kanara", "varada"...
|
||||
//police logo
|
||||
//goods/equipment availability (1-per-economy-type: aka agricultural, industrial, tourist, etc)
|
||||
|
||||
typedef std::vector<SystemPath> ClaimList;
|
||||
ClaimList m_ownedsystemlist;
|
||||
ClaimList m_ownedsystemlist;
|
||||
void PushClaim(SystemPath path) { m_ownedsystemlist.push_back(path); }
|
||||
bool IsClaimed(SystemPath) const;
|
||||
|
||||
// commodity legality
|
||||
typedef std::map<GalacticEconomy::Commodity, Uint32> CommodityProbMap;
|
||||
CommodityProbMap commodity_legality;
|
||||
CommodityProbMap commodity_legality;
|
||||
|
||||
Color colour;
|
||||
Color colour;
|
||||
|
||||
const double Radius() const { return (FACTION_CURRENT_YEAR - foundingDate) * expansionRate; };
|
||||
const bool IsValid() const { return idx != BAD_FACTION_IDX; };
|
||||
const Color AdjustedColour(fixed population, bool inRange) const;
|
||||
const double Radius() const { return (FACTION_CURRENT_YEAR - foundingDate) * expansionRate; };
|
||||
const bool IsValid() const { return idx != BAD_FACTION_IDX; };
|
||||
const Color AdjustedColour(fixed population, bool inRange) const;
|
||||
const Polit::GovType PickGovType(Random &rand) const;
|
||||
|
||||
// set the homeworld to one near the supplied co-ordinates
|
||||
|
@ -71,11 +72,11 @@ public:
|
|||
RefCountedPtr<const Sector> GetHomeSector() const;
|
||||
|
||||
private:
|
||||
static const double FACTION_CURRENT_YEAR; // used to calculate faction radius
|
||||
static const double FACTION_CURRENT_YEAR; // used to calculate faction radius
|
||||
|
||||
Galaxy* const m_galaxy; // galaxy we are part of
|
||||
mutable RefCountedPtr<const Sector> m_homesector; // cache of home sector to use in distance calculations
|
||||
const bool IsCloserAndContains(double& closestFactionDist, const Sector::System* sys) const;
|
||||
Galaxy *const m_galaxy; // galaxy we are part of
|
||||
mutable RefCountedPtr<const Sector> m_homesector; // cache of home sector to use in distance calculations
|
||||
const bool IsCloserAndContains(double &closestFactionDist, const Sector::System *sys) const;
|
||||
};
|
||||
|
||||
/* One day it might grow up to become a full tree, on the other hand it might be
|
||||
|
@ -85,21 +86,26 @@ private:
|
|||
|
||||
class FactionsDatabase {
|
||||
public:
|
||||
FactionsDatabase(Galaxy* galaxy, const std::string& factionDir) : m_galaxy(galaxy), m_factionDirectory(factionDir), m_no_faction(galaxy), m_may_assign_factions(false), m_initialized(false) { }
|
||||
FactionsDatabase(Galaxy *galaxy, const std::string &factionDir) :
|
||||
m_galaxy(galaxy),
|
||||
m_factionDirectory(factionDir),
|
||||
m_no_faction(galaxy),
|
||||
m_may_assign_factions(false),
|
||||
m_initialized(false) {}
|
||||
~FactionsDatabase();
|
||||
|
||||
void Init();
|
||||
void PostInit();
|
||||
void ClearCache() { ClearHomeSectors(); }
|
||||
bool IsInitialized() const;
|
||||
Galaxy* GetGalaxy() const { return m_galaxy; }
|
||||
void RegisterCustomSystem(CustomSystem *cs, const std::string& factionName);
|
||||
void AddFaction(Faction* faction);
|
||||
Galaxy *GetGalaxy() const { return m_galaxy; }
|
||||
void RegisterCustomSystem(CustomSystem *cs, const std::string &factionName);
|
||||
void AddFaction(Faction *faction);
|
||||
|
||||
const Faction *GetFaction(const Uint32 index) const;
|
||||
const Faction *GetFaction(const std::string& factionName) const;
|
||||
const Faction *GetNearestClaimant(const Sector::System* sys) const;
|
||||
bool IsHomeSystem(const SystemPath& sysPath) const;
|
||||
const Faction *GetFaction(const std::string &factionName) const;
|
||||
const Faction *GetNearestClaimant(const Sector::System *sys) const;
|
||||
bool IsHomeSystem(const SystemPath &sysPath) const;
|
||||
|
||||
const Uint32 GetNumFactions() const;
|
||||
|
||||
|
@ -108,37 +114,36 @@ public:
|
|||
private:
|
||||
class Octsapling {
|
||||
public:
|
||||
void Add(const Faction* faction);
|
||||
const std::vector<const Faction*>& CandidateFactions(const Sector::System* sys) const;
|
||||
void Add(const Faction *faction);
|
||||
const std::vector<const Faction *> &CandidateFactions(const Sector::System *sys) const;
|
||||
|
||||
private:
|
||||
std::vector<const Faction*> octbox[2][2][2];
|
||||
static const int BoxIndex(Sint32 sectorIndex) { return sectorIndex < 0 ? 0: 1; };
|
||||
std::vector<const Faction *> octbox[2][2][2];
|
||||
static const int BoxIndex(Sint32 sectorIndex) { return sectorIndex < 0 ? 0 : 1; };
|
||||
void PruneDuplicates(const int bx, const int by, const int bz);
|
||||
};
|
||||
|
||||
typedef std::vector<Faction*> FactionList;
|
||||
typedef std::vector<Faction *> FactionList;
|
||||
typedef FactionList::iterator FactionIterator;
|
||||
typedef const std::vector<const Faction*> ConstFactionList;
|
||||
typedef const std::vector<const Faction *> ConstFactionList;
|
||||
typedef ConstFactionList::const_iterator ConstFactionIterator;
|
||||
typedef std::map<std::string, Faction*> FactionMap;
|
||||
typedef std::set<SystemPath> HomeSystemSet;
|
||||
typedef std::map<std::string, std::list<CustomSystem*> > MissingFactionsMap;
|
||||
typedef std::map<std::string, Faction *> FactionMap;
|
||||
typedef std::set<SystemPath> HomeSystemSet;
|
||||
typedef std::map<std::string, std::list<CustomSystem *>> MissingFactionsMap;
|
||||
|
||||
void ClearHomeSectors();
|
||||
void SetHomeSectors();
|
||||
|
||||
Galaxy* const m_galaxy;
|
||||
Galaxy *const m_galaxy;
|
||||
const std::string m_factionDirectory;
|
||||
Faction m_no_faction; // instead of answering null, we often want to answer a working faction object for no faction
|
||||
FactionList m_factions;
|
||||
FactionMap m_factions_byName;
|
||||
HomeSystemSet m_homesystems;
|
||||
Octsapling m_spatial_index;
|
||||
bool m_may_assign_factions;
|
||||
bool m_initialized = false;
|
||||
Faction m_no_faction; // instead of answering null, we often want to answer a working faction object for no faction
|
||||
FactionList m_factions;
|
||||
FactionMap m_factions_byName;
|
||||
HomeSystemSet m_homesystems;
|
||||
Octsapling m_spatial_index;
|
||||
bool m_may_assign_factions;
|
||||
bool m_initialized = false;
|
||||
MissingFactionsMap m_missingFactionsMap;
|
||||
|
||||
};
|
||||
|
||||
#endif /* _FACTIONS_H */
|
||||
|
|
|
@ -13,173 +13,174 @@ extern "C" {
|
|||
|
||||
namespace FileSystem {
|
||||
|
||||
FileSourceZip::FileSourceZip(FileSourceFS &fs, const std::string &zipPath) : FileSource(zipPath), m_archive(0)
|
||||
{
|
||||
mz_zip_archive *zip = static_cast<mz_zip_archive*>(std::calloc(1, sizeof(mz_zip_archive)));
|
||||
FILE *file = fs.OpenReadStream(zipPath);
|
||||
if (!mz_zip_reader_init_file_stream(zip, file, 0)) {
|
||||
Output("FileSourceZip: unable to open '%s'\n", zipPath.c_str());
|
||||
std::free(zip);
|
||||
return;
|
||||
}
|
||||
FileSourceZip::FileSourceZip(FileSourceFS &fs, const std::string &zipPath) :
|
||||
FileSource(zipPath),
|
||||
m_archive(0)
|
||||
{
|
||||
mz_zip_archive *zip = static_cast<mz_zip_archive *>(std::calloc(1, sizeof(mz_zip_archive)));
|
||||
FILE *file = fs.OpenReadStream(zipPath);
|
||||
if (!mz_zip_reader_init_file_stream(zip, file, 0)) {
|
||||
Output("FileSourceZip: unable to open '%s'\n", zipPath.c_str());
|
||||
std::free(zip);
|
||||
return;
|
||||
}
|
||||
|
||||
mz_zip_archive_file_stat zipStat;
|
||||
mz_zip_archive_file_stat zipStat;
|
||||
|
||||
Uint32 numFiles = mz_zip_reader_get_num_files(zip);
|
||||
for (Uint32 i = 0; i < numFiles; i++) {
|
||||
if (mz_zip_reader_file_stat(zip, i, &zipStat)) {
|
||||
bool is_dir = mz_zip_reader_is_file_a_directory(zip, i);
|
||||
if (!mz_zip_reader_is_file_encrypted(zip, i)) {
|
||||
std::string fname = zipStat.m_filename;
|
||||
if ((fname.size() > 1) && (fname[fname.size()-1] == '/')) {
|
||||
fname.resize(fname.size() - 1);
|
||||
Uint32 numFiles = mz_zip_reader_get_num_files(zip);
|
||||
for (Uint32 i = 0; i < numFiles; i++) {
|
||||
if (mz_zip_reader_file_stat(zip, i, &zipStat)) {
|
||||
bool is_dir = mz_zip_reader_is_file_a_directory(zip, i);
|
||||
if (!mz_zip_reader_is_file_encrypted(zip, i)) {
|
||||
std::string fname = zipStat.m_filename;
|
||||
if ((fname.size() > 1) && (fname[fname.size() - 1] == '/')) {
|
||||
fname.resize(fname.size() - 1);
|
||||
}
|
||||
AddFile(zipStat.m_filename, FileStat(i, zipStat.m_uncomp_size, MakeFileInfo(fname, is_dir ? FileInfo::FT_DIR : FileInfo::FT_FILE)));
|
||||
}
|
||||
AddFile(zipStat.m_filename, FileStat(i, zipStat.m_uncomp_size,
|
||||
MakeFileInfo(fname, is_dir ? FileInfo::FT_DIR : FileInfo::FT_FILE)));
|
||||
}
|
||||
}
|
||||
|
||||
m_archive = static_cast<void *>(zip);
|
||||
}
|
||||
|
||||
m_archive = static_cast<void*>(zip);
|
||||
}
|
||||
|
||||
FileSourceZip::~FileSourceZip()
|
||||
{
|
||||
if (!m_archive) return;
|
||||
mz_zip_archive *zip = static_cast<mz_zip_archive*>(m_archive);
|
||||
mz_zip_reader_end(zip);
|
||||
}
|
||||
|
||||
static void SplitPath(const std::string &path, std::vector<std::string> &output)
|
||||
{
|
||||
static const std::string delim("/");
|
||||
|
||||
size_t start = 0, end = 0;
|
||||
while (end != std::string::npos) {
|
||||
// get to the first non-delim char
|
||||
start = path.find_first_not_of(delim, end);
|
||||
|
||||
// read the end, no more to do
|
||||
if (start == std::string::npos)
|
||||
break;
|
||||
|
||||
// find the end - next delim or end of string
|
||||
end = path.find_first_of(delim, start);
|
||||
|
||||
// extract the fragment and remember it
|
||||
output.push_back(path.substr(start, (end == std::string::npos) ? std::string::npos : end - start));
|
||||
}
|
||||
}
|
||||
|
||||
bool FileSourceZip::FindDirectoryAndFile(const std::string &path, const Directory* &dir, std::string &filename)
|
||||
{
|
||||
std::vector<std::string> fragments;
|
||||
SplitPath(NormalisePath(path), fragments);
|
||||
|
||||
assert(fragments.size() > 0);
|
||||
|
||||
dir = &m_root;
|
||||
|
||||
if (fragments.size() > 1) {
|
||||
for (unsigned int i = 0; i < fragments.size()-1; i++) {
|
||||
std::map<std::string,Directory>::const_iterator it = dir->subdirs.find(fragments[i]);
|
||||
if (it == dir->subdirs.end())
|
||||
return false;
|
||||
dir = &((*it).second);
|
||||
}
|
||||
}
|
||||
|
||||
filename = fragments.back();
|
||||
return true;
|
||||
}
|
||||
|
||||
FileInfo FileSourceZip::Lookup(const std::string &path)
|
||||
{
|
||||
const Directory *dir;
|
||||
std::string filename;
|
||||
if (!FindDirectoryAndFile(path, dir, filename))
|
||||
return MakeFileInfo(path, FileInfo::FT_NON_EXISTENT);
|
||||
|
||||
std::map<std::string,FileStat>::const_iterator i = dir->files.find(filename);
|
||||
if (i == dir->files.end())
|
||||
return MakeFileInfo(path, FileInfo::FT_NON_EXISTENT);
|
||||
|
||||
return (*i).second.info;
|
||||
}
|
||||
|
||||
RefCountedPtr<FileData> FileSourceZip::ReadFile(const std::string &path)
|
||||
{
|
||||
if (!m_archive) return RefCountedPtr<FileData>();
|
||||
mz_zip_archive *zip = static_cast<mz_zip_archive*>(m_archive);
|
||||
|
||||
const Directory *dir;
|
||||
std::string filename;
|
||||
if (!FindDirectoryAndFile(path, dir, filename))
|
||||
return RefCountedPtr<FileData>();
|
||||
|
||||
std::map<std::string,FileStat>::const_iterator i = dir->files.find(filename);
|
||||
if (i == dir->files.end())
|
||||
return RefCountedPtr<FileData>();
|
||||
|
||||
const FileStat &st = (*i).second;
|
||||
|
||||
char *data = static_cast<char*>(std::malloc(st.size));
|
||||
if (!mz_zip_reader_extract_to_mem(zip, st.index, data, st.size, 0)) {
|
||||
Output("FileSourceZip::ReadFile: couldn't extract '%s'\n", path.c_str());
|
||||
return RefCountedPtr<FileData>();
|
||||
}
|
||||
|
||||
return RefCountedPtr<FileData>(new FileDataMalloc(st.info, st.size, data));
|
||||
}
|
||||
|
||||
bool FileSourceZip::ReadDirectory(const std::string &path, std::vector<FileInfo> &output)
|
||||
{
|
||||
const Directory *dir;
|
||||
std::string filename;
|
||||
if (!FindDirectoryAndFile(path, dir, filename))
|
||||
return false;
|
||||
|
||||
FileSourceZip::~FileSourceZip()
|
||||
{
|
||||
std::map<std::string,Directory>::const_iterator i = dir->subdirs.find(filename);
|
||||
if (i == dir->subdirs.end())
|
||||
return false;
|
||||
dir = &((*i).second);
|
||||
if (!m_archive) return;
|
||||
mz_zip_archive *zip = static_cast<mz_zip_archive *>(m_archive);
|
||||
mz_zip_reader_end(zip);
|
||||
}
|
||||
|
||||
for (std::map<std::string,FileStat>::const_iterator i = dir->files.begin(); i != dir->files.end(); ++i)
|
||||
output.push_back((*i).second.info);
|
||||
static void SplitPath(const std::string &path, std::vector<std::string> &output)
|
||||
{
|
||||
static const std::string delim("/");
|
||||
|
||||
return true;
|
||||
}
|
||||
size_t start = 0, end = 0;
|
||||
while (end != std::string::npos) {
|
||||
// get to the first non-delim char
|
||||
start = path.find_first_not_of(delim, end);
|
||||
|
||||
void FileSourceZip::AddFile(const std::string &path, const FileStat &fileStat)
|
||||
{
|
||||
std::vector<std::string> fragments;
|
||||
SplitPath(path, fragments);
|
||||
// read the end, no more to do
|
||||
if (start == std::string::npos)
|
||||
break;
|
||||
|
||||
assert(fragments.size() > 0);
|
||||
// find the end - next delim or end of string
|
||||
end = path.find_first_of(delim, start);
|
||||
|
||||
Directory *dir = &m_root;
|
||||
|
||||
if (fragments.size() > 1) {
|
||||
std::string fullPath;
|
||||
|
||||
for (unsigned int i = 0; i < fragments.size()-1; i++) {
|
||||
fullPath += ((i > 0) ? "/" : "") + fragments[i];
|
||||
|
||||
std::map<std::string,FileStat>::const_iterator it = dir->files.find(fragments[i]);
|
||||
if (it == dir->files.end())
|
||||
dir->files.insert(std::make_pair(fragments[i], FileStat(Uint32(-1), 0, MakeFileInfo(fullPath, FileInfo::FT_DIR))));
|
||||
dir = &(dir->subdirs[fragments[i]]);
|
||||
// extract the fragment and remember it
|
||||
output.push_back(path.substr(start, (end == std::string::npos) ? std::string::npos : end - start));
|
||||
}
|
||||
}
|
||||
|
||||
const std::string &filename = fragments.back();
|
||||
bool FileSourceZip::FindDirectoryAndFile(const std::string &path, const Directory *&dir, std::string &filename)
|
||||
{
|
||||
std::vector<std::string> fragments;
|
||||
SplitPath(NormalisePath(path), fragments);
|
||||
|
||||
if (fileStat.info.IsDir())
|
||||
dir->subdirs.insert(std::make_pair(filename, Directory()));
|
||||
assert(fragments.size() > 0);
|
||||
|
||||
dir->files.insert(std::make_pair(filename, fileStat));
|
||||
}
|
||||
dir = &m_root;
|
||||
|
||||
}
|
||||
if (fragments.size() > 1) {
|
||||
for (unsigned int i = 0; i < fragments.size() - 1; i++) {
|
||||
std::map<std::string, Directory>::const_iterator it = dir->subdirs.find(fragments[i]);
|
||||
if (it == dir->subdirs.end())
|
||||
return false;
|
||||
dir = &((*it).second);
|
||||
}
|
||||
}
|
||||
|
||||
filename = fragments.back();
|
||||
return true;
|
||||
}
|
||||
|
||||
FileInfo FileSourceZip::Lookup(const std::string &path)
|
||||
{
|
||||
const Directory *dir;
|
||||
std::string filename;
|
||||
if (!FindDirectoryAndFile(path, dir, filename))
|
||||
return MakeFileInfo(path, FileInfo::FT_NON_EXISTENT);
|
||||
|
||||
std::map<std::string, FileStat>::const_iterator i = dir->files.find(filename);
|
||||
if (i == dir->files.end())
|
||||
return MakeFileInfo(path, FileInfo::FT_NON_EXISTENT);
|
||||
|
||||
return (*i).second.info;
|
||||
}
|
||||
|
||||
RefCountedPtr<FileData> FileSourceZip::ReadFile(const std::string &path)
|
||||
{
|
||||
if (!m_archive) return RefCountedPtr<FileData>();
|
||||
mz_zip_archive *zip = static_cast<mz_zip_archive *>(m_archive);
|
||||
|
||||
const Directory *dir;
|
||||
std::string filename;
|
||||
if (!FindDirectoryAndFile(path, dir, filename))
|
||||
return RefCountedPtr<FileData>();
|
||||
|
||||
std::map<std::string, FileStat>::const_iterator i = dir->files.find(filename);
|
||||
if (i == dir->files.end())
|
||||
return RefCountedPtr<FileData>();
|
||||
|
||||
const FileStat &st = (*i).second;
|
||||
|
||||
char *data = static_cast<char *>(std::malloc(st.size));
|
||||
if (!mz_zip_reader_extract_to_mem(zip, st.index, data, st.size, 0)) {
|
||||
Output("FileSourceZip::ReadFile: couldn't extract '%s'\n", path.c_str());
|
||||
return RefCountedPtr<FileData>();
|
||||
}
|
||||
|
||||
return RefCountedPtr<FileData>(new FileDataMalloc(st.info, st.size, data));
|
||||
}
|
||||
|
||||
bool FileSourceZip::ReadDirectory(const std::string &path, std::vector<FileInfo> &output)
|
||||
{
|
||||
const Directory *dir;
|
||||
std::string filename;
|
||||
if (!FindDirectoryAndFile(path, dir, filename))
|
||||
return false;
|
||||
|
||||
{
|
||||
std::map<std::string, Directory>::const_iterator i = dir->subdirs.find(filename);
|
||||
if (i == dir->subdirs.end())
|
||||
return false;
|
||||
dir = &((*i).second);
|
||||
}
|
||||
|
||||
for (std::map<std::string, FileStat>::const_iterator i = dir->files.begin(); i != dir->files.end(); ++i)
|
||||
output.push_back((*i).second.info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileSourceZip::AddFile(const std::string &path, const FileStat &fileStat)
|
||||
{
|
||||
std::vector<std::string> fragments;
|
||||
SplitPath(path, fragments);
|
||||
|
||||
assert(fragments.size() > 0);
|
||||
|
||||
Directory *dir = &m_root;
|
||||
|
||||
if (fragments.size() > 1) {
|
||||
std::string fullPath;
|
||||
|
||||
for (unsigned int i = 0; i < fragments.size() - 1; i++) {
|
||||
fullPath += ((i > 0) ? "/" : "") + fragments[i];
|
||||
|
||||
std::map<std::string, FileStat>::const_iterator it = dir->files.find(fragments[i]);
|
||||
if (it == dir->files.end())
|
||||
dir->files.insert(std::make_pair(fragments[i], FileStat(Uint32(-1), 0, MakeFileInfo(fullPath, FileInfo::FT_DIR))));
|
||||
dir = &(dir->subdirs[fragments[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
const std::string &filename = fragments.back();
|
||||
|
||||
if (fileStat.info.IsDir())
|
||||
dir->subdirs.insert(std::make_pair(filename, Directory()));
|
||||
|
||||
dir->files.insert(std::make_pair(filename, fileStat));
|
||||
}
|
||||
|
||||
} // namespace FileSystem
|
||||
|
|
|
@ -11,38 +11,41 @@
|
|||
|
||||
namespace FileSystem {
|
||||
|
||||
class FileSourceZip : public FileSource {
|
||||
public:
|
||||
// for now this needs to be FileSourceFS rather than just FileSource,
|
||||
// because we need a FILE* stream access to the .zip file
|
||||
FileSourceZip(FileSourceFS &fs, const std::string &zipPath);
|
||||
virtual ~FileSourceZip();
|
||||
class FileSourceZip : public FileSource {
|
||||
public:
|
||||
// for now this needs to be FileSourceFS rather than just FileSource,
|
||||
// because we need a FILE* stream access to the .zip file
|
||||
FileSourceZip(FileSourceFS &fs, const std::string &zipPath);
|
||||
virtual ~FileSourceZip();
|
||||
|
||||
virtual FileInfo Lookup(const std::string &path);
|
||||
virtual RefCountedPtr<FileData> ReadFile(const std::string &path);
|
||||
virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output);
|
||||
virtual FileInfo Lookup(const std::string &path);
|
||||
virtual RefCountedPtr<FileData> ReadFile(const std::string &path);
|
||||
virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output);
|
||||
|
||||
private:
|
||||
void *m_archive;
|
||||
private:
|
||||
void *m_archive;
|
||||
|
||||
struct FileStat {
|
||||
FileStat(Uint32 _index, Uint64 _size, const FileInfo &_info) : index(_index), size(_size), info(_info) {}
|
||||
const Uint32 index;
|
||||
const Uint64 size;
|
||||
const FileInfo info;
|
||||
struct FileStat {
|
||||
FileStat(Uint32 _index, Uint64 _size, const FileInfo &_info) :
|
||||
index(_index),
|
||||
size(_size),
|
||||
info(_info) {}
|
||||
const Uint32 index;
|
||||
const Uint64 size;
|
||||
const FileInfo info;
|
||||
};
|
||||
|
||||
struct Directory {
|
||||
std::map<std::string, Directory> subdirs;
|
||||
std::map<std::string, FileStat> files;
|
||||
};
|
||||
|
||||
Directory m_root;
|
||||
|
||||
bool FindDirectoryAndFile(const std::string &path, const Directory *&dir, std::string &filename);
|
||||
void AddFile(const std::string &path, const FileStat &fileStat);
|
||||
};
|
||||
|
||||
struct Directory {
|
||||
std::map<std::string,Directory> subdirs;
|
||||
std::map<std::string,FileStat> files;
|
||||
};
|
||||
|
||||
Directory m_root;
|
||||
|
||||
bool FindDirectoryAndFile(const std::string &path, const Directory* &dir, std::string &filename);
|
||||
void AddFile(const std::string &path, const FileStat &fileStat);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace FileSystem
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "FileSystem.h"
|
||||
#include "StringRange.h"
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include "libs.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace FileSystem {
|
||||
|
@ -71,7 +71,9 @@ namespace FileSystem {
|
|||
if (result.size() <= initial_result_length)
|
||||
throw std::invalid_argument(path.ToString());
|
||||
size_t pos = result.rfind('/');
|
||||
if (pos == std::string::npos) { pos = 0; }
|
||||
if (pos == std::string::npos) {
|
||||
pos = 0;
|
||||
}
|
||||
assert(pos >= initial_result_length);
|
||||
result.erase(pos);
|
||||
} else {
|
||||
|
@ -80,7 +82,9 @@ namespace FileSystem {
|
|||
result += '/';
|
||||
result.append(part.begin, part.Size());
|
||||
}
|
||||
if (part.end == path.end) { break; }
|
||||
if (part.end == path.end) {
|
||||
break;
|
||||
}
|
||||
assert(*part.end == '/');
|
||||
part.begin = part.end + 1;
|
||||
part.end = path.end;
|
||||
|
@ -105,7 +109,7 @@ namespace FileSystem {
|
|||
else {
|
||||
std::string result(base);
|
||||
result.reserve(result.size() + 1 + path.size());
|
||||
if (result[result.size()-1] != '/')
|
||||
if (result[result.size() - 1] != '/')
|
||||
result += '/';
|
||||
StringRange rhs(path.c_str(), path.size());
|
||||
if (path[0] == '/') {
|
||||
|
@ -129,14 +133,14 @@ namespace FileSystem {
|
|||
{
|
||||
}
|
||||
|
||||
FileInfo::FileInfo(FileSource *source, const std::string &path, FileType type, Time::DateTime modTime):
|
||||
FileInfo::FileInfo(FileSource *source, const std::string &path, FileType type, Time::DateTime modTime) :
|
||||
m_source(source),
|
||||
m_path(path),
|
||||
m_modTime(modTime),
|
||||
m_dirLen(0),
|
||||
m_type(type)
|
||||
{
|
||||
assert((m_path.size() <= 1) || (m_path[m_path.size()-1] != '/'));
|
||||
assert((m_path.size() <= 1) || (m_path[m_path.size() - 1] != '/'));
|
||||
std::size_t slashpos = m_path.rfind('/');
|
||||
if (slashpos != std::string::npos) {
|
||||
m_dirLen = slashpos + 1;
|
||||
|
@ -155,7 +159,8 @@ namespace FileSystem {
|
|||
return MakeFileInfo(path, fileType, Time::DateTime());
|
||||
}
|
||||
|
||||
FileSourceUnion::FileSourceUnion(): FileSource(":union:") {}
|
||||
FileSourceUnion::FileSourceUnion() :
|
||||
FileSource(":union:") {}
|
||||
FileSourceUnion::~FileSourceUnion() {}
|
||||
|
||||
void FileSourceUnion::PrependSource(FileSource *fs)
|
||||
|
@ -174,17 +179,19 @@ namespace FileSystem {
|
|||
|
||||
void FileSourceUnion::RemoveSource(FileSource *fs)
|
||||
{
|
||||
std::vector<FileSource*>::iterator nend = std::remove(m_sources.begin(), m_sources.end(), fs);
|
||||
std::vector<FileSource *>::iterator nend = std::remove(m_sources.begin(), m_sources.end(), fs);
|
||||
m_sources.erase(nend, m_sources.end());
|
||||
}
|
||||
|
||||
FileInfo FileSourceUnion::Lookup(const std::string &path)
|
||||
{
|
||||
for (std::vector<FileSource*>::const_iterator
|
||||
it = m_sources.begin(); it != m_sources.end(); ++it)
|
||||
{
|
||||
for (std::vector<FileSource *>::const_iterator
|
||||
it = m_sources.begin();
|
||||
it != m_sources.end(); ++it) {
|
||||
FileInfo info = (*it)->Lookup(path);
|
||||
if (info.Exists()) { return info; }
|
||||
if (info.Exists()) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return MakeFileInfo(path, FileInfo::FT_NON_EXISTENT);
|
||||
}
|
||||
|
@ -203,11 +210,13 @@ namespace FileSystem {
|
|||
|
||||
RefCountedPtr<FileData> FileSourceUnion::ReadFile(const std::string &path)
|
||||
{
|
||||
for (std::vector<FileSource*>::const_iterator
|
||||
it = m_sources.begin(); it != m_sources.end(); ++it)
|
||||
{
|
||||
for (std::vector<FileSource *>::const_iterator
|
||||
it = m_sources.begin();
|
||||
it != m_sources.end(); ++it) {
|
||||
RefCountedPtr<FileData> data = (*it)->ReadFile(path);
|
||||
if (data) { return data; }
|
||||
if (data) {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return RefCountedPtr<FileData>();
|
||||
}
|
||||
|
@ -218,16 +227,19 @@ namespace FileSystem {
|
|||
// in preference to non-directories; otherwise, the FileInfo from the
|
||||
// first vector is selected in preference to the second vector.
|
||||
static void file_union_merge(
|
||||
std::vector<FileInfo>::const_iterator a, std::vector<FileInfo>::const_iterator aend,
|
||||
std::vector<FileInfo>::const_iterator b, std::vector<FileInfo>::const_iterator bend,
|
||||
std::vector<FileInfo> &output)
|
||||
std::vector<FileInfo>::const_iterator a, std::vector<FileInfo>::const_iterator aend,
|
||||
std::vector<FileInfo>::const_iterator b, std::vector<FileInfo>::const_iterator bend,
|
||||
std::vector<FileInfo> &output)
|
||||
{
|
||||
while ((a != aend) && (b != bend)) {
|
||||
int order = a->GetPath().compare(b->GetPath());
|
||||
int which = order;
|
||||
if (which == 0) {
|
||||
if (b->IsDir() && !a->IsDir()) { which = 1; }
|
||||
else { which = -1; }
|
||||
if (b->IsDir() && !a->IsDir()) {
|
||||
which = 1;
|
||||
} else {
|
||||
which = -1;
|
||||
}
|
||||
}
|
||||
if (which < 0) {
|
||||
output.push_back(*a++);
|
||||
|
@ -238,8 +250,12 @@ namespace FileSystem {
|
|||
}
|
||||
}
|
||||
|
||||
if (a != aend) { std::copy(a, aend, std::back_inserter(output)); }
|
||||
if (b != bend) { std::copy(b, bend, std::back_inserter(output)); }
|
||||
if (a != aend) {
|
||||
std::copy(a, aend, std::back_inserter(output));
|
||||
}
|
||||
if (b != bend) {
|
||||
std::copy(b, bend, std::back_inserter(output));
|
||||
}
|
||||
}
|
||||
|
||||
bool FileSourceUnion::ReadDirectory(const std::string &path, std::vector<FileInfo> &output)
|
||||
|
@ -254,9 +270,9 @@ namespace FileSystem {
|
|||
bool founddir = false;
|
||||
|
||||
std::vector<FileInfo> merged;
|
||||
for (std::vector<FileSource*>::const_iterator
|
||||
it = m_sources.begin(); it != m_sources.end(); ++it)
|
||||
{
|
||||
for (std::vector<FileSource *>::const_iterator
|
||||
it = m_sources.begin();
|
||||
it != m_sources.end(); ++it) {
|
||||
std::vector<FileInfo> nextfiles;
|
||||
if ((*it)->ReadDirectory(path, nextfiles)) {
|
||||
founddir = true;
|
||||
|
@ -278,11 +294,13 @@ namespace FileSystem {
|
|||
return founddir;
|
||||
}
|
||||
|
||||
FileEnumerator::FileEnumerator(FileSource &fs, int flags):
|
||||
m_source(&fs), m_flags(flags) {}
|
||||
FileEnumerator::FileEnumerator(FileSource &fs, int flags) :
|
||||
m_source(&fs),
|
||||
m_flags(flags) {}
|
||||
|
||||
FileEnumerator::FileEnumerator(FileSource &fs, const std::string &path, int flags):
|
||||
m_source(&fs), m_flags(flags)
|
||||
FileEnumerator::FileEnumerator(FileSource &fs, const std::string &path, int flags) :
|
||||
m_source(&fs),
|
||||
m_flags(flags)
|
||||
{
|
||||
AddSearchRoot(path);
|
||||
}
|
||||
|
@ -321,20 +339,29 @@ namespace FileSystem {
|
|||
std::vector<FileInfo> entries;
|
||||
m_source->ReadDirectory(info.GetPath(), entries);
|
||||
for (std::vector<FileInfo>::const_iterator
|
||||
it = entries.begin(); it != entries.end(); ++it) {
|
||||
it = entries.begin();
|
||||
it != entries.end(); ++it) {
|
||||
|
||||
switch (it->GetType()) {
|
||||
case FileInfo::FT_DIR:
|
||||
if (m_flags & IncludeDirs) { m_queue.push_back(*it); }
|
||||
if (m_flags & Recurse) { m_dirQueue.push_back(*it); }
|
||||
break;
|
||||
case FileInfo::FT_FILE:
|
||||
if (!(m_flags & ExcludeFiles)) { m_queue.push_back(*it); }
|
||||
break;
|
||||
case FileInfo::FT_SPECIAL:
|
||||
if (m_flags & IncludeSpecials) { m_queue.push_back(*it); }
|
||||
break;
|
||||
default: assert(0); break;
|
||||
case FileInfo::FT_DIR:
|
||||
if (m_flags & IncludeDirs) {
|
||||
m_queue.push_back(*it);
|
||||
}
|
||||
if (m_flags & Recurse) {
|
||||
m_dirQueue.push_back(*it);
|
||||
}
|
||||
break;
|
||||
case FileInfo::FT_FILE:
|
||||
if (!(m_flags & ExcludeFiles)) {
|
||||
m_queue.push_back(*it);
|
||||
}
|
||||
break;
|
||||
case FileInfo::FT_SPECIAL:
|
||||
if (m_flags & IncludeSpecials) {
|
||||
m_queue.push_back(*it);
|
||||
}
|
||||
break;
|
||||
default: assert(0); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
#ifndef _FILESYSTEM_H
|
||||
#define _FILESYSTEM_H
|
||||
|
||||
#include "RefCounted.h"
|
||||
#include "StringRange.h"
|
||||
#include "ByteRange.h"
|
||||
#include "DateTime.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "RefCounted.h"
|
||||
#include "StringRange.h"
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
* Functionality:
|
||||
|
@ -63,8 +63,12 @@ namespace FileSystem {
|
|||
|
||||
class FileInfo {
|
||||
friend class FileSource;
|
||||
|
||||
public:
|
||||
FileInfo(): m_source(0), m_dirLen(0), m_type(FT_NON_EXISTENT) {}
|
||||
FileInfo() :
|
||||
m_source(0),
|
||||
m_dirLen(0),
|
||||
m_type(FT_NON_EXISTENT) {}
|
||||
|
||||
enum FileType {
|
||||
// note: order here affects sort-order of FileInfo
|
||||
|
@ -95,24 +99,36 @@ namespace FileSystem {
|
|||
RefCountedPtr<FileData> Read() const;
|
||||
|
||||
friend bool operator==(const FileInfo &a, const FileInfo &b)
|
||||
{ return (a.m_source == b.m_source && a.m_type == b.m_type && a.m_path == b.m_path); }
|
||||
{
|
||||
return (a.m_source == b.m_source && a.m_type == b.m_type && a.m_path == b.m_path);
|
||||
}
|
||||
friend bool operator!=(const FileInfo &a, const FileInfo &b)
|
||||
{ return (a.m_source != b.m_source || a.m_type != b.m_type || a.m_path != b.m_path); }
|
||||
friend bool operator< (const FileInfo &a, const FileInfo &b)
|
||||
{
|
||||
return (a.m_source != b.m_source || a.m_type != b.m_type || a.m_path != b.m_path);
|
||||
}
|
||||
friend bool operator<(const FileInfo &a, const FileInfo &b)
|
||||
{
|
||||
int c = a.m_path.compare(b.m_path);
|
||||
if (c != 0) { return (c < 0); }
|
||||
if (a.m_type != b.m_type) { return (a.m_type < b.m_type); }
|
||||
if (c != 0) {
|
||||
return (c < 0);
|
||||
}
|
||||
if (a.m_type != b.m_type) {
|
||||
return (a.m_type < b.m_type);
|
||||
}
|
||||
return (a.m_source < b.m_source);
|
||||
}
|
||||
friend bool operator<=(const FileInfo &a, const FileInfo &b)
|
||||
{
|
||||
int c = a.m_path.compare(b.m_path);
|
||||
if (c != 0) { return (c < 0); }
|
||||
if (a.m_type != b.m_type) { return (a.m_type < b.m_type); }
|
||||
if (c != 0) {
|
||||
return (c < 0);
|
||||
}
|
||||
if (a.m_type != b.m_type) {
|
||||
return (a.m_type < b.m_type);
|
||||
}
|
||||
return (a.m_source <= b.m_source);
|
||||
}
|
||||
friend bool operator> (const FileInfo &a, const FileInfo &b) { return (b < a); }
|
||||
friend bool operator>(const FileInfo &a, const FileInfo &b) { return (b < a); }
|
||||
friend bool operator>=(const FileInfo &a, const FileInfo &b) { return (b <= a); }
|
||||
|
||||
private:
|
||||
|
@ -132,14 +148,23 @@ namespace FileSystem {
|
|||
|
||||
const FileInfo &GetInfo() const { return m_info; }
|
||||
size_t GetSize() const { return m_size; }
|
||||
const char *GetData() const { assert(m_info.IsFile()); return m_data; }
|
||||
const char *GetData() const
|
||||
{
|
||||
assert(m_info.IsFile());
|
||||
return m_data;
|
||||
}
|
||||
StringRange AsStringRange() const { return StringRange(m_data, m_size); }
|
||||
ByteRange AsByteRange() const { return ByteRange(m_data, m_size); }
|
||||
|
||||
protected:
|
||||
FileData(const FileInfo &info, size_t size, char *data):
|
||||
m_info(info), m_data(data), m_size(size) {}
|
||||
FileData(const FileInfo &info): m_info(info), m_data(0), m_size(0) {}
|
||||
FileData(const FileInfo &info, size_t size, char *data) :
|
||||
m_info(info),
|
||||
m_data(data),
|
||||
m_size(size) {}
|
||||
FileData(const FileInfo &info) :
|
||||
m_info(info),
|
||||
m_data(0),
|
||||
m_size(0) {}
|
||||
|
||||
FileInfo m_info;
|
||||
char *m_data;
|
||||
|
@ -148,16 +173,18 @@ namespace FileSystem {
|
|||
|
||||
class FileDataMalloc : public FileData {
|
||||
public:
|
||||
FileDataMalloc(const FileInfo &info, size_t size):
|
||||
FileData(info, size, static_cast<char*>(std::malloc(size))) {}
|
||||
FileDataMalloc(const FileInfo &info, size_t size, char *data):
|
||||
FileDataMalloc(const FileInfo &info, size_t size) :
|
||||
FileData(info, size, static_cast<char *>(std::malloc(size))) {}
|
||||
FileDataMalloc(const FileInfo &info, size_t size, char *data) :
|
||||
FileData(info, size, data) {}
|
||||
virtual ~FileDataMalloc() { std::free(m_data); }
|
||||
};
|
||||
|
||||
class FileSource {
|
||||
public:
|
||||
explicit FileSource(const std::string &root, bool trusted = false): m_root(root), m_trusted(trusted) {}
|
||||
explicit FileSource(const std::string &root, bool trusted = false) :
|
||||
m_root(root),
|
||||
m_trusted(trusted) {}
|
||||
virtual ~FileSource() {}
|
||||
|
||||
const std::string &GetRoot() const { return m_root; }
|
||||
|
@ -193,9 +220,9 @@ namespace FileSystem {
|
|||
};
|
||||
|
||||
// similar to fopen(path, "rb")
|
||||
FILE* OpenReadStream(const std::string &path);
|
||||
FILE *OpenReadStream(const std::string &path);
|
||||
// similar to fopen(path, "wb")
|
||||
FILE* OpenWriteStream(const std::string &path, int flags = 0);
|
||||
FILE *OpenWriteStream(const std::string &path, int flags = 0);
|
||||
};
|
||||
|
||||
class FileSourceUnion : public FileSource {
|
||||
|
@ -216,16 +243,16 @@ namespace FileSystem {
|
|||
virtual bool ReadDirectory(const std::string &path, std::vector<FileInfo> &output);
|
||||
|
||||
private:
|
||||
std::vector<FileSource*> m_sources;
|
||||
std::vector<FileSource *> m_sources;
|
||||
};
|
||||
|
||||
class FileEnumerator {
|
||||
public:
|
||||
enum Flags {
|
||||
IncludeDirs = 1,
|
||||
IncludeSpecials = 2,
|
||||
ExcludeFiles = 4,
|
||||
Recurse = 8
|
||||
IncludeDirs = 1,
|
||||
IncludeSpecials = 2,
|
||||
ExcludeFiles = 4,
|
||||
Recurse = 8
|
||||
};
|
||||
|
||||
explicit FileEnumerator(FileSource &fs, int flags = 0);
|
||||
|
@ -251,12 +278,18 @@ namespace FileSystem {
|
|||
} // namespace FileSystem
|
||||
|
||||
inline std::string FileSystem::FileInfo::GetAbsoluteDir() const
|
||||
{ return JoinPath(m_source->GetRoot(), GetDir()); }
|
||||
{
|
||||
return JoinPath(m_source->GetRoot(), GetDir());
|
||||
}
|
||||
|
||||
inline std::string FileSystem::FileInfo::GetAbsolutePath() const
|
||||
{ return JoinPath(m_source->GetRoot(), GetPath()); }
|
||||
{
|
||||
return JoinPath(m_source->GetRoot(), GetPath());
|
||||
}
|
||||
|
||||
inline RefCountedPtr<FileSystem::FileData> FileSystem::FileInfo::Read() const
|
||||
{ return m_source->ReadFile(m_path); }
|
||||
{
|
||||
return m_source->ReadFile(m_path);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "FixedGuns.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "Beam.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "StringF.h"
|
||||
|
||||
FixedGuns::FixedGuns()
|
||||
|
@ -34,7 +34,7 @@ bool FixedGuns::IsBeam(const int num)
|
|||
|
||||
void FixedGuns::Init(DynamicBody *b)
|
||||
{
|
||||
for (int i=0; i<Guns::GUNMOUNT_MAX; i++) {
|
||||
for (int i = 0; i < Guns::GUNMOUNT_MAX; i++) {
|
||||
// Initialize structs
|
||||
m_is_firing[i] = false;
|
||||
m_gun[i].recharge = 0;
|
||||
|
@ -52,16 +52,15 @@ void FixedGuns::Init(DynamicBody *b)
|
|||
m_recharge_stat[i] = 0.0;
|
||||
m_temperature_stat[i] = 0.0;
|
||||
};
|
||||
b->AddFeature( DynamicBody::FIXED_GUNS );
|
||||
b->AddFeature(DynamicBody::FIXED_GUNS);
|
||||
}
|
||||
|
||||
void FixedGuns::SaveToJson( Json &jsonObj, Space *space )
|
||||
void FixedGuns::SaveToJson(Json &jsonObj, Space *space)
|
||||
{
|
||||
|
||||
Json gunArray = Json::array(); // Create JSON array to contain gun data.
|
||||
|
||||
for (int i = 0; i<Guns::GUNMOUNT_MAX; i++)
|
||||
{
|
||||
for (int i = 0; i < Guns::GUNMOUNT_MAX; i++) {
|
||||
Json gunArrayEl = Json::object(); // Create JSON object to contain gun.
|
||||
gunArrayEl["state"] = m_is_firing[i];
|
||||
gunArrayEl["recharge"] = m_recharge_stat[i];
|
||||
|
@ -71,14 +70,13 @@ void FixedGuns::SaveToJson( Json &jsonObj, Space *space )
|
|||
jsonObj["guns"] = gunArray; // Add gun array to ship object.
|
||||
};
|
||||
|
||||
void FixedGuns::LoadFromJson( const Json &jsonObj, Space *space )
|
||||
void FixedGuns::LoadFromJson(const Json &jsonObj, Space *space)
|
||||
{
|
||||
Json gunArray = jsonObj["guns"].get<Json::array_t>();
|
||||
assert(Guns::GUNMOUNT_MAX == gunArray.size());
|
||||
|
||||
try {
|
||||
for (unsigned int i = 0; i < Guns::GUNMOUNT_MAX; i++)
|
||||
{
|
||||
for (unsigned int i = 0; i < Guns::GUNMOUNT_MAX; i++) {
|
||||
Json gunArrayEl = gunArray[i];
|
||||
|
||||
m_is_firing[i] = gunArrayEl["state"];
|
||||
|
@ -90,16 +88,14 @@ void FixedGuns::LoadFromJson( const Json &jsonObj, Space *space )
|
|||
}
|
||||
};
|
||||
|
||||
void FixedGuns::InitGuns( SceneGraph::Model *m)
|
||||
void FixedGuns::InitGuns(SceneGraph::Model *m)
|
||||
{
|
||||
for (int num = 0; num < Guns::GUNMOUNT_MAX; num++)
|
||||
{
|
||||
for (int num = 0; num < Guns::GUNMOUNT_MAX; num++) {
|
||||
int found = 0;
|
||||
// probably 4 is fine 99% of the time (X-Wings)
|
||||
m_gun[num].locs.reserve(4);
|
||||
// 32 is a crazy number...
|
||||
for (int gun = 0; gun < 32; gun++)
|
||||
{
|
||||
// 32 is a crazy number...
|
||||
for (int gun = 0; gun < 32; gun++) {
|
||||
const std::string tag = stringf("tag_gunmount_%0{d}_multi_%1{d}", num, gun); //"gunmount_0_multi_0";
|
||||
const SceneGraph::MatrixTransform *mt = m->FindTagByName(tag);
|
||||
if (mt) {
|
||||
|
@ -109,9 +105,7 @@ void FixedGuns::InitGuns( SceneGraph::Model *m)
|
|||
loc.pos = vector3d(trans.GetTranslate());
|
||||
loc.dir = vector3d(trans.GetOrient().VectorZ());
|
||||
m_gun[num].locs.push_back(loc);
|
||||
}
|
||||
else if (found == 0)
|
||||
{
|
||||
} else if (found == 0) {
|
||||
// look for legacy "tag_gunmount_0" or "tag_gunmount_1" tags
|
||||
const std::string tag = stringf("tag_gunmount_%0{d}", num); //"gunmount_0";
|
||||
const SceneGraph::MatrixTransform *mt = m->FindTagByName(tag);
|
||||
|
@ -124,17 +118,16 @@ void FixedGuns::InitGuns( SceneGraph::Model *m)
|
|||
m_gun[num].locs.push_back(loc);
|
||||
}
|
||||
break; // definitely no more "gun"s for this "num" if we've come down this path
|
||||
}
|
||||
else
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FixedGuns::MountGun(const int num, const float recharge, const float lifespan, const float damage, const float length,
|
||||
const float width, const bool mining, const Color& color, const float speed, const bool beam, const float heatrate, const float coolrate )
|
||||
const float width, const bool mining, const Color &color, const float speed, const bool beam, const float heatrate, const float coolrate)
|
||||
{
|
||||
if(num >= Guns::GUNMOUNT_MAX)
|
||||
if (num >= Guns::GUNMOUNT_MAX)
|
||||
return;
|
||||
// Here we have projectile data MORE recharge time
|
||||
m_is_firing[num] = false;
|
||||
|
@ -152,11 +145,11 @@ void FixedGuns::MountGun(const int num, const float recharge, const float lifesp
|
|||
m_gun_present[num] = true;
|
||||
};
|
||||
|
||||
void FixedGuns::UnMountGun( int num )
|
||||
void FixedGuns::UnMountGun(int num)
|
||||
{
|
||||
if(num >= Guns::GUNMOUNT_MAX)
|
||||
if (num >= Guns::GUNMOUNT_MAX)
|
||||
return;
|
||||
if(!m_gun_present[num])
|
||||
if (!m_gun_present[num])
|
||||
return;
|
||||
m_is_firing[num] = false;
|
||||
m_gun[num].recharge = 0;
|
||||
|
@ -172,13 +165,13 @@ void FixedGuns::UnMountGun( int num )
|
|||
m_gun_present[num] = false;
|
||||
}
|
||||
|
||||
bool FixedGuns::Fire( const int num, Body* b )
|
||||
bool FixedGuns::Fire(const int num, Body *b)
|
||||
{
|
||||
if (!m_gun_present[num]) return false;
|
||||
if (!m_is_firing[num]) return false;
|
||||
// Output("Firing gun %i, present\n", num);
|
||||
// Output(" is firing\n");
|
||||
if (m_recharge_stat[num]>0) return false;
|
||||
if (m_recharge_stat[num] > 0) return false;
|
||||
// Output(" recharge stat <= 0\n");
|
||||
if (m_temperature_stat[num] > 1.0) return false;
|
||||
// Output(" temperature stat <= 1.0\n");
|
||||
|
@ -188,36 +181,32 @@ bool FixedGuns::Fire( const int num, Body* b )
|
|||
|
||||
const int maxBarrels = std::min(size_t(m_gun[num].dual ? 2 : 1), m_gun[num].locs.size());
|
||||
|
||||
for (int iBarrel = 0; iBarrel < maxBarrels; iBarrel++)
|
||||
{
|
||||
for (int iBarrel = 0; iBarrel < maxBarrels; iBarrel++) {
|
||||
const vector3d dir = (b->GetOrient() * vector3d(m_gun[num].locs[iBarrel].dir)).Normalized();
|
||||
const vector3d pos = b->GetOrient() * vector3d(m_gun[num].locs[iBarrel].pos) + b->GetPosition();
|
||||
|
||||
if (m_gun[num].projData.beam)
|
||||
{
|
||||
if (m_gun[num].projData.beam) {
|
||||
Beam::Add(b, m_gun[num].projData, pos, b->GetVelocity(), dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
const vector3d dirVel = m_gun[num].projData.speed * dir;
|
||||
Projectile::Add(b, m_gun[num].projData, pos, b->GetVelocity(), dirVel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
void FixedGuns::UpdateGuns( float timeStep )
|
||||
void FixedGuns::UpdateGuns(float timeStep)
|
||||
{
|
||||
for (int i=0; i<Guns::GUNMOUNT_MAX; i++) {
|
||||
if ( !m_gun_present[i] )
|
||||
for (int i = 0; i < Guns::GUNMOUNT_MAX; i++) {
|
||||
if (!m_gun_present[i])
|
||||
continue;
|
||||
|
||||
m_recharge_stat[i] -= timeStep;
|
||||
|
||||
float rateCooling = m_gun[i].temp_cool_rate;
|
||||
rateCooling *= m_cooler_boost;
|
||||
m_temperature_stat[i] -= rateCooling*timeStep;
|
||||
m_temperature_stat[i] -= rateCooling * timeStep;
|
||||
|
||||
if (m_temperature_stat[i] < 0.0f)
|
||||
m_temperature_stat[i] = 0;
|
||||
|
@ -227,10 +216,10 @@ void FixedGuns::UpdateGuns( float timeStep )
|
|||
if (m_recharge_stat[i] < 0.0f)
|
||||
m_recharge_stat[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
float FixedGuns::GetGunTemperature(int idx) const {
|
||||
if(m_gun_present[idx])
|
||||
float FixedGuns::GetGunTemperature(int idx) const
|
||||
{
|
||||
if (m_gun_present[idx])
|
||||
return m_temperature_stat[idx];
|
||||
else
|
||||
return 0.0f;
|
||||
|
|
102
src/FixedGuns.h
102
src/FixedGuns.h
|
@ -4,14 +4,14 @@
|
|||
#ifndef FIXEDGUNS_H
|
||||
#define FIXEDGUNS_H
|
||||
|
||||
#include "vector3.h"
|
||||
#include "libs.h"
|
||||
#include "Space.h"
|
||||
#include "Camera.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "scenegraph/Model.h"
|
||||
#include "Projectile.h"
|
||||
#include "DynamicBody.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "Projectile.h"
|
||||
#include "Space.h"
|
||||
#include "libs.h"
|
||||
#include "scenegraph/Model.h"
|
||||
#include "vector3.h"
|
||||
|
||||
enum Guns {
|
||||
GUN_FRONT,
|
||||
|
@ -19,54 +19,54 @@ enum Guns {
|
|||
GUNMOUNT_MAX = 2
|
||||
};
|
||||
|
||||
class FixedGuns : public RefCounted
|
||||
{
|
||||
public:
|
||||
FixedGuns();
|
||||
virtual ~FixedGuns();
|
||||
void Init(DynamicBody *b);
|
||||
void InitGuns( SceneGraph::Model *m);
|
||||
void UpdateGuns( float timeStep );
|
||||
bool Fire( const int num, Body* b );
|
||||
bool IsFiring();
|
||||
bool IsFiring(const int num);
|
||||
bool IsBeam(const int num);
|
||||
float GetGunTemperature(int idx) const;
|
||||
inline void IsDual( int idx, bool dual ) { m_gun[idx].dual = dual; };
|
||||
void MountGun( const int num, const float recharge, const float lifespan, const float damage, const float length,
|
||||
const float width, const bool mining, const Color& color, const float speed, const bool beam, const float heatrate, const float coolrate);
|
||||
void UnMountGun( int num );
|
||||
inline float GetGunRange( int idx ) { return m_gun[idx].projData.speed*m_gun[idx].projData.lifespan; };
|
||||
inline float GetProjSpeed(int idx ) { return m_gun[idx].projData.speed; };
|
||||
inline void SetCoolingBoost( float cooler ) { m_cooler_boost = cooler; };
|
||||
inline void SetGunFiringState( int idx, int s ) {
|
||||
if(m_gun_present[idx])
|
||||
m_is_firing[idx] = s;
|
||||
};
|
||||
virtual void SaveToJson( Json &jsonObj, Space *space);
|
||||
virtual void LoadFromJson( const Json &jsonObj, Space *space);
|
||||
private:
|
||||
class FixedGuns : public RefCounted {
|
||||
public:
|
||||
FixedGuns();
|
||||
virtual ~FixedGuns();
|
||||
void Init(DynamicBody *b);
|
||||
void InitGuns(SceneGraph::Model *m);
|
||||
void UpdateGuns(float timeStep);
|
||||
bool Fire(const int num, Body *b);
|
||||
bool IsFiring();
|
||||
bool IsFiring(const int num);
|
||||
bool IsBeam(const int num);
|
||||
float GetGunTemperature(int idx) const;
|
||||
inline void IsDual(int idx, bool dual) { m_gun[idx].dual = dual; };
|
||||
void MountGun(const int num, const float recharge, const float lifespan, const float damage, const float length,
|
||||
const float width, const bool mining, const Color &color, const float speed, const bool beam, const float heatrate, const float coolrate);
|
||||
void UnMountGun(int num);
|
||||
inline float GetGunRange(int idx) { return m_gun[idx].projData.speed * m_gun[idx].projData.lifespan; };
|
||||
inline float GetProjSpeed(int idx) { return m_gun[idx].projData.speed; };
|
||||
inline void SetCoolingBoost(float cooler) { m_cooler_boost = cooler; };
|
||||
inline void SetGunFiringState(int idx, int s)
|
||||
{
|
||||
if (m_gun_present[idx])
|
||||
m_is_firing[idx] = s;
|
||||
};
|
||||
virtual void SaveToJson(Json &jsonObj, Space *space);
|
||||
virtual void LoadFromJson(const Json &jsonObj, Space *space);
|
||||
|
||||
struct GunData {
|
||||
struct GunLoc {
|
||||
vector3d pos;
|
||||
vector3d dir;
|
||||
};
|
||||
std::vector<GunLoc> locs;
|
||||
float recharge;
|
||||
float temp_heat_rate;
|
||||
float temp_cool_rate;
|
||||
bool dual;
|
||||
ProjectileData projData;
|
||||
private:
|
||||
struct GunData {
|
||||
struct GunLoc {
|
||||
vector3d pos;
|
||||
vector3d dir;
|
||||
};
|
||||
std::vector<GunLoc> locs;
|
||||
float recharge;
|
||||
float temp_heat_rate;
|
||||
float temp_cool_rate;
|
||||
bool dual;
|
||||
ProjectileData projData;
|
||||
};
|
||||
|
||||
bool m_is_firing[Guns::GUNMOUNT_MAX];
|
||||
float m_recharge_stat[Guns::GUNMOUNT_MAX];
|
||||
float m_temperature_stat[Guns::GUNMOUNT_MAX];
|
||||
//TODO: Make it a vector and rework struct Gun to have bool dir={Forward,Backward}
|
||||
bool m_gun_present[Guns::GUNMOUNT_MAX];
|
||||
GunData m_gun[Guns::GUNMOUNT_MAX];
|
||||
float m_cooler_boost;
|
||||
bool m_is_firing[Guns::GUNMOUNT_MAX];
|
||||
float m_recharge_stat[Guns::GUNMOUNT_MAX];
|
||||
float m_temperature_stat[Guns::GUNMOUNT_MAX];
|
||||
//TODO: Make it a vector and rework struct Gun to have bool dir={Forward,Backward}
|
||||
bool m_gun_present[Guns::GUNMOUNT_MAX];
|
||||
GunData m_gun[Guns::GUNMOUNT_MAX];
|
||||
float m_cooler_boost;
|
||||
};
|
||||
|
||||
#endif // FIXEDGUNS_H
|
||||
|
|
|
@ -39,33 +39,38 @@
|
|||
// bool is_nan(float x);
|
||||
// bool is_finite(float x);
|
||||
|
||||
|
||||
// ====================================================================
|
||||
|
||||
// in the following code, IEEEFloatTraits<T>::bool_type is used to limit
|
||||
// the application of the functions by SFINAE
|
||||
|
||||
template <typename T> struct IEEEFloatTraits;
|
||||
template <typename T>
|
||||
struct IEEEFloatTraits;
|
||||
|
||||
// --- float function helpers
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::float_type float_abs(T x)
|
||||
{ return (x < T(0)) ? (-x) : x; }
|
||||
{
|
||||
return (x < T(0)) ? (-x) : x;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::float_type float_max(T x, T y)
|
||||
{ return (y > x) ? y : x; }
|
||||
{
|
||||
return (y > x) ? y : x;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::float_type float_max(T x, T y, T z)
|
||||
{ return float_max(x, float_max(y, z)); }
|
||||
{
|
||||
return float_max(x, float_max(y, z));
|
||||
}
|
||||
|
||||
// --- float property helpers
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_nan_bits
|
||||
(const typename IEEEFloatTraits<T>::uint_type& bits)
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_nan_bits(const typename IEEEFloatTraits<T>::uint_type &bits)
|
||||
{
|
||||
typedef typename IEEEFloatTraits<T>::uint_type uint_type;
|
||||
const uint_type top = IEEEFloatTraits<T>::TopBit;
|
||||
|
@ -79,8 +84,7 @@ inline typename IEEEFloatTraits<T>::bool_type is_nan_bits
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_finite_bits
|
||||
(const typename IEEEFloatTraits<T>::uint_type& bits)
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_finite_bits(const typename IEEEFloatTraits<T>::uint_type &bits)
|
||||
{
|
||||
typedef typename IEEEFloatTraits<T>::uint_type uint_type;
|
||||
const uint_type ebits = IEEEFloatTraits<T>::ExponentBits;
|
||||
|
@ -90,7 +94,8 @@ inline typename IEEEFloatTraits<T>::bool_type is_finite_bits
|
|||
// --- infinity
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_finite(T x) {
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_finite(T x)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return _finite(x);
|
||||
#else
|
||||
|
@ -104,7 +109,10 @@ inline typename IEEEFloatTraits<T>::bool_type is_finite(T x) {
|
|||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
#endif
|
||||
inline bool is_equal_exact(float a, float b) { return (a == b); }
|
||||
inline bool is_equal_exact(float a, float b)
|
||||
{
|
||||
return (a == b);
|
||||
}
|
||||
inline bool is_equal_exact(double a, double b) { return (a == b); }
|
||||
|
||||
inline bool is_zero_exact(float x) { return (x == 0.0f); }
|
||||
|
@ -119,36 +127,31 @@ inline bool is_nan(double x) { return (x != x); }
|
|||
// --- relative & absolute error comparisons
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_equal_relative
|
||||
(T a, T b, T tol = IEEEFloatTraits<T>::DefaultRelTolerance())
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_equal_relative(T a, T b, T tol = IEEEFloatTraits<T>::DefaultRelTolerance())
|
||||
{
|
||||
return (float_abs(a - b) <= tol * float_max(float_abs(a), float_abs(b)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_equal_absolute
|
||||
(T a, T b, T tol = IEEEFloatTraits<T>::DefaultAbsTolerance())
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_equal_absolute(T a, T b, T tol = IEEEFloatTraits<T>::DefaultAbsTolerance())
|
||||
{
|
||||
return (float_abs(a - b) <= tol);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_equal_general
|
||||
(T a, T b, T rel_tol, T abs_tol)
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_equal_general(T a, T b, T rel_tol, T abs_tol)
|
||||
{
|
||||
return (float_abs(a - b) <= float_max(abs_tol, rel_tol * float_max(float_abs(a), float_abs(b))));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_equal_general
|
||||
(T a, T b, T tol = IEEEFloatTraits<T>::DefaultTolerance())
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_equal_general(T a, T b, T tol = IEEEFloatTraits<T>::DefaultTolerance())
|
||||
{
|
||||
return (float_abs(a - b) <= tol * float_max(T(1), float_abs(a), float_abs(b)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_zero_general
|
||||
(T x, T tol = IEEEFloatTraits<T>::DefaultRelTolerance())
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_zero_general(T x, T tol = IEEEFloatTraits<T>::DefaultRelTolerance())
|
||||
{
|
||||
return (float_abs(x) <= tol);
|
||||
}
|
||||
|
@ -156,7 +159,8 @@ inline typename IEEEFloatTraits<T>::bool_type is_zero_general
|
|||
// --- ulp-based comparisons
|
||||
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::int_type float_ulp_difference(T a, T b) {
|
||||
inline typename IEEEFloatTraits<T>::int_type float_ulp_difference(T a, T b)
|
||||
{
|
||||
typedef typename IEEEFloatTraits<T>::FloatOrInt union_type;
|
||||
union_type afi, bfi;
|
||||
afi.f = a;
|
||||
|
@ -171,9 +175,7 @@ inline typename IEEEFloatTraits<T>::int_type float_ulp_difference(T a, T b) {
|
|||
|
||||
// IEEEFloatTraits<T>::bool_type used for SFINAE
|
||||
template <typename T>
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_equal_ulps
|
||||
(T a, T b, typename IEEEFloatTraits<T>::int_type max_ulps
|
||||
= IEEEFloatTraits<T>::DefaultUlpTolerance)
|
||||
inline typename IEEEFloatTraits<T>::bool_type is_equal_ulps(T a, T b, typename IEEEFloatTraits<T>::int_type max_ulps = IEEEFloatTraits<T>::DefaultUlpTolerance)
|
||||
{
|
||||
typedef typename IEEEFloatTraits<T>::FloatOrInt union_type;
|
||||
typedef typename IEEEFloatTraits<T>::int_type int_type;
|
||||
|
@ -182,13 +184,12 @@ inline typename IEEEFloatTraits<T>::bool_type is_equal_ulps
|
|||
bfi.f = b;
|
||||
|
||||
// Infinities aren't close to anything except themselves
|
||||
if ( (!is_finite_bits<T>(afi.ui) && is_finite_bits<T>(bfi.ui))
|
||||
|| (is_finite_bits<T>(afi.ui) && !is_finite_bits<T>(bfi.ui)))
|
||||
return false;
|
||||
if ((!is_finite_bits<T>(afi.ui) && is_finite_bits<T>(bfi.ui)) || (is_finite_bits<T>(afi.ui) && !is_finite_bits<T>(bfi.ui)))
|
||||
return false;
|
||||
|
||||
// IEEE says NaNs are unequal to everything (even themselves)
|
||||
if (is_nan_bits<T>(afi.ui) || is_nan_bits<T>(bfi.ui))
|
||||
return false;
|
||||
return false;
|
||||
|
||||
// transform from sign-magnitude to two's-complement
|
||||
if (afi.i < 0) afi.ui = (IEEEFloatTraits<T>::TopBit - afi.ui);
|
||||
|
@ -205,8 +206,7 @@ template <typename T>
|
|||
struct IEEEFloatTraits {};
|
||||
|
||||
template <>
|
||||
struct IEEEFloatTraits<double>
|
||||
{
|
||||
struct IEEEFloatTraits<double> {
|
||||
typedef double float_type;
|
||||
typedef bool bool_type;
|
||||
|
||||
|
@ -219,15 +219,11 @@ struct IEEEFloatTraits<double>
|
|||
int_type i;
|
||||
};
|
||||
|
||||
static const uint_type TopBit
|
||||
= static_cast<uint_type>(1) << (sizeof(double)*8 - 1);
|
||||
static const uint_type ExponentBits
|
||||
= (~static_cast<uint_type>(0) << std::numeric_limits<double>::digits) & ~TopBit;
|
||||
static const uint_type MantissaBits
|
||||
= ~TopBit & ~ExponentBits;
|
||||
static const uint_type TopBit = static_cast<uint_type>(1) << (sizeof(double) * 8 - 1);
|
||||
static const uint_type ExponentBits = (~static_cast<uint_type>(0) << std::numeric_limits<double>::digits) & ~TopBit;
|
||||
static const uint_type MantissaBits = ~TopBit & ~ExponentBits;
|
||||
|
||||
static const int_type DefaultUlpTolerance
|
||||
= 16;
|
||||
static const int_type DefaultUlpTolerance = 16;
|
||||
|
||||
static double DefaultAbsTolerance() { return 1e-12; }
|
||||
static double DefaultRelTolerance() { return 1e-6; }
|
||||
|
@ -236,8 +232,7 @@ struct IEEEFloatTraits<double>
|
|||
};
|
||||
|
||||
template <>
|
||||
struct IEEEFloatTraits<float>
|
||||
{
|
||||
struct IEEEFloatTraits<float> {
|
||||
typedef float float_type;
|
||||
typedef bool bool_type;
|
||||
|
||||
|
@ -250,15 +245,11 @@ struct IEEEFloatTraits<float>
|
|||
int_type i;
|
||||
};
|
||||
|
||||
static const uint_type TopBit
|
||||
= uint_type(1) << (sizeof(float)*8 - 1);
|
||||
static const uint_type ExponentBits
|
||||
= (~uint_type(0) << std::numeric_limits<float>::digits) & ~TopBit;
|
||||
static const uint_type MantissaBits
|
||||
= ~TopBit & ~ExponentBits;
|
||||
static const uint_type TopBit = uint_type(1) << (sizeof(float) * 8 - 1);
|
||||
static const uint_type ExponentBits = (~uint_type(0) << std::numeric_limits<float>::digits) & ~TopBit;
|
||||
static const uint_type MantissaBits = ~TopBit & ~ExponentBits;
|
||||
|
||||
static const int_type DefaultUlpTolerance
|
||||
= 4;
|
||||
static const int_type DefaultUlpTolerance = 4;
|
||||
|
||||
static float DefaultAbsTolerance() { return 1e-6f; }
|
||||
static float DefaultRelTolerance() { return 1e-5f; }
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "FontCache.h"
|
||||
#include "text/TextureFont.h"
|
||||
#include "FileSystem.h"
|
||||
#include "gui/GuiScreen.h"
|
||||
#include "Lang.h"
|
||||
#include "gui/GuiScreen.h"
|
||||
#include "text/TextureFont.h"
|
||||
|
||||
RefCountedPtr<Text::TextureFont> FontCache::GetTextureFont(const std::string &name)
|
||||
{
|
||||
std::map< std::string,RefCountedPtr<Text::TextureFont> >::iterator i = m_textureFonts.find(name);
|
||||
std::map<std::string, RefCountedPtr<Text::TextureFont>>::iterator i = m_textureFonts.find(name);
|
||||
if (i != m_textureFonts.end())
|
||||
return (*i).second;
|
||||
|
||||
|
@ -18,7 +18,7 @@ RefCountedPtr<Text::TextureFont> FontCache::GetTextureFont(const std::string &na
|
|||
|
||||
const Text::FontConfig config(name, scale[0], scale[1]);
|
||||
RefCountedPtr<Text::TextureFont> font(new Text::TextureFont(config, Gui::Screen::GetRenderer()));
|
||||
m_textureFonts.insert(std::pair< std::string,RefCountedPtr<Text::TextureFont> >(name, font));
|
||||
m_textureFonts.insert(std::pair<std::string, RefCountedPtr<Text::TextureFont>>(name, font));
|
||||
|
||||
return font;
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
#ifndef _FONTCACHE_H
|
||||
#define _FONTCACHE_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "RefCounted.h"
|
||||
#include "text/TextureFont.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class FontCache {
|
||||
public:
|
||||
|
@ -19,8 +19,7 @@ private:
|
|||
FontCache(const FontCache &);
|
||||
FontCache &operator=(const FontCache &);
|
||||
|
||||
std::map< std::string,RefCountedPtr<Text::TextureFont> > m_textureFonts;
|
||||
std::map<std::string, RefCountedPtr<Text::TextureFont>> m_textureFonts;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
145
src/Frame.cpp
145
src/Frame.cpp
|
@ -3,14 +3,14 @@
|
|||
|
||||
#include "Frame.h"
|
||||
#include "Body.h"
|
||||
#include "Game.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "Pi.h"
|
||||
#include "Sfx.h"
|
||||
#include "Space.h"
|
||||
#include "collider/collider.h"
|
||||
#include "Sfx.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "Pi.h"
|
||||
#include "Game.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "GameSaveError.h"
|
||||
#include <algorithm>
|
||||
|
||||
Frame::Frame()
|
||||
|
@ -40,8 +40,7 @@ void Frame::ToJson(Json &frameObj, Frame *f, Space *space)
|
|||
frameObj["index_for_astro_body"] = space->GetIndexForBody(f->m_astroBody);
|
||||
|
||||
Json childFrameArray = Json::array(); // Create JSON array to contain child frame data.
|
||||
for (Frame* kid : f->GetChildren())
|
||||
{
|
||||
for (Frame *kid : f->GetChildren()) {
|
||||
Json childFrameArrayEl = Json::object(); // Create JSON object to contain child frame.
|
||||
Frame::ToJson(childFrameArrayEl, kid, space);
|
||||
childFrameArray.push_back(childFrameArrayEl); // Append child frame object to array.
|
||||
|
@ -70,7 +69,7 @@ Frame *Frame::FromJson(const Json &frameObj, Space *space, Frame *parent, double
|
|||
f->m_vel = vector3d(0.0); // m_vel is set to zero.
|
||||
|
||||
if (frameObj.count("child_frames") && frameObj["child_frames"].is_array()) {
|
||||
Json childFrameArray = frameObj["child_frames"];
|
||||
Json childFrameArray = frameObj["child_frames"];
|
||||
for (unsigned int i = 0; i < childFrameArray.size(); ++i) {
|
||||
f->m_children.push_back(FromJson(childFrameArray[i], space, f, at_time));
|
||||
}
|
||||
|
@ -91,7 +90,7 @@ void Frame::PostUnserializeFixup(Frame *f, Space *space)
|
|||
{
|
||||
f->UpdateRootRelativeVars();
|
||||
f->m_astroBody = space->GetBodyByIndex(f->m_astroBodyIndex);
|
||||
for (Frame* kid : f->GetChildren())
|
||||
for (Frame *kid : f->GetChildren())
|
||||
PostUnserializeFixup(kid, space);
|
||||
}
|
||||
|
||||
|
@ -119,15 +118,14 @@ Frame::~Frame()
|
|||
{
|
||||
m_sfx.reset();
|
||||
delete m_collisionSpace;
|
||||
for (Frame* kid : m_children)
|
||||
for (Frame *kid : m_children)
|
||||
delete kid;
|
||||
}
|
||||
|
||||
void Frame::RemoveChild(Frame *f)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
const std::vector<Frame*>::iterator it
|
||||
= std::find(m_children.begin(), m_children.end(), f);
|
||||
const std::vector<Frame *>::iterator it = std::find(m_children.begin(), m_children.end(), f);
|
||||
if (it != m_children.end())
|
||||
m_children.erase(it);
|
||||
}
|
||||
|
@ -138,54 +136,68 @@ void Frame::AddStaticGeom(Geom *g) { m_collisionSpace->AddStaticGeom(g); }
|
|||
void Frame::RemoveStaticGeom(Geom *g) { m_collisionSpace->RemoveStaticGeom(g); }
|
||||
void Frame::SetPlanetGeom(double radius, Body *obj)
|
||||
{
|
||||
m_collisionSpace->SetSphere(vector3d(0,0,0), radius, static_cast<void*>(obj));
|
||||
m_collisionSpace->SetSphere(vector3d(0, 0, 0), radius, static_cast<void *>(obj));
|
||||
}
|
||||
|
||||
// doesn't consider stasis velocity
|
||||
vector3d Frame::GetVelocityRelTo(const Frame *relTo) const
|
||||
{
|
||||
if (this == relTo) return vector3d(0,0,0); // early-out to avoid unnecessary computation
|
||||
if (this == relTo) return vector3d(0, 0, 0); // early-out to avoid unnecessary computation
|
||||
vector3d diff = m_rootVel - relTo->m_rootVel;
|
||||
if (relTo->IsRotFrame()) return diff * relTo->m_rootOrient;
|
||||
else return diff;
|
||||
if (relTo->IsRotFrame())
|
||||
return diff * relTo->m_rootOrient;
|
||||
else
|
||||
return diff;
|
||||
}
|
||||
|
||||
vector3d Frame::GetPositionRelTo(const Frame *relTo) const
|
||||
{
|
||||
// early-outs for simple cases, required for accuracy in large systems
|
||||
if (this == relTo) return vector3d(0, 0, 0);
|
||||
if (GetParent() == relTo) return m_pos; // relative to parent
|
||||
if (relTo->GetParent() == this) { // relative to child
|
||||
if (!relTo->IsRotFrame()) return -relTo->m_pos;
|
||||
else return -relTo->m_pos * relTo->m_orient;
|
||||
if (GetParent() == relTo) return m_pos; // relative to parent
|
||||
if (relTo->GetParent() == this) { // relative to child
|
||||
if (!relTo->IsRotFrame())
|
||||
return -relTo->m_pos;
|
||||
else
|
||||
return -relTo->m_pos * relTo->m_orient;
|
||||
}
|
||||
if (relTo->GetParent() == GetParent()) { // common parent
|
||||
if (!relTo->IsRotFrame()) return m_pos - relTo->m_pos;
|
||||
else return (m_pos - relTo->m_pos) * relTo->m_orient;
|
||||
if (relTo->GetParent() == GetParent()) { // common parent
|
||||
if (!relTo->IsRotFrame())
|
||||
return m_pos - relTo->m_pos;
|
||||
else
|
||||
return (m_pos - relTo->m_pos) * relTo->m_orient;
|
||||
}
|
||||
|
||||
vector3d diff = m_rootPos - relTo->m_rootPos;
|
||||
if (relTo->IsRotFrame()) return diff * relTo->m_rootOrient;
|
||||
else return diff;
|
||||
if (relTo->IsRotFrame())
|
||||
return diff * relTo->m_rootOrient;
|
||||
else
|
||||
return diff;
|
||||
}
|
||||
|
||||
vector3d Frame::GetInterpPositionRelTo(const Frame *relTo) const
|
||||
{
|
||||
// early-outs for simple cases, required for accuracy in large systems
|
||||
if (this == relTo) return vector3d(0,0,0);
|
||||
if (GetParent() == relTo) return m_interpPos; // relative to parent
|
||||
if (relTo->GetParent() == this) { // relative to child
|
||||
if (!relTo->IsRotFrame()) return -relTo->m_interpPos;
|
||||
else return -relTo->m_interpPos * relTo->m_interpOrient;
|
||||
if (this == relTo) return vector3d(0, 0, 0);
|
||||
if (GetParent() == relTo) return m_interpPos; // relative to parent
|
||||
if (relTo->GetParent() == this) { // relative to child
|
||||
if (!relTo->IsRotFrame())
|
||||
return -relTo->m_interpPos;
|
||||
else
|
||||
return -relTo->m_interpPos * relTo->m_interpOrient;
|
||||
}
|
||||
if (relTo->GetParent() == GetParent()) { // common parent
|
||||
if (!relTo->IsRotFrame()) return m_interpPos - relTo->m_interpPos;
|
||||
else return (m_interpPos - relTo->m_interpPos) * relTo->m_interpOrient;
|
||||
if (relTo->GetParent() == GetParent()) { // common parent
|
||||
if (!relTo->IsRotFrame())
|
||||
return m_interpPos - relTo->m_interpPos;
|
||||
else
|
||||
return (m_interpPos - relTo->m_interpPos) * relTo->m_interpOrient;
|
||||
}
|
||||
|
||||
vector3d diff = m_rootInterpPos - relTo->m_rootInterpPos;
|
||||
if (relTo->IsRotFrame()) return diff * relTo->m_rootInterpOrient;
|
||||
else return diff;
|
||||
if (relTo->IsRotFrame())
|
||||
return diff * relTo->m_rootInterpOrient;
|
||||
else
|
||||
return diff;
|
||||
}
|
||||
|
||||
matrix3x3d Frame::GetOrientRelTo(const Frame *relTo) const
|
||||
|
@ -198,7 +210,7 @@ matrix3x3d Frame::GetInterpOrientRelTo(const Frame *relTo) const
|
|||
{
|
||||
if (this == relTo) return matrix3x3d::Identity();
|
||||
return relTo->m_rootInterpOrient.Transpose() * m_rootInterpOrient;
|
||||
/* if (IsRotFrame()) {
|
||||
/* if (IsRotFrame()) {
|
||||
if (relTo->IsRotFrame()) return m_interpOrient * relTo->m_interpOrient.Transpose();
|
||||
else return m_interpOrient;
|
||||
}
|
||||
|
@ -210,23 +222,23 @@ matrix3x3d Frame::GetInterpOrientRelTo(const Frame *relTo) const
|
|||
void Frame::UpdateInterpTransform(double alpha)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
m_interpPos = alpha*m_pos + (1.0-alpha)*m_oldPos;
|
||||
m_interpPos = alpha * m_pos + (1.0 - alpha) * m_oldPos;
|
||||
|
||||
double len = m_oldAngDisplacement * (1.0-alpha);
|
||||
if (!is_zero_exact(len)) { // very small values are normal here
|
||||
matrix3x3d rot = matrix3x3d::RotateY(len); // RotateY is backwards
|
||||
double len = m_oldAngDisplacement * (1.0 - alpha);
|
||||
if (!is_zero_exact(len)) { // very small values are normal here
|
||||
matrix3x3d rot = matrix3x3d::RotateY(len); // RotateY is backwards
|
||||
m_interpOrient = m_orient * rot;
|
||||
}
|
||||
else m_interpOrient = m_orient;
|
||||
} else
|
||||
m_interpOrient = m_orient;
|
||||
|
||||
if (!m_parent) ClearMovement();
|
||||
if (!m_parent)
|
||||
ClearMovement();
|
||||
else {
|
||||
m_rootInterpPos = m_parent->m_rootInterpOrient * m_interpPos
|
||||
+ m_parent->m_rootInterpPos;
|
||||
m_rootInterpPos = m_parent->m_rootInterpOrient * m_interpPos + m_parent->m_rootInterpPos;
|
||||
m_rootInterpOrient = m_parent->m_rootInterpOrient * m_interpOrient;
|
||||
}
|
||||
|
||||
for (Frame* kid : m_children)
|
||||
for (Frame *kid : m_children)
|
||||
kid->UpdateInterpTransform(alpha);
|
||||
}
|
||||
|
||||
|
@ -234,7 +246,8 @@ void Frame::GetFrameTransform(const Frame *fFrom, const Frame *fTo, matrix4x4d &
|
|||
{
|
||||
matrix3x3d forient = fFrom->GetOrientRelTo(fTo);
|
||||
vector3d fpos = fFrom->GetPositionRelTo(fTo);
|
||||
m = forient; m.SetTranslate(fpos);
|
||||
m = forient;
|
||||
m.SetTranslate(fpos);
|
||||
}
|
||||
|
||||
void Frame::ClearMovement()
|
||||
|
@ -255,41 +268,44 @@ void Frame::UpdateOrbitRails(double time, double timestep)
|
|||
// update frame position and velocity
|
||||
if (m_parent && m_sbody && !IsRotFrame()) {
|
||||
m_pos = m_sbody->GetOrbit().OrbitalPosAtTime(time);
|
||||
vector3d pos2 = m_sbody->GetOrbit().OrbitalPosAtTime(time+timestep);
|
||||
vector3d pos2 = m_sbody->GetOrbit().OrbitalPosAtTime(time + timestep);
|
||||
m_vel = (pos2 - m_pos) / timestep;
|
||||
}
|
||||
// temporary test thing
|
||||
else m_pos = m_pos + m_vel * timestep;
|
||||
else
|
||||
m_pos = m_pos + m_vel * timestep;
|
||||
|
||||
// update frame rotation
|
||||
double ang = fmod(m_angSpeed * time, 2.0 * M_PI);
|
||||
if (!is_zero_exact(ang)) { // frequently used with e^-10 etc
|
||||
matrix3x3d rot = matrix3x3d::RotateY(-ang); // RotateY is backwards
|
||||
m_orient = m_initialOrient * rot; // angvel always +y
|
||||
if (!is_zero_exact(ang)) { // frequently used with e^-10 etc
|
||||
matrix3x3d rot = matrix3x3d::RotateY(-ang); // RotateY is backwards
|
||||
m_orient = m_initialOrient * rot; // angvel always +y
|
||||
}
|
||||
UpdateRootRelativeVars(); // update root-relative pos/vel/orient
|
||||
UpdateRootRelativeVars(); // update root-relative pos/vel/orient
|
||||
|
||||
for (Frame* kid : m_children)
|
||||
for (Frame *kid : m_children)
|
||||
kid->UpdateOrbitRails(time, timestep);
|
||||
}
|
||||
|
||||
void Frame::SetInitialOrient(const matrix3x3d &m, double time) {
|
||||
void Frame::SetInitialOrient(const matrix3x3d &m, double time)
|
||||
{
|
||||
m_initialOrient = m;
|
||||
double ang = fmod(m_angSpeed * time, 2.0 * M_PI);
|
||||
if (!is_zero_exact(ang)) { // frequently used with e^-10 etc
|
||||
matrix3x3d rot = matrix3x3d::RotateY(-ang); // RotateY is backwards
|
||||
m_orient = m_initialOrient * rot; // angvel always +y
|
||||
if (!is_zero_exact(ang)) { // frequently used with e^-10 etc
|
||||
matrix3x3d rot = matrix3x3d::RotateY(-ang); // RotateY is backwards
|
||||
m_orient = m_initialOrient * rot; // angvel always +y
|
||||
} else {
|
||||
m_orient = m_initialOrient;
|
||||
}
|
||||
}
|
||||
|
||||
void Frame::SetOrient(const matrix3x3d &m, double time) {
|
||||
void Frame::SetOrient(const matrix3x3d &m, double time)
|
||||
{
|
||||
m_orient = m;
|
||||
double ang = fmod(m_angSpeed * time, 2.0 * M_PI);
|
||||
if (!is_zero_exact(ang)) { // frequently used with e^-10 etc
|
||||
matrix3x3d rot = matrix3x3d::RotateY(ang); // RotateY is backwards
|
||||
m_initialOrient = m_orient * rot; // angvel always +y
|
||||
if (!is_zero_exact(ang)) { // frequently used with e^-10 etc
|
||||
matrix3x3d rot = matrix3x3d::RotateY(ang); // RotateY is backwards
|
||||
m_initialOrient = m_orient * rot; // angvel always +y
|
||||
} else {
|
||||
m_initialOrient = m_orient;
|
||||
}
|
||||
|
@ -299,10 +315,9 @@ void Frame::UpdateRootRelativeVars()
|
|||
{
|
||||
// update pos & vel relative to parent frame
|
||||
if (!m_parent) {
|
||||
m_rootPos = m_rootVel = vector3d(0,0,0);
|
||||
m_rootPos = m_rootVel = vector3d(0, 0, 0);
|
||||
m_rootOrient = matrix3x3d::Identity();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
m_rootPos = m_parent->m_rootOrient * m_pos + m_parent->m_rootPos;
|
||||
m_rootVel = m_parent->m_rootOrient * m_vel + m_parent->m_rootVel;
|
||||
m_rootOrient = m_parent->m_rootOrient * m_orient;
|
||||
|
|
40
src/Frame.h
40
src/Frame.h
|
@ -4,11 +4,11 @@
|
|||
#ifndef _FRAME_H
|
||||
#define _FRAME_H
|
||||
|
||||
#include "libs.h"
|
||||
#include "IterationProxy.h"
|
||||
#include "JsonFwd.h"
|
||||
#include <string>
|
||||
#include "libs.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
class Body;
|
||||
class CollisionSpace;
|
||||
|
@ -21,7 +21,9 @@ class Space;
|
|||
|
||||
class Frame {
|
||||
public:
|
||||
enum { FLAG_DEFAULT=(0), FLAG_ROTATING=(1<<1), FLAG_HAS_ROT=(1<<2) };
|
||||
enum { FLAG_DEFAULT = (0),
|
||||
FLAG_ROTATING = (1 << 1),
|
||||
FLAG_HAS_ROT = (1 << 2) };
|
||||
|
||||
Frame();
|
||||
Frame(Frame *parent, const char *label);
|
||||
|
@ -54,7 +56,11 @@ public:
|
|||
const Frame *GetRotFrame() const { return HasRotFrame() ? m_children.front() : this; }
|
||||
Frame *GetRotFrame() { return HasRotFrame() ? m_children.front() : this; }
|
||||
|
||||
void SetBodies(SystemBody *s, Body *b) { m_sbody = s; m_astroBody = b; }
|
||||
void SetBodies(SystemBody *s, Body *b)
|
||||
{
|
||||
m_sbody = s;
|
||||
m_astroBody = b;
|
||||
}
|
||||
SystemBody *GetSystemBody() const { return m_sbody; }
|
||||
Body *GetBody() const { return m_astroBody; }
|
||||
|
||||
|
@ -62,8 +68,8 @@ public:
|
|||
void RemoveChild(Frame *f);
|
||||
bool HasChildren() const { return !m_children.empty(); }
|
||||
unsigned GetNumChildren() const { return static_cast<Uint32>(m_children.size()); }
|
||||
IterationProxy<std::vector<Frame*> > GetChildren() { return MakeIterationProxy(m_children); }
|
||||
const IterationProxy<const std::vector<Frame*> > GetChildren() const { return MakeIterationProxy(m_children); }
|
||||
IterationProxy<std::vector<Frame *>> GetChildren() { return MakeIterationProxy(m_children); }
|
||||
const IterationProxy<const std::vector<Frame *>> GetChildren() const { return MakeIterationProxy(m_children); }
|
||||
|
||||
void AddGeom(Geom *);
|
||||
void RemoveGeom(Geom *);
|
||||
|
@ -78,7 +84,7 @@ public:
|
|||
|
||||
// For an object in a rotating frame, relative to non-rotating frames it
|
||||
// must attain this velocity within rotating frame to be stationary.
|
||||
vector3d GetStasisVelocity(const vector3d &pos) const { return -vector3d(0,m_angSpeed,0).Cross(pos); }
|
||||
vector3d GetStasisVelocity(const vector3d &pos) const { return -vector3d(0, m_angSpeed, 0).Cross(pos); }
|
||||
|
||||
vector3d GetPositionRelTo(const Frame *relTo) const;
|
||||
vector3d GetVelocityRelTo(const Frame *relTo) const;
|
||||
|
@ -91,16 +97,16 @@ public:
|
|||
|
||||
static void GetFrameTransform(const Frame *fFrom, const Frame *fTo, matrix4x4d &m);
|
||||
|
||||
std::unique_ptr<SfxManager> m_sfx; // the last survivor. actually m_children is pretty grim too.
|
||||
std::unique_ptr<SfxManager> m_sfx; // the last survivor. actually m_children is pretty grim too.
|
||||
|
||||
private:
|
||||
void Init(Frame *parent, const char *label, unsigned int flags);
|
||||
void UpdateRootRelativeVars();
|
||||
|
||||
Frame *m_parent; // if parent is null then frame position is absolute
|
||||
std::vector<Frame*> m_children; // child frames, first may be rotating
|
||||
SystemBody *m_sbody; // points to SBodies in Pi::current_system
|
||||
Body *m_astroBody; // if frame contains a star or planet or something
|
||||
Frame *m_parent; // if parent is null then frame position is absolute
|
||||
std::vector<Frame *> m_children; // child frames, first may be rotating
|
||||
SystemBody *m_sbody; // points to SBodies in Pi::current_system
|
||||
Body *m_astroBody; // if frame contains a star or planet or something
|
||||
|
||||
vector3d m_pos;
|
||||
vector3d m_oldPos;
|
||||
|
@ -109,7 +115,7 @@ private:
|
|||
matrix3x3d m_orient;
|
||||
matrix3x3d m_interpOrient;
|
||||
vector3d m_vel; // note we don't use this to move frame. rather,
|
||||
// orbital rails determine velocity.
|
||||
// orbital rails determine velocity.
|
||||
double m_angSpeed; // this however *is* directly applied (for rotating frames)
|
||||
double m_oldAngDisplacement;
|
||||
std::string m_label;
|
||||
|
@ -117,11 +123,11 @@ private:
|
|||
int m_flags;
|
||||
CollisionSpace *m_collisionSpace;
|
||||
|
||||
vector3d m_rootVel; // velocity, position and orient relative to root frame
|
||||
vector3d m_rootPos; // updated by UpdateOrbitRails
|
||||
vector3d m_rootVel; // velocity, position and orient relative to root frame
|
||||
vector3d m_rootPos; // updated by UpdateOrbitRails
|
||||
matrix3x3d m_rootOrient;
|
||||
vector3d m_rootInterpPos; // interp position and orient relative to root frame
|
||||
matrix3x3d m_rootInterpOrient; // updated by UpdateInterpTransform
|
||||
vector3d m_rootInterpPos; // interp position and orient relative to root frame
|
||||
matrix3x3d m_rootInterpOrient; // updated by UpdateInterpTransform
|
||||
|
||||
int m_astroBodyIndex; // deserialisation
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "GZipFormat.h"
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
extern "C" {
|
||||
#include "miniz/miniz.h"
|
||||
|
@ -9,17 +9,17 @@ extern "C" {
|
|||
|
||||
namespace {
|
||||
enum GZipFlags {
|
||||
FLAG_TEXT = 1,
|
||||
FLAG_HCRC = 2, // Header CRC included
|
||||
FLAG_EXTRA = 4,
|
||||
FLAG_NAME = 8,
|
||||
FLAG_TEXT = 1,
|
||||
FLAG_HCRC = 2, // Header CRC included
|
||||
FLAG_EXTRA = 4,
|
||||
FLAG_NAME = 8,
|
||||
FLAG_COMMENT = 16,
|
||||
|
||||
FLAGS_ALL = (FLAG_TEXT | FLAG_HCRC | FLAG_EXTRA | FLAG_NAME | FLAG_COMMENT),
|
||||
FLAGS_ALL = (FLAG_TEXT | FLAG_HCRC | FLAG_EXTRA | FLAG_NAME | FLAG_COMMENT),
|
||||
};
|
||||
|
||||
enum GZipCompressionModes {
|
||||
CM_DEFLATE = 8, // The only one defined in the RFC (and the one we need).
|
||||
CM_DEFLATE = 8, // The only one defined in the RFC (and the one we need).
|
||||
};
|
||||
|
||||
enum GZipHeaderSizes {
|
||||
|
@ -28,36 +28,44 @@ namespace {
|
|||
};
|
||||
|
||||
// Streaming output function for tdefl_compress_mem_to_output.
|
||||
static mz_bool PutBytesToString(const void *buf, int len, void *user) {
|
||||
std::string *out = static_cast<std::string*>(user);
|
||||
out->append(static_cast<const char*>(buf), len);
|
||||
static mz_bool PutBytesToString(const void *buf, int len, void *user)
|
||||
{
|
||||
std::string *out = static_cast<std::string *>(user);
|
||||
out->append(static_cast<const char *>(buf), len);
|
||||
return MZ_TRUE;
|
||||
}
|
||||
|
||||
static uint32_t ReadLE32(const unsigned char *data) {
|
||||
return
|
||||
(uint32_t(data[0]) << 0) |
|
||||
(uint32_t(data[1]) << 8) |
|
||||
static uint32_t ReadLE32(const unsigned char *data)
|
||||
{
|
||||
return (uint32_t(data[0]) << 0) |
|
||||
(uint32_t(data[1]) << 8) |
|
||||
(uint32_t(data[2]) << 16) |
|
||||
(uint32_t(data[3]) << 24);
|
||||
}
|
||||
|
||||
static void WriteLE32(unsigned char *out, uint32_t value) {
|
||||
out[0] = (value >> 0) & 0xffu;
|
||||
out[1] = (value >> 8) & 0xffu;
|
||||
static void WriteLE32(unsigned char *out, uint32_t value)
|
||||
{
|
||||
out[0] = (value >> 0) & 0xffu;
|
||||
out[1] = (value >> 8) & 0xffu;
|
||||
out[2] = (value >> 16) & 0xffu;
|
||||
out[3] = (value >> 24) & 0xffu;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool gzip::IsGZipFormat(const unsigned char *data, size_t length) {
|
||||
bool gzip::IsGZipFormat(const unsigned char *data, size_t length)
|
||||
{
|
||||
// (This assumes it's possible to provide 0 bytes of compressed data, which is probably not true).
|
||||
if (length < BASE_HEADER_SIZE + BASE_FOOTER_SIZE) { return false; }
|
||||
if (data[0] != 0x1fu || data[1] != 0x8bu) { return false; }
|
||||
if (length < BASE_HEADER_SIZE + BASE_FOOTER_SIZE) {
|
||||
return false;
|
||||
}
|
||||
if (data[0] != 0x1fu || data[1] != 0x8bu) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string gzip::DecompressDeflateOrGZip(const unsigned char *data, size_t length) {
|
||||
std::string gzip::DecompressDeflateOrGZip(const unsigned char *data, size_t length)
|
||||
{
|
||||
assert(data != nullptr);
|
||||
if (gzip::IsGZipFormat(data, length)) {
|
||||
return gzip::DecompressGZip(data, length);
|
||||
|
@ -67,7 +75,8 @@ std::string gzip::DecompressDeflateOrGZip(const unsigned char *data, size_t leng
|
|||
}
|
||||
}
|
||||
|
||||
std::string gzip::DecompressGZip(const unsigned char *data, size_t length) {
|
||||
std::string gzip::DecompressGZip(const unsigned char *data, size_t length)
|
||||
{
|
||||
assert(data != nullptr);
|
||||
assert(length >= BASE_HEADER_SIZE + BASE_FOOTER_SIZE);
|
||||
|
||||
|
@ -75,48 +84,64 @@ std::string gzip::DecompressGZip(const unsigned char *data, size_t length) {
|
|||
const unsigned char *at_footer = data + (length - BASE_FOOTER_SIZE);
|
||||
|
||||
// We only know about DEFLATE.
|
||||
if (at_header[2] != CM_DEFLATE) { throw gzip::DecompressionFailedException(); }
|
||||
if (at_header[2] != CM_DEFLATE) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
|
||||
int gzip_flags = at_header[3];
|
||||
// There are not supposed to be any unknown flags!
|
||||
if (gzip_flags & ~FLAGS_ALL) { throw gzip::DecompressionFailedException(); }
|
||||
if (gzip_flags & ~FLAGS_ALL) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
|
||||
const unsigned char *at_data = at_header + BASE_HEADER_SIZE;
|
||||
assert(at_data <= at_footer);
|
||||
size_t data_length = length - BASE_HEADER_SIZE + BASE_FOOTER_SIZE;
|
||||
|
||||
if (gzip_flags & FLAG_EXTRA) {
|
||||
if (data_length < 2) { throw gzip::DecompressionFailedException(); }
|
||||
if (data_length < 2) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
size_t xlen = uint8_t(at_data[0]) | (uint8_t(at_data[1]) << 8);
|
||||
xlen += 2; // Add the two bytes for the length itself.
|
||||
if (data_length < xlen) { throw gzip::DecompressionFailedException(); }
|
||||
xlen += 2; // Add the two bytes for the length itself.
|
||||
if (data_length < xlen) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
at_data += xlen;
|
||||
assert(at_data <= at_footer);
|
||||
data_length = at_footer - at_data;
|
||||
}
|
||||
|
||||
if (gzip_flags & FLAG_NAME) {
|
||||
const unsigned char *name_end = static_cast<const unsigned char*>(std::memchr(at_data, 0, data_length));
|
||||
if (!name_end) { throw gzip::DecompressionFailedException(); }
|
||||
at_data = name_end + 1; // +1 to skip the null terminator.
|
||||
const unsigned char *name_end = static_cast<const unsigned char *>(std::memchr(at_data, 0, data_length));
|
||||
if (!name_end) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
at_data = name_end + 1; // +1 to skip the null terminator.
|
||||
assert(at_data <= at_footer);
|
||||
data_length = at_footer - at_data;
|
||||
}
|
||||
|
||||
if (gzip_flags & FLAG_COMMENT) {
|
||||
const unsigned char *comment_end = static_cast<const unsigned char*>(std::memchr(at_data, 0, data_length));
|
||||
if (!comment_end) { throw gzip::DecompressionFailedException(); }
|
||||
at_data = comment_end + 1; // +1 to skip the null terminator.
|
||||
const unsigned char *comment_end = static_cast<const unsigned char *>(std::memchr(at_data, 0, data_length));
|
||||
if (!comment_end) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
at_data = comment_end + 1; // +1 to skip the null terminator.
|
||||
assert(at_data <= at_footer);
|
||||
data_length = at_footer - at_data;
|
||||
}
|
||||
|
||||
if (gzip_flags & FLAG_HCRC) {
|
||||
if (data_length < 2) { throw gzip::DecompressionFailedException(); }
|
||||
if (data_length < 2) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
uint32_t true_crc = mz_crc32(MZ_CRC32_INIT, at_header, (at_data - at_header));
|
||||
true_crc &= 0xffffu; // Only care about the bottom 16 bits.
|
||||
true_crc &= 0xffffu; // Only care about the bottom 16 bits.
|
||||
uint32_t file_crc = uint8_t(at_data[0]) | (uint8_t(at_data[1]) << 8);
|
||||
if (true_crc != file_crc) { throw gzip::DecompressionFailedException(); }
|
||||
if (true_crc != file_crc) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
at_data += 2;
|
||||
data_length -= 2;
|
||||
assert(at_data <= at_footer);
|
||||
|
@ -125,57 +150,67 @@ std::string gzip::DecompressGZip(const unsigned char *data, size_t length) {
|
|||
std::string out;
|
||||
|
||||
assert(at_data + data_length == at_footer);
|
||||
bool inflate_success = tinfl_decompress_mem_to_callback(static_cast<const void*>(at_data), &data_length, &PutBytesToString, static_cast<void*>(&out), 0);
|
||||
if (!inflate_success) { throw gzip::DecompressionFailedException(); }
|
||||
bool inflate_success = tinfl_decompress_mem_to_callback(static_cast<const void *>(at_data), &data_length, &PutBytesToString, static_cast<void *>(&out), 0);
|
||||
if (!inflate_success) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
|
||||
uint32_t true_crc = mz_crc32(MZ_CRC32_INIT, reinterpret_cast<const mz_uint8*>(out.data()), out.size());
|
||||
uint32_t true_crc = mz_crc32(MZ_CRC32_INIT, reinterpret_cast<const mz_uint8 *>(out.data()), out.size());
|
||||
uint32_t crc_from_file = ReadLE32(at_footer + 0);
|
||||
uint32_t size_from_header = ReadLE32(at_footer + 4);
|
||||
if (true_crc != crc_from_file) { throw gzip::DecompressionFailedException(); }
|
||||
if (size_from_header != static_cast<uint32_t>(out.size())) { throw gzip::DecompressionFailedException(); }
|
||||
if (true_crc != crc_from_file) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
if (size_from_header != static_cast<uint32_t>(out.size())) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string gzip::DecompressRawDeflate(const unsigned char *data, size_t length) {
|
||||
std::string gzip::DecompressRawDeflate(const unsigned char *data, size_t length)
|
||||
{
|
||||
assert(data != nullptr);
|
||||
std::string out;
|
||||
size_t in_size = length;
|
||||
bool success = tinfl_decompress_mem_to_callback(static_cast<const void*>(data), &in_size, &PutBytesToString, static_cast<void*>(&out), 0);
|
||||
if (!success) { throw gzip::DecompressionFailedException(); }
|
||||
bool success = tinfl_decompress_mem_to_callback(static_cast<const void *>(data), &in_size, &PutBytesToString, static_cast<void *>(&out), 0);
|
||||
if (!success) {
|
||||
throw gzip::DecompressionFailedException();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string gzip::CompressGZip(const std::string &data, const std::string &inner_file_name) {
|
||||
std::string gzip::CompressGZip(const std::string &data, const std::string &inner_file_name)
|
||||
{
|
||||
std::string out;
|
||||
|
||||
// The base GZip header.
|
||||
const unsigned char header_bytes[10] = { 31, 139, 8, FLAG_HCRC | FLAG_NAME, 0, 0, 0, 0, 0, 255 };
|
||||
out.append(reinterpret_cast<const char*>(header_bytes), sizeof(header_bytes));
|
||||
out.append(reinterpret_cast<const char *>(header_bytes), sizeof(header_bytes));
|
||||
|
||||
// Add inner file name, *including* null terminator (c_str() ensures that the data is null terminated).
|
||||
out.append(inner_file_name.c_str(), inner_file_name.size() + 1);
|
||||
|
||||
// Add 16-bit header-CRC.
|
||||
uint32_t header_crc = mz_crc32(MZ_CRC32_INIT, reinterpret_cast<const mz_uint8*>(out.data()), out.size());
|
||||
uint32_t header_crc = mz_crc32(MZ_CRC32_INIT, reinterpret_cast<const mz_uint8 *>(out.data()), out.size());
|
||||
const unsigned char crc_buf[2] = {
|
||||
static_cast<unsigned char>((header_crc >> 0) & 0xffu),
|
||||
static_cast<unsigned char>((header_crc >> 8) & 0xffu),
|
||||
};
|
||||
out.append(reinterpret_cast<const char*>(crc_buf), sizeof(crc_buf));
|
||||
out.append(reinterpret_cast<const char *>(crc_buf), sizeof(crc_buf));
|
||||
|
||||
bool success = tdefl_compress_mem_to_output(data.data(), data.size(), &PutBytesToString, static_cast<void*>(&out), TDEFL_DEFAULT_MAX_PROBES);
|
||||
bool success = tdefl_compress_mem_to_output(data.data(), data.size(), &PutBytesToString, static_cast<void *>(&out), TDEFL_DEFAULT_MAX_PROBES);
|
||||
if (!success) {
|
||||
throw gzip::CompressionFailedException();
|
||||
}
|
||||
|
||||
unsigned char footer_bytes[8];
|
||||
uint32_t data_crc = mz_crc32(MZ_CRC32_INIT, reinterpret_cast<const mz_uint8*>(data.data()), data.size());
|
||||
uint32_t data_crc = mz_crc32(MZ_CRC32_INIT, reinterpret_cast<const mz_uint8 *>(data.data()), data.size());
|
||||
WriteLE32(footer_bytes + 0, data_crc);
|
||||
// GZip specifies that size is written little-endian, modulo 2^32
|
||||
// (ie, if size is really > 2^32 we just chop off the high bits).
|
||||
WriteLE32(footer_bytes + 4, data.size());
|
||||
out.append(reinterpret_cast<const char*>(footer_bytes), sizeof(footer_bytes));
|
||||
out.append(reinterpret_cast<const char *>(footer_bytes), sizeof(footer_bytes));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,6 @@ namespace gzip {
|
|||
// If compression fails it throws an exception.
|
||||
// Parameter 'inner_file_name' is the name written in the GZip header as the file name of the compressed block.
|
||||
std::string CompressGZip(const std::string &data, const std::string &inner_file_name);
|
||||
}
|
||||
} // namespace gzip
|
||||
|
||||
#endif
|
||||
|
|
256
src/Game.cpp
256
src/Game.cpp
|
@ -2,33 +2,33 @@
|
|||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "Game.h"
|
||||
#include "Factions.h"
|
||||
#include "Space.h"
|
||||
#include "Player.h"
|
||||
#include "Body.h"
|
||||
#include "SpaceStation.h"
|
||||
#include "HyperspaceCloud.h"
|
||||
#include "Pi.h"
|
||||
#include "ShipCpanel.h"
|
||||
#include "Sfx.h"
|
||||
#include "MathUtil.h"
|
||||
#include "SectorView.h"
|
||||
#include "WorldView.h"
|
||||
#include "DeathView.h"
|
||||
#include "SystemView.h"
|
||||
#include "SystemInfoView.h"
|
||||
#include "UIView.h"
|
||||
#include "LuaEvent.h"
|
||||
#include "LuaRef.h"
|
||||
#include "ObjectViewerView.h"
|
||||
#include "Factions.h"
|
||||
#include "FileSystem.h"
|
||||
#include "GZipFormat.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "HyperspaceCloud.h"
|
||||
#include "LuaEvent.h"
|
||||
#include "LuaRef.h"
|
||||
#include "MathUtil.h"
|
||||
#include "ObjectViewerView.h"
|
||||
#include "Pi.h"
|
||||
#include "Player.h"
|
||||
#include "SectorView.h"
|
||||
#include "Sfx.h"
|
||||
#include "ShipCpanel.h"
|
||||
#include "Space.h"
|
||||
#include "SpaceStation.h"
|
||||
#include "SystemInfoView.h"
|
||||
#include "SystemView.h"
|
||||
#include "UIView.h"
|
||||
#include "WorldView.h"
|
||||
#include "galaxy/GalaxyGenerator.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "ui/Context.h"
|
||||
#include "galaxy/GalaxyGenerator.h"
|
||||
#include "GameSaveError.h"
|
||||
|
||||
static const int s_saveVersion = 85;
|
||||
static const int s_saveVersion = 85;
|
||||
|
||||
Game::Game(const SystemPath &path, double time) :
|
||||
m_galaxy(GalaxyGenerator::Create()),
|
||||
|
@ -77,11 +77,11 @@ Game::Game(const SystemPath &path, double time) :
|
|||
m_player->SetFrame(b->GetFrame());
|
||||
|
||||
if (b->GetType() == Object::SPACESTATION) {
|
||||
m_player->SetDockedWith(static_cast<SpaceStation*>(b), 0);
|
||||
m_player->SetDockedWith(static_cast<SpaceStation *>(b), 0);
|
||||
} else {
|
||||
const SystemBody *sbody = b->GetSystemBody();
|
||||
m_player->SetPosition(vector3d(0, 1.5*sbody->GetRadius(), 0));
|
||||
m_player->SetVelocity(vector3d(0,0,0));
|
||||
m_player->SetPosition(vector3d(0, 1.5 * sbody->GetRadius(), 0));
|
||||
m_player->SetVelocity(vector3d(0, 0, 0));
|
||||
}
|
||||
|
||||
CreateViews();
|
||||
|
@ -119,9 +119,9 @@ Game::~Game()
|
|||
}
|
||||
|
||||
Game::Game(const Json &jsonObj) :
|
||||
m_timeAccel(TIMEACCEL_PAUSED),
|
||||
m_requestedTimeAccel(TIMEACCEL_PAUSED),
|
||||
m_forceTimeAccel(false)
|
||||
m_timeAccel(TIMEACCEL_PAUSED),
|
||||
m_requestedTimeAccel(TIMEACCEL_PAUSED),
|
||||
m_forceTimeAccel(false)
|
||||
{
|
||||
try {
|
||||
int version = jsonObj["version"];
|
||||
|
@ -154,14 +154,14 @@ m_forceTimeAccel(false)
|
|||
m_space.reset(new Space(this, m_galaxy, jsonObj, m_time));
|
||||
|
||||
unsigned int player = jsonObj["player"];
|
||||
m_player.reset(static_cast<Player*>(m_space->GetBodyByIndex(player)));
|
||||
m_player.reset(static_cast<Player *>(m_space->GetBodyByIndex(player)));
|
||||
|
||||
assert(!m_player->IsDead()); // Pioneer does not support necromancy
|
||||
|
||||
// hyperspace clouds being brought over from the previous system
|
||||
Json hyperspaceCloudArray = jsonObj["hyperspace_clouds"].get<Json::array_t>();
|
||||
for (Uint32 i = 0; i < hyperspaceCloudArray.size(); i++) {
|
||||
m_hyperspaceClouds.push_back(static_cast<HyperspaceCloud*>(Body::FromJson(hyperspaceCloudArray[i], 0)));
|
||||
m_hyperspaceClouds.push_back(static_cast<HyperspaceCloud *>(Body::FromJson(hyperspaceCloudArray[i], 0)));
|
||||
}
|
||||
} catch (Json::type_error &) {
|
||||
throw SavedGameCorruptException();
|
||||
|
@ -205,8 +205,7 @@ void Game::ToJson(Json &jsonObj)
|
|||
|
||||
// hyperspace clouds being brought over from the previous system
|
||||
Json hyperspaceCloudArray = Json::array(); // Create JSON array to contain hyperspace cloud data.
|
||||
for (std::list<HyperspaceCloud*>::const_iterator i = m_hyperspaceClouds.begin(); i != m_hyperspaceClouds.end(); ++i)
|
||||
{
|
||||
for (std::list<HyperspaceCloud *>::const_iterator i = m_hyperspaceClouds.begin(); i != m_hyperspaceClouds.end(); ++i) {
|
||||
Json hyperspaceCloudArrayEl = Json::object(); // Create JSON object to contain hyperspace cloud.
|
||||
(*i)->ToJson(hyperspaceCloudArrayEl, m_space.get());
|
||||
hyperspaceCloudArray.push_back(hyperspaceCloudArrayEl); // Append hyperspace cloud object to array.
|
||||
|
@ -268,7 +267,7 @@ void Game::ToJson(Json &jsonObj)
|
|||
void Game::TimeStep(float step)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
m_time += step; // otherwise planets lag time accel changes by a frame
|
||||
m_time += step; // otherwise planets lag time accel changes by a frame
|
||||
if (m_state == STATE_HYPERSPACE && Pi::game->GetTime() >= m_hyperspaceEndTime)
|
||||
m_time = m_hyperspaceEndTime;
|
||||
|
||||
|
@ -283,8 +282,7 @@ void Game::TimeStep(float step)
|
|||
SwitchToNormalSpace();
|
||||
m_player->EnterSystem();
|
||||
RequestTimeAccel(TIMEACCEL_1X);
|
||||
}
|
||||
else
|
||||
} else
|
||||
m_hyperspaceProgress += step;
|
||||
return;
|
||||
}
|
||||
|
@ -315,8 +313,8 @@ bool Game::UpdateTimeAccel()
|
|||
|
||||
// force down to timeaccel 1 during the docking sequence or when just initiating hyperspace
|
||||
else if (m_player->GetFlightState() == Ship::DOCKING ||
|
||||
m_player->GetFlightState() == Ship::JUMPING ||
|
||||
m_player->GetFlightState() == Ship::UNDOCKING) {
|
||||
m_player->GetFlightState() == Ship::JUMPING ||
|
||||
m_player->GetFlightState() == Ship::UNDOCKING) {
|
||||
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_10X);
|
||||
RequestTimeAccel(newTimeAccel);
|
||||
}
|
||||
|
@ -330,13 +328,13 @@ bool Game::UpdateTimeAccel()
|
|||
|
||||
if (!m_forceTimeAccel) {
|
||||
|
||||
// if not forced - limit timeaccel to 10x when other ships are close
|
||||
// if not forced - limit timeaccel to 10x when other ships are close
|
||||
if (m_player->GetAlertState() == Ship::ALERT_SHIP_NEARBY)
|
||||
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_10X);
|
||||
|
||||
// if not forced - check if we aren't too near to objects for timeaccel
|
||||
// if not forced - check if we aren't too near to objects for timeaccel
|
||||
else {
|
||||
for (const Body* b : m_space->GetBodies()) {
|
||||
for (const Body *b : m_space->GetBodies()) {
|
||||
if (b == m_player.get()) continue;
|
||||
if (b->IsType(Object::HYPERSPACECLOUD)) continue;
|
||||
|
||||
|
@ -346,28 +344,28 @@ bool Game::UpdateTimeAccel()
|
|||
|
||||
if (dist < 1000.0) {
|
||||
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_1X);
|
||||
} else if (dist < std::min(rad+0.0001*AU, rad*1.1)) {
|
||||
} else if (dist < std::min(rad + 0.0001 * AU, rad * 1.1)) {
|
||||
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_10X);
|
||||
} else if (dist < std::min(rad+0.001*AU, rad*5.0)) {
|
||||
} else if (dist < std::min(rad + 0.001 * AU, rad * 5.0)) {
|
||||
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_100X);
|
||||
} else if (dist < std::min(rad+0.01*AU,rad*10.0)) {
|
||||
} else if (dist < std::min(rad + 0.01 * AU, rad * 10.0)) {
|
||||
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_1000X);
|
||||
} else if (dist < std::min(rad+0.1*AU, rad*1000.0)) {
|
||||
} else if (dist < std::min(rad + 0.1 * AU, rad * 1000.0)) {
|
||||
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_10000X);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_player->AIIsActive()) { // don't do this when autopilot is active
|
||||
if (!m_player->AIIsActive()) { // don't do this when autopilot is active
|
||||
const double locVel = m_player->GetAngVelocity().Length();
|
||||
const double strictness = 20.0;
|
||||
if(locVel > strictness / Game::s_timeAccelRates[TIMEACCEL_10X]) {
|
||||
if (locVel > strictness / Game::s_timeAccelRates[TIMEACCEL_10X]) {
|
||||
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_1X);
|
||||
} else if(locVel > strictness / Game::s_timeAccelRates[TIMEACCEL_100X]) {
|
||||
} else if (locVel > strictness / Game::s_timeAccelRates[TIMEACCEL_100X]) {
|
||||
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_10X);
|
||||
} else if(locVel > strictness / Game::s_timeAccelRates[TIMEACCEL_1000X]) {
|
||||
} else if (locVel > strictness / Game::s_timeAccelRates[TIMEACCEL_1000X]) {
|
||||
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_100X);
|
||||
} else if(locVel > strictness / Game::s_timeAccelRates[TIMEACCEL_10000X]) {
|
||||
} else if (locVel > strictness / Game::s_timeAccelRates[TIMEACCEL_10000X]) {
|
||||
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_1000X);
|
||||
}
|
||||
}
|
||||
|
@ -396,7 +394,7 @@ double Game::GetHyperspaceArrivalProbability() const
|
|||
return scale * (1.0 - exp(-fudge * progress));
|
||||
}
|
||||
|
||||
void Game::RemoveHyperspaceCloud(HyperspaceCloud* cloud)
|
||||
void Game::RemoveHyperspaceCloud(HyperspaceCloud *cloud)
|
||||
{
|
||||
m_hyperspaceClouds.remove(cloud);
|
||||
}
|
||||
|
@ -406,17 +404,17 @@ void Game::SwitchToHyperspace()
|
|||
PROFILE_SCOPED()
|
||||
// remember where we came from so we can properly place the player on exit
|
||||
m_hyperspaceSource = m_space->GetStarSystem()->GetPath();
|
||||
m_hyperspaceDest = m_player->GetHyperspaceDest();
|
||||
m_hyperspaceDest = m_player->GetHyperspaceDest();
|
||||
|
||||
// find all the departure clouds, convert them to arrival clouds and store
|
||||
// them for the next system
|
||||
m_hyperspaceClouds.clear();
|
||||
for (Body* b : m_space->GetBodies()) {
|
||||
for (Body *b : m_space->GetBodies()) {
|
||||
|
||||
if (!b->IsType(Object::HYPERSPACECLOUD)) continue;
|
||||
|
||||
// only want departure clouds with ships in them
|
||||
HyperspaceCloud *cloud = static_cast<HyperspaceCloud*>(b);
|
||||
HyperspaceCloud *cloud = static_cast<HyperspaceCloud *>(b);
|
||||
if (cloud->IsArrival() || cloud->GetShip() == 0)
|
||||
continue;
|
||||
|
||||
|
@ -449,7 +447,7 @@ void Game::SwitchToHyperspace()
|
|||
// create hyperspace :)
|
||||
m_space.reset(new Space(this, m_galaxy, m_space.get()));
|
||||
|
||||
m_space->GetBackground()->SetDrawFlags( Background::Container::DRAW_STARS );
|
||||
m_space->GetBackground()->SetDrawFlags(Background::Container::DRAW_STARS);
|
||||
|
||||
// Reset planner
|
||||
Pi::planner->ResetStartTime();
|
||||
|
@ -461,8 +459,8 @@ void Game::SwitchToHyperspace()
|
|||
|
||||
// put player at the origin. kind of unnecessary since it won't be moving
|
||||
// but at least it gives some consistency
|
||||
m_player->SetPosition(vector3d(0,0,0));
|
||||
m_player->SetVelocity(vector3d(0,0,0));
|
||||
m_player->SetPosition(vector3d(0, 0, 0));
|
||||
m_player->SetVelocity(vector3d(0, 0, 0));
|
||||
m_player->SetOrient(matrix3x3d::Identity());
|
||||
|
||||
// animation and end time counters
|
||||
|
@ -490,7 +488,7 @@ void Game::SwitchToNormalSpace()
|
|||
m_space->AddBody(m_player.get());
|
||||
|
||||
// place it
|
||||
vector3d pos,vel;
|
||||
vector3d pos, vel;
|
||||
m_space->GetHyperspaceExitParams(m_hyperspaceSource, m_hyperspaceDest, pos, vel);
|
||||
m_player->SetPosition(pos);
|
||||
m_player->SetVelocity(vel);
|
||||
|
@ -500,7 +498,7 @@ void Game::SwitchToNormalSpace()
|
|||
vector3d oz = -vel.Normalized();
|
||||
vector3d ox = MathUtil::OrthogonalDirection(vel);
|
||||
vector3d oy = oz.Cross(ox).Normalized();
|
||||
m_player->SetOrient(matrix3x3d::FromVectors(ox,oy,oz));
|
||||
m_player->SetOrient(matrix3x3d::FromVectors(ox, oy, oz));
|
||||
}
|
||||
|
||||
// place the exit cloud
|
||||
|
@ -509,7 +507,7 @@ void Game::SwitchToNormalSpace()
|
|||
cloud->SetPosition(m_player->GetPosition());
|
||||
m_space->AddBody(cloud);
|
||||
|
||||
for (std::list<HyperspaceCloud*>::iterator i = m_hyperspaceClouds.begin(); i != m_hyperspaceClouds.end(); ++i) {
|
||||
for (std::list<HyperspaceCloud *>::iterator i = m_hyperspaceClouds.begin(); i != m_hyperspaceClouds.end(); ++i) {
|
||||
cloud = *i;
|
||||
|
||||
cloud->SetFrame(m_space->GetRootFrame());
|
||||
|
@ -522,7 +520,7 @@ void Game::SwitchToNormalSpace()
|
|||
Ship *ship = cloud->EvictShip();
|
||||
|
||||
ship->SetFrame(m_space->GetRootFrame());
|
||||
ship->SetVelocity(vector3d(0,0,-100.0));
|
||||
ship->SetVelocity(vector3d(0, 0, -100.0));
|
||||
ship->SetOrient(matrix3x3d::Identity());
|
||||
ship->SetFlightState(Ship::FLYING);
|
||||
|
||||
|
@ -575,7 +573,7 @@ void Game::SwitchToNormalSpace()
|
|||
SystemBody *sbody = m_space->GetStarSystem()->GetBodyByPath(&sdest);
|
||||
if (sbody->GetType() == SystemBody::TYPE_STARPORT_ORBITAL) {
|
||||
ship->SetFrame(target_body->GetFrame());
|
||||
ship->SetPosition(MathUtil::RandomPointOnSphere(1000.0)*1000.0); // somewhere 1000km out
|
||||
ship->SetPosition(MathUtil::RandomPointOnSphere(1000.0) * 1000.0); // somewhere 1000km out
|
||||
}
|
||||
|
||||
else {
|
||||
|
@ -585,7 +583,7 @@ void Game::SwitchToNormalSpace()
|
|||
target_body = m_space->FindBodyForPath(&path);
|
||||
}
|
||||
|
||||
double sdist = sbody->GetRadius()*2.0;
|
||||
double sdist = sbody->GetRadius() * 2.0;
|
||||
|
||||
ship->SetFrame(target_body->GetFrame());
|
||||
ship->SetPosition(MathUtil::RandomPointOnSphere(sdist));
|
||||
|
@ -600,46 +598,46 @@ void Game::SwitchToNormalSpace()
|
|||
}
|
||||
m_hyperspaceClouds.clear();
|
||||
|
||||
m_space->GetBackground()->SetDrawFlags( Background::Container::DRAW_SKYBOX | Background::Container::DRAW_STARS );
|
||||
m_space->GetBackground()->SetDrawFlags(Background::Container::DRAW_SKYBOX | Background::Container::DRAW_STARS);
|
||||
|
||||
m_state = STATE_NORMAL;
|
||||
}
|
||||
|
||||
const float Game::s_timeAccelRates[] = {
|
||||
0.0f, // paused
|
||||
1.0f, // 1x
|
||||
10.0f, // 10x
|
||||
100.0f, // 100x
|
||||
1000.0f, // 1000x
|
||||
10000.0f, // 10000x
|
||||
100000.0f // hyperspace
|
||||
0.0f, // paused
|
||||
1.0f, // 1x
|
||||
10.0f, // 10x
|
||||
100.0f, // 100x
|
||||
1000.0f, // 1000x
|
||||
10000.0f, // 10000x
|
||||
100000.0f // hyperspace
|
||||
};
|
||||
|
||||
const float Game::s_timeInvAccelRates[] = {
|
||||
0.0f, // paused
|
||||
1.0f, // 1x
|
||||
0.1f, // 10x
|
||||
0.01f, // 100x
|
||||
0.001f, // 1000x
|
||||
0.0001f, // 10000x
|
||||
0.00001f // hyperspace
|
||||
0.0f, // paused
|
||||
1.0f, // 1x
|
||||
0.1f, // 10x
|
||||
0.01f, // 100x
|
||||
0.001f, // 1000x
|
||||
0.0001f, // 10000x
|
||||
0.00001f // hyperspace
|
||||
};
|
||||
|
||||
void Game::SetTimeAccel(TimeAccel t)
|
||||
{
|
||||
// don't want player to spin like mad when hitting time accel
|
||||
if ((t != m_timeAccel) && (t > TIMEACCEL_1X) &&
|
||||
m_player->GetPlayerController()->GetRotationDamping()) {
|
||||
m_player->SetAngVelocity(vector3d(0,0,0));
|
||||
m_player->SetTorque(vector3d(0,0,0));
|
||||
m_player->GetPlayerController()->GetRotationDamping()) {
|
||||
m_player->SetAngVelocity(vector3d(0, 0, 0));
|
||||
m_player->SetTorque(vector3d(0, 0, 0));
|
||||
m_player->SetAngThrusterState(vector3d(0.0));
|
||||
}
|
||||
|
||||
// Give all ships a half-step acceleration to stop autopilot overshoot
|
||||
if (t < m_timeAccel)
|
||||
for (Body* b : m_space->GetBodies())
|
||||
for (Body *b : m_space->GetBodies())
|
||||
if (b->IsType(Object::SHIP))
|
||||
(static_cast<Ship*>(b))->TimeAccelAdjust(0.5f * GetTimeStep());
|
||||
(static_cast<Ship *>(b))->TimeAccelAdjust(0.5f * GetTimeStep());
|
||||
|
||||
bool emitPaused = (t == TIMEACCEL_PAUSED && t != m_timeAccel);
|
||||
bool emitResumed = (m_timeAccel == TIMEACCEL_PAUSED && t != TIMEACCEL_PAUSED);
|
||||
|
@ -668,59 +666,59 @@ void Game::RequestTimeAccel(TimeAccel t, bool force)
|
|||
|
||||
void Game::RequestTimeAccelInc(bool force)
|
||||
{
|
||||
switch(m_requestedTimeAccel) {
|
||||
case Game::TIMEACCEL_1X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_10X;
|
||||
break;
|
||||
case Game::TIMEACCEL_10X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_100X;
|
||||
break;
|
||||
case Game::TIMEACCEL_100X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_1000X;
|
||||
break;
|
||||
case Game::TIMEACCEL_1000X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_10000X;
|
||||
break;
|
||||
default:
|
||||
// ignore if paused, hyperspace or 10000X
|
||||
break;
|
||||
switch (m_requestedTimeAccel) {
|
||||
case Game::TIMEACCEL_1X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_10X;
|
||||
break;
|
||||
case Game::TIMEACCEL_10X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_100X;
|
||||
break;
|
||||
case Game::TIMEACCEL_100X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_1000X;
|
||||
break;
|
||||
case Game::TIMEACCEL_1000X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_10000X;
|
||||
break;
|
||||
default:
|
||||
// ignore if paused, hyperspace or 10000X
|
||||
break;
|
||||
}
|
||||
m_forceTimeAccel = force;
|
||||
}
|
||||
|
||||
void Game::RequestTimeAccelDec(bool force)
|
||||
{
|
||||
switch(m_requestedTimeAccel) {
|
||||
case Game::TIMEACCEL_10X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_1X;
|
||||
break;
|
||||
case Game::TIMEACCEL_100X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_10X;
|
||||
break;
|
||||
case Game::TIMEACCEL_1000X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_100X;
|
||||
break;
|
||||
case Game::TIMEACCEL_10000X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_1000X;
|
||||
break;
|
||||
default:
|
||||
// ignore if paused, hyperspace or 1X
|
||||
break;
|
||||
switch (m_requestedTimeAccel) {
|
||||
case Game::TIMEACCEL_10X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_1X;
|
||||
break;
|
||||
case Game::TIMEACCEL_100X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_10X;
|
||||
break;
|
||||
case Game::TIMEACCEL_1000X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_100X;
|
||||
break;
|
||||
case Game::TIMEACCEL_10000X:
|
||||
m_requestedTimeAccel = Game::TIMEACCEL_1000X;
|
||||
break;
|
||||
default:
|
||||
// ignore if paused, hyperspace or 1X
|
||||
break;
|
||||
}
|
||||
m_forceTimeAccel = force;
|
||||
}
|
||||
|
||||
Game::Views::Views()
|
||||
: m_sectorView(nullptr)
|
||||
, m_galacticView(nullptr)
|
||||
, m_systemInfoView(nullptr)
|
||||
, m_systemView(nullptr)
|
||||
, m_worldView(nullptr)
|
||||
, m_deathView(nullptr)
|
||||
, m_spaceStationView(nullptr)
|
||||
, m_infoView(nullptr)
|
||||
, m_cpan(nullptr)
|
||||
{ }
|
||||
Game::Views::Views() :
|
||||
m_sectorView(nullptr),
|
||||
m_galacticView(nullptr),
|
||||
m_systemInfoView(nullptr),
|
||||
m_systemView(nullptr),
|
||||
m_worldView(nullptr),
|
||||
m_deathView(nullptr),
|
||||
m_spaceStationView(nullptr),
|
||||
m_infoView(nullptr),
|
||||
m_cpan(nullptr)
|
||||
{}
|
||||
|
||||
void Game::Views::SetRenderer(Graphics::Renderer *r)
|
||||
{
|
||||
|
@ -737,7 +735,7 @@ void Game::Views::SetRenderer(Graphics::Renderer *r)
|
|||
#endif
|
||||
}
|
||||
|
||||
void Game::Views::Init(Game* game)
|
||||
void Game::Views::Init(Game *game)
|
||||
{
|
||||
m_cpan = new ShipCpanel(Pi::renderer, game);
|
||||
m_sectorView = new SectorView(game);
|
||||
|
@ -756,7 +754,7 @@ void Game::Views::Init(Game* game)
|
|||
SetRenderer(Pi::renderer);
|
||||
}
|
||||
|
||||
void Game::Views::LoadFromJson(const Json &jsonObj, Game* game)
|
||||
void Game::Views::LoadFromJson(const Json &jsonObj, Game *game)
|
||||
{
|
||||
m_cpan = new ShipCpanel(jsonObj, Pi::renderer, game);
|
||||
m_sectorView = new SectorView(jsonObj, game);
|
||||
|
@ -840,7 +838,7 @@ void Game::DestroyViews()
|
|||
|
||||
void Game::EmitPauseState(bool paused)
|
||||
{
|
||||
if (paused) {
|
||||
if (paused) {
|
||||
// Notify UI that time is paused.
|
||||
LuaEvent::Queue("onGamePaused");
|
||||
} else {
|
||||
|
@ -872,11 +870,9 @@ Game *Game::LoadGame(const std::string &filename)
|
|||
|
||||
try {
|
||||
return new Game(rootNode);
|
||||
}
|
||||
catch (Json::type_error) {
|
||||
} catch (Json::type_error) {
|
||||
throw SavedGameCorruptException();
|
||||
}
|
||||
catch (Json::out_of_range) {
|
||||
} catch (Json::out_of_range) {
|
||||
throw SavedGameCorruptException();
|
||||
}
|
||||
}
|
||||
|
|
70
src/Game.h
70
src/Game.h
|
@ -4,13 +4,13 @@
|
|||
#ifndef _GAME_H
|
||||
#define _GAME_H
|
||||
|
||||
#include <string>
|
||||
#include "libs.h"
|
||||
#include "gameconsts.h"
|
||||
#include "GameLog.h"
|
||||
#include "JsonFwd.h"
|
||||
#include "galaxy/Galaxy.h"
|
||||
#include "galaxy/SystemPath.h"
|
||||
#include "JsonFwd.h"
|
||||
#include "gameconsts.h"
|
||||
#include "libs.h"
|
||||
#include <string>
|
||||
|
||||
class HyperspaceCloud;
|
||||
class Player;
|
||||
|
@ -22,7 +22,8 @@ struct CannotSaveInHyperspace : public CannotSaveCurrentGameState {};
|
|||
struct CannotSaveDeadPlayer : public CannotSaveCurrentGameState {};
|
||||
struct InvalidGameStartLocation {
|
||||
std::string error;
|
||||
InvalidGameStartLocation(const std::string& error_) : error(error_) {}
|
||||
InvalidGameStartLocation(const std::string &error_) :
|
||||
error(error_) {}
|
||||
};
|
||||
|
||||
class SectorView;
|
||||
|
@ -83,9 +84,9 @@ public:
|
|||
double GetHyperspaceDuration() const { return m_hyperspaceDuration; }
|
||||
double GetHyperspaceEndTime() const { return m_hyperspaceEndTime; }
|
||||
double GetHyperspaceArrivalProbability() const;
|
||||
const SystemPath& GetHyperspaceDest() const { return m_hyperspaceDest; }
|
||||
const SystemPath& GetHyperspaceSource() const { return m_hyperspaceSource; }
|
||||
void RemoveHyperspaceCloud(HyperspaceCloud*);
|
||||
const SystemPath &GetHyperspaceDest() const { return m_hyperspaceDest; }
|
||||
const SystemPath &GetHyperspaceSource() const { return m_hyperspaceSource; }
|
||||
void RemoveHyperspaceCloud(HyperspaceCloud *);
|
||||
|
||||
enum TimeAccel {
|
||||
TIMEACCEL_PAUSED,
|
||||
|
@ -95,7 +96,7 @@ public:
|
|||
TIMEACCEL_1000X,
|
||||
TIMEACCEL_10000X,
|
||||
TIMEACCEL_HYPERSPACE
|
||||
};
|
||||
};
|
||||
|
||||
void SetTimeAccel(TimeAccel t);
|
||||
void RequestTimeAccel(TimeAccel t, bool force = false);
|
||||
|
@ -114,19 +115,22 @@ public:
|
|||
float GetTimeAccelRate() const { return s_timeAccelRates[m_timeAccel]; }
|
||||
float GetInvTimeAccelRate() const { return s_timeInvAccelRates[m_timeAccel]; }
|
||||
|
||||
float GetTimeStep() const { return s_timeAccelRates[m_timeAccel]*(1.0f/PHYSICS_HZ); }
|
||||
float GetTimeStep() const { return s_timeAccelRates[m_timeAccel] * (1.0f / PHYSICS_HZ); }
|
||||
|
||||
SectorView* GetSectorView() const { return m_gameViews->m_sectorView; }
|
||||
UIView* GetGalacticView() const { return m_gameViews->m_galacticView; }
|
||||
SystemInfoView* GetSystemInfoView() const { return m_gameViews->m_systemInfoView; }
|
||||
SystemView* GetSystemView() const { return m_gameViews->m_systemView; }
|
||||
WorldView* GetWorldView() const { return m_gameViews->m_worldView; }
|
||||
DeathView* GetDeathView() const { return m_gameViews->m_deathView; }
|
||||
UIView* GetSpaceStationView() const { return m_gameViews->m_spaceStationView; }
|
||||
UIView* GetInfoView() const { return m_gameViews->m_infoView; }
|
||||
ShipCpanel* GetCpan() const { return m_gameViews->m_cpan; }
|
||||
SectorView *GetSectorView() const { return m_gameViews->m_sectorView; }
|
||||
UIView *GetGalacticView() const { return m_gameViews->m_galacticView; }
|
||||
SystemInfoView *GetSystemInfoView() const { return m_gameViews->m_systemInfoView; }
|
||||
SystemView *GetSystemView() const { return m_gameViews->m_systemView; }
|
||||
WorldView *GetWorldView() const { return m_gameViews->m_worldView; }
|
||||
DeathView *GetDeathView() const { return m_gameViews->m_deathView; }
|
||||
UIView *GetSpaceStationView() const { return m_gameViews->m_spaceStationView; }
|
||||
UIView *GetInfoView() const { return m_gameViews->m_infoView; }
|
||||
ShipCpanel *GetCpan() const { return m_gameViews->m_cpan; }
|
||||
#if WITH_OBJECTVIEWER
|
||||
ObjectViewerView* GetObjectViewerView() const { return m_gameViews->m_objectViewerView; }
|
||||
ObjectViewerView *GetObjectViewerView() const
|
||||
{
|
||||
return m_gameViews->m_objectViewerView;
|
||||
}
|
||||
#endif
|
||||
|
||||
GameLog *log;
|
||||
|
@ -135,23 +139,23 @@ private:
|
|||
class Views {
|
||||
public:
|
||||
Views();
|
||||
void Init(Game* game);
|
||||
void LoadFromJson(const Json &jsonObj, Game* game);
|
||||
void Init(Game *game);
|
||||
void LoadFromJson(const Json &jsonObj, Game *game);
|
||||
~Views();
|
||||
|
||||
void SetRenderer(Graphics::Renderer *r);
|
||||
|
||||
SectorView* m_sectorView;
|
||||
UIView* m_galacticView;
|
||||
SystemInfoView* m_systemInfoView;
|
||||
SystemView* m_systemView;
|
||||
WorldView* m_worldView;
|
||||
DeathView* m_deathView;
|
||||
UIView* m_spaceStationView;
|
||||
UIView* m_infoView;
|
||||
ShipCpanel* m_cpan;
|
||||
SectorView *m_sectorView;
|
||||
UIView *m_galacticView;
|
||||
SystemInfoView *m_systemInfoView;
|
||||
SystemView *m_systemView;
|
||||
WorldView *m_worldView;
|
||||
DeathView *m_deathView;
|
||||
UIView *m_spaceStationView;
|
||||
UIView *m_infoView;
|
||||
ShipCpanel *m_cpan;
|
||||
#if WITH_OBJECTVIEWER
|
||||
ObjectViewerView* m_objectViewerView;
|
||||
ObjectViewerView *m_objectViewerView;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -179,7 +183,7 @@ private:
|
|||
|
||||
bool m_wantHyperspace;
|
||||
|
||||
std::list<HyperspaceCloud*> m_hyperspaceClouds;
|
||||
std::list<HyperspaceCloud *> m_hyperspaceClouds;
|
||||
SystemPath m_hyperspaceSource;
|
||||
SystemPath m_hyperspaceDest;
|
||||
double m_hyperspaceProgress;
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "GameConfig.h"
|
||||
#include "KeyBindings.h"
|
||||
#include "FileSystem.h"
|
||||
#include "KeyBindings.h"
|
||||
|
||||
GameConfig::GameConfig(const map_string &override_)
|
||||
{
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "GameLog.h"
|
||||
#include "Game.h"
|
||||
#include "LuaObject.h"
|
||||
#include "Pi.h"
|
||||
#include "StringF.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "LuaObject.h"
|
||||
#include "Game.h"
|
||||
#include "Pi.h"
|
||||
|
||||
void GameLog::Add(const std::string &msg)
|
||||
{
|
||||
|
@ -28,4 +28,3 @@ void GameLog::Add(const std::string &from, const std::string &msg, GameLog::Prio
|
|||
lua_pushnumber(l, priority);
|
||||
lua_call(l, 3, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,16 +9,14 @@
|
|||
* atm it holds only 6 messages, but do extend
|
||||
*/
|
||||
|
||||
|
||||
class GameLog {
|
||||
public:
|
||||
enum Priority { PRIORITY_NORMAL = 0,
|
||||
PRIORITY_IMPORTANT = 1,
|
||||
PRIORITY_ALERT = 2 };
|
||||
PRIORITY_IMPORTANT = 1,
|
||||
PRIORITY_ALERT = 2 };
|
||||
|
||||
void Add(const std::string&);
|
||||
void Add(const std::string &);
|
||||
void Add(const std::string &from, const std::string &msg, Priority priority);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
292
src/GasGiant.cpp
292
src/GasGiant.cpp
|
@ -1,38 +1,37 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "GasGiant.h"
|
||||
#include "perlin.h"
|
||||
#include "Pi.h"
|
||||
#include "IniConfig.h"
|
||||
#include "FileSystem.h"
|
||||
#include "Game.h"
|
||||
#include "IniConfig.h"
|
||||
#include "Pi.h"
|
||||
#include "RefCounted.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/opengl/GenGasGiantColourMaterial.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/Frustum.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/TextureBuilder.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "graphics/Types.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "graphics/opengl/GenGasGiantColourMaterial.h"
|
||||
#include "libs.h"
|
||||
#include "perlin.h"
|
||||
#include "vcacheopt/vcacheopt.h"
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
RefCountedPtr<GasPatchContext> GasGiant::s_patchContext;
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
static Uint32 s_texture_size_small = 16;
|
||||
static Uint32 s_texture_size_cpu[5];
|
||||
static Uint32 s_texture_size_gpu[5];
|
||||
static Uint32 s_noiseOctaves[5];
|
||||
static float s_initialCPUDelayTime = 60.0f; // (perhaps) 60 seconds seems like a reasonable default
|
||||
static float s_initialGPUDelayTime = 5.0f; // (perhaps) 5 seconds seems like a reasonable default
|
||||
static std::vector<GasGiant*> s_allGasGiants;
|
||||
static std::vector<GasGiant *> s_allGasGiants;
|
||||
|
||||
static const std::string GGJupiter("GGJupiter");
|
||||
static const std::string GGNeptune("GGNeptune");
|
||||
|
@ -46,7 +45,7 @@ namespace
|
|||
static const std::string delim(",");
|
||||
|
||||
enum dataEntries {
|
||||
eCPU=0,
|
||||
eCPU = 0,
|
||||
eGPU,
|
||||
eOCTAVES
|
||||
};
|
||||
|
@ -64,8 +63,7 @@ namespace
|
|||
end = spec.find_first_of(delim, start);
|
||||
|
||||
// extract the fragment and remember it
|
||||
switch(i)
|
||||
{
|
||||
switch (i) {
|
||||
case eCPU:
|
||||
cpuOut = ceil_pow2(Clamp(atoi(spec.substr(start, (end == std::string::npos) ? std::string::npos : end - start).c_str()), 64, 4096));
|
||||
break;
|
||||
|
@ -82,83 +80,87 @@ namespace
|
|||
i++;
|
||||
}
|
||||
|
||||
return i==4;
|
||||
return i == 4;
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace
|
||||
|
||||
class GasPatchContext : public RefCounted {
|
||||
public:
|
||||
#pragma pack(push, 4)
|
||||
struct VBOVertex
|
||||
{
|
||||
#pragma pack(push, 4)
|
||||
struct VBOVertex {
|
||||
vector3f pos;
|
||||
vector3f norm;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
#pragma pack(pop)
|
||||
|
||||
int edgeLen;
|
||||
|
||||
inline int IDX_VBO_COUNT_ALL_IDX() const { return ((edgeLen-1)*(edgeLen-1))*2*3; }
|
||||
inline int IDX_VBO_COUNT_ALL_IDX() const { return ((edgeLen - 1) * (edgeLen - 1)) * 2 * 3; }
|
||||
|
||||
inline int NUMVERTICES() const { return edgeLen*edgeLen; }
|
||||
inline int NUMVERTICES() const { return edgeLen * edgeLen; }
|
||||
|
||||
double frac;
|
||||
|
||||
std::unique_ptr<Uint32[]> indices;
|
||||
RefCountedPtr<Graphics::IndexBuffer> indexBuffer;
|
||||
|
||||
GasPatchContext(const int _edgeLen) : edgeLen(_edgeLen) {
|
||||
GasPatchContext(const int _edgeLen) :
|
||||
edgeLen(_edgeLen)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
~GasPatchContext() {
|
||||
~GasPatchContext()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void Refresh() {
|
||||
void Refresh()
|
||||
{
|
||||
Cleanup();
|
||||
Init();
|
||||
}
|
||||
|
||||
void Cleanup() {
|
||||
void Cleanup()
|
||||
{
|
||||
indices.reset();
|
||||
}
|
||||
|
||||
int GetIndices(std::vector<Uint32> &pl)
|
||||
{
|
||||
// calculate how many tri's there are
|
||||
const int tri_count = IDX_VBO_COUNT_ALL_IDX()/3;
|
||||
const int tri_count = IDX_VBO_COUNT_ALL_IDX() / 3;
|
||||
|
||||
// pre-allocate enough space
|
||||
pl.reserve(IDX_VBO_COUNT_ALL_IDX());
|
||||
|
||||
// add all of the middle indices
|
||||
for(int i=0; i<IDX_VBO_COUNT_ALL_IDX(); ++i) {
|
||||
for (int i = 0; i < IDX_VBO_COUNT_ALL_IDX(); ++i) {
|
||||
pl.push_back(indices[i]);
|
||||
}
|
||||
|
||||
return tri_count;
|
||||
}
|
||||
|
||||
void Init() {
|
||||
void Init()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
frac = 1.0 / double(edgeLen-1);
|
||||
frac = 1.0 / double(edgeLen - 1);
|
||||
|
||||
// also want vtx indices for tris not touching edge of patch
|
||||
indices.reset(new Uint32[IDX_VBO_COUNT_ALL_IDX()]);
|
||||
Uint32 *idx = indices.get();
|
||||
for (int x=0; x<edgeLen-1; x++) {
|
||||
for (int y=0; y<edgeLen-1; y++) {
|
||||
idx[0] = x + edgeLen*y;
|
||||
idx[1] = x+1 + edgeLen*y;
|
||||
idx[2] = x + edgeLen*(y+1);
|
||||
idx+=3;
|
||||
for (int x = 0; x < edgeLen - 1; x++) {
|
||||
for (int y = 0; y < edgeLen - 1; y++) {
|
||||
idx[0] = x + edgeLen * y;
|
||||
idx[1] = x + 1 + edgeLen * y;
|
||||
idx[2] = x + edgeLen * (y + 1);
|
||||
idx += 3;
|
||||
|
||||
idx[0] = x+1 + edgeLen*y;
|
||||
idx[1] = x+1 + edgeLen*(y+1);
|
||||
idx[2] = x + edgeLen*(y+1);
|
||||
idx+=3;
|
||||
idx[0] = x + 1 + edgeLen * y;
|
||||
idx[1] = x + 1 + edgeLen * (y + 1);
|
||||
idx[2] = x + edgeLen * (y + 1);
|
||||
idx += 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,7 +176,7 @@ public:
|
|||
|
||||
//create buffer & copy
|
||||
indexBuffer.Reset(Pi::renderer->CreateIndexBuffer(pl_short.size(), Graphics::BUFFER_USAGE_STATIC));
|
||||
Uint32* idxPtr = indexBuffer->Map(Graphics::BUFFER_MAP_WRITE);
|
||||
Uint32 *idxPtr = indexBuffer->Map(Graphics::BUFFER_MAP_WRITE);
|
||||
for (Uint32 j = 0; j < pl_short.size(); j++) {
|
||||
idxPtr[j] = pl_short[j];
|
||||
}
|
||||
|
@ -186,7 +188,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class GasPatch {
|
||||
public:
|
||||
RefCountedPtr<GasPatchContext> ctx;
|
||||
|
@ -196,13 +197,19 @@ public:
|
|||
vector3d clipCentroid;
|
||||
double clipRadius;
|
||||
|
||||
GasPatch(const RefCountedPtr<GasPatchContext> &_ctx, GasGiant *gs, vector3d v0, vector3d v1, vector3d v2, vector3d v3)
|
||||
: ctx(_ctx), gasSphere(gs), clipCentroid(((v0+v1+v2+v3) * 0.25).Normalized()), clipRadius(0.0)
|
||||
GasPatch(const RefCountedPtr<GasPatchContext> &_ctx, GasGiant *gs, vector3d v0, vector3d v1, vector3d v2, vector3d v3) :
|
||||
ctx(_ctx),
|
||||
gasSphere(gs),
|
||||
clipCentroid(((v0 + v1 + v2 + v3) * 0.25).Normalized()),
|
||||
clipRadius(0.0)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3;
|
||||
for (int i=0; i<4; i++) {
|
||||
clipRadius = std::max(clipRadius, (v[i]-clipCentroid).Length());
|
||||
v[0] = v0;
|
||||
v[1] = v1;
|
||||
v[2] = v2;
|
||||
v[3] = v3;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
clipRadius = std::max(clipRadius, (v[i] - clipCentroid).Length());
|
||||
}
|
||||
|
||||
UpdateVBOs();
|
||||
|
@ -211,30 +218,32 @@ public:
|
|||
~GasPatch() {}
|
||||
|
||||
/* in patch surface coords, [0,1] */
|
||||
vector3d GetSpherePoint(const double x, const double y) const {
|
||||
return (v[0] + x*(1.0-y)*(v[1]-v[0]) + x*y*(v[2]-v[0]) + (1.0-x)*y*(v[3]-v[0])).Normalized();
|
||||
vector3d GetSpherePoint(const double x, const double y) const
|
||||
{
|
||||
return (v[0] + x * (1.0 - y) * (v[1] - v[0]) + x * y * (v[2] - v[0]) + (1.0 - x) * y * (v[3] - v[0])).Normalized();
|
||||
}
|
||||
|
||||
void UpdateVBOs() {
|
||||
void UpdateVBOs()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
//create buffer and upload data
|
||||
Graphics::VertexBufferDesc vbd;
|
||||
vbd.attrib[0].semantic = Graphics::ATTRIB_POSITION;
|
||||
vbd.attrib[0].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[0].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[1].semantic = Graphics::ATTRIB_NORMAL;
|
||||
vbd.attrib[1].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[1].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.numVertices = ctx->NUMVERTICES();
|
||||
vbd.usage = Graphics::BUFFER_USAGE_STATIC;
|
||||
m_vertexBuffer.reset(Pi::renderer->CreateVertexBuffer(vbd));
|
||||
|
||||
GasPatchContext::VBOVertex* vtxPtr = m_vertexBuffer->Map<GasPatchContext::VBOVertex>(Graphics::BUFFER_MAP_WRITE);
|
||||
GasPatchContext::VBOVertex *vtxPtr = m_vertexBuffer->Map<GasPatchContext::VBOVertex>(Graphics::BUFFER_MAP_WRITE);
|
||||
assert(m_vertexBuffer->GetDesc().stride == sizeof(GasPatchContext::VBOVertex));
|
||||
|
||||
const Sint32 edgeLen = ctx->edgeLen;
|
||||
const double frac = ctx->frac;
|
||||
for (Sint32 y=0; y<edgeLen; y++) {
|
||||
for (Sint32 x=0; x<edgeLen; x++) {
|
||||
const vector3d p = GetSpherePoint(x*frac, y*frac);
|
||||
for (Sint32 y = 0; y < edgeLen; y++) {
|
||||
for (Sint32 x = 0; x < edgeLen; x++) {
|
||||
const vector3d p = GetSpherePoint(x * frac, y * frac);
|
||||
const vector3d pSubCentroid = p - clipCentroid;
|
||||
clipRadius = std::max(clipRadius, p.Length());
|
||||
vtxPtr->pos = vector3f(pSubCentroid);
|
||||
|
@ -246,7 +255,8 @@ public:
|
|||
m_vertexBuffer->Unmap();
|
||||
}
|
||||
|
||||
void Render(Graphics::Renderer *renderer, const vector3d &campos, const matrix4x4d &modelView, const Graphics::Frustum &frustum) {
|
||||
void Render(Graphics::Renderer *renderer, const vector3d &campos, const matrix4x4d &modelView, const Graphics::Frustum &frustum)
|
||||
{
|
||||
if (!frustum.TestPoint(clipCentroid, clipRadius))
|
||||
return;
|
||||
|
||||
|
@ -256,7 +266,7 @@ public:
|
|||
const vector3d relpos = clipCentroid - campos;
|
||||
renderer->SetTransform(modelView * matrix4x4d::Translation(relpos));
|
||||
|
||||
Pi::statSceneTris += 2*(ctx->edgeLen-1)*(ctx->edgeLen-1);
|
||||
Pi::statSceneTris += 2 * (ctx->edgeLen - 1) * (ctx->edgeLen - 1);
|
||||
++Pi::statNumPatches;
|
||||
|
||||
renderer->DrawBufferIndexed(m_vertexBuffer.get(), ctx->indexBuffer.Get(), rs, mat.Get());
|
||||
|
@ -264,15 +274,14 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
Graphics::RenderTarget *GasGiant::s_renderTarget;
|
||||
Graphics::RenderState *GasGiant::s_quadRenderState;
|
||||
Graphics::RenderTarget *GasGiant::s_renderTarget;
|
||||
Graphics::RenderState *GasGiant::s_quadRenderState;
|
||||
|
||||
// static
|
||||
void GasGiant::UpdateAllGasGiants()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
for(std::vector<GasGiant*>::iterator i = s_allGasGiants.begin(); i != s_allGasGiants.end(); ++i)
|
||||
{
|
||||
for (std::vector<GasGiant *>::iterator i = s_allGasGiants.begin(); i != s_allGasGiants.end(); ++i) {
|
||||
(*i)->Update();
|
||||
}
|
||||
}
|
||||
|
@ -283,8 +292,7 @@ void GasGiant::OnChangeDetailLevel()
|
|||
s_patchContext.Reset(new GasPatchContext(127));
|
||||
|
||||
// reinit the geosphere terrain data
|
||||
for(std::vector<GasGiant*>::iterator i = s_allGasGiants.begin(); i != s_allGasGiants.end(); ++i)
|
||||
{
|
||||
for (std::vector<GasGiant *>::iterator i = s_allGasGiants.begin(); i != s_allGasGiants.end(); ++i) {
|
||||
// clearout anything we don't need
|
||||
(*i)->Reset();
|
||||
|
||||
|
@ -293,19 +301,23 @@ void GasGiant::OnChangeDetailLevel()
|
|||
}
|
||||
}
|
||||
|
||||
GasGiant::GasGiant(const SystemBody *body) : BaseSphere(body),
|
||||
m_hasTempCampos(false), m_tempCampos(0.0), m_hasGpuJobRequest(false), m_timeDelay(s_initialCPUDelayTime)
|
||||
GasGiant::GasGiant(const SystemBody *body) :
|
||||
BaseSphere(body),
|
||||
m_hasTempCampos(false),
|
||||
m_tempCampos(0.0),
|
||||
m_hasGpuJobRequest(false),
|
||||
m_timeDelay(s_initialCPUDelayTime)
|
||||
{
|
||||
s_allGasGiants.push_back(this);
|
||||
|
||||
for(int i=0; i<NUM_PATCHES; i++) {
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
m_hasJobRequest[i] = false;
|
||||
}
|
||||
|
||||
Random rng(GetSystemBody()->GetSeed()+4609837);
|
||||
Random rng(GetSystemBody()->GetSeed() + 4609837);
|
||||
|
||||
const bool bEnableGPUJobs = (Pi::config->Int("EnableGPUJobs") == 1);
|
||||
if(bEnableGPUJobs)
|
||||
if (bEnableGPUJobs)
|
||||
m_timeDelay = s_initialGPUDelayTime + (rng.Double() * (s_initialGPUDelayTime * 0.5));
|
||||
|
||||
//SetUpMaterials is not called until first Render since light count is zero :)
|
||||
|
@ -323,14 +335,14 @@ GasGiant::~GasGiant()
|
|||
void GasGiant::Reset()
|
||||
{
|
||||
{
|
||||
for(int i=0; i<NUM_PATCHES; i++) {
|
||||
if(m_hasJobRequest[i] && m_job[i].HasJob())
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
if (m_hasJobRequest[i] && m_job[i].HasJob())
|
||||
m_job[i].GetJob()->OnCancel();
|
||||
m_hasJobRequest[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int p=0; p<NUM_PATCHES; p++) {
|
||||
for (int p = 0; p < NUM_PATCHES; p++) {
|
||||
// delete patches
|
||||
if (m_patches[p]) {
|
||||
m_patches[p].reset();
|
||||
|
@ -346,14 +358,14 @@ void GasGiant::Reset()
|
|||
bool GasGiant::OnAddTextureFaceResult(const SystemPath &path, GasGiantJobs::STextureFaceResult *res)
|
||||
{
|
||||
// Find the correct GeoSphere via it's system path, and give it the split result
|
||||
for(std::vector<GasGiant*>::iterator i=s_allGasGiants.begin(), iEnd=s_allGasGiants.end(); i!=iEnd; ++i) {
|
||||
if( path == (*i)->GetSystemBody()->GetPath() ) {
|
||||
for (std::vector<GasGiant *>::iterator i = s_allGasGiants.begin(), iEnd = s_allGasGiants.end(); i != iEnd; ++i) {
|
||||
if (path == (*i)->GetSystemBody()->GetPath()) {
|
||||
(*i)->AddTextureFaceResult(res);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// GasGiant not found to return the data to, cancel (which deletes it) instead
|
||||
if( res ) {
|
||||
if (res) {
|
||||
res->OnCancel();
|
||||
delete res;
|
||||
}
|
||||
|
@ -364,14 +376,14 @@ bool GasGiant::OnAddTextureFaceResult(const SystemPath &path, GasGiantJobs::STex
|
|||
bool GasGiant::OnAddGPUGenResult(const SystemPath &path, GasGiantJobs::SGPUGenResult *res)
|
||||
{
|
||||
// Find the correct GeoSphere via it's system path, and give it the split result
|
||||
for(std::vector<GasGiant*>::iterator i=s_allGasGiants.begin(), iEnd=s_allGasGiants.end(); i!=iEnd; ++i) {
|
||||
if( path == (*i)->GetSystemBody()->GetPath() ) {
|
||||
for (std::vector<GasGiant *>::iterator i = s_allGasGiants.begin(), iEnd = s_allGasGiants.end(); i != iEnd; ++i) {
|
||||
if (path == (*i)->GetSystemBody()->GetPath()) {
|
||||
(*i)->AddGPUGenResult(res);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// GasGiant not found to return the data to, cancel (which deletes it) instead
|
||||
if( res ) {
|
||||
if (res) {
|
||||
res->OnCancel();
|
||||
delete res;
|
||||
}
|
||||
|
@ -384,7 +396,7 @@ bool GasGiant::OnAddGPUGenResult(const SystemPath &path, GasGiantJobs::SGPUGenRe
|
|||
#include "FileSystem.h"
|
||||
#include "PngWriter.h"
|
||||
#include "graphics/opengl/TextureGL.h"
|
||||
void textureDump(const char* destFile, const int width, const int height, const Color* buf)
|
||||
void textureDump(const char *destFile, const int width, const int height, const Color *buf)
|
||||
{
|
||||
const std::string dir = "generated_textures";
|
||||
FileSystem::userFiles.MakeDirectory(dir);
|
||||
|
@ -405,20 +417,20 @@ bool GasGiant::AddTextureFaceResult(GasGiantJobs::STextureFaceResult *res)
|
|||
bool result = false;
|
||||
assert(res);
|
||||
assert(res->face() >= 0 && res->face() < NUM_PATCHES);
|
||||
m_jobColorBuffers[res->face()].reset( res->data().colors );
|
||||
m_jobColorBuffers[res->face()].reset(res->data().colors);
|
||||
m_hasJobRequest[res->face()] = false;
|
||||
const Sint32 uvDims = res->data().uvDims;
|
||||
assert( uvDims > 0 && uvDims <= 4096 );
|
||||
assert(uvDims > 0 && uvDims <= 4096);
|
||||
|
||||
// tidyup
|
||||
delete res;
|
||||
|
||||
bool bCreateTexture = true;
|
||||
for(int i=0; i<NUM_PATCHES; i++) {
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
bCreateTexture = bCreateTexture & (!m_hasJobRequest[i]);
|
||||
}
|
||||
|
||||
if( bCreateTexture ) {
|
||||
if (bCreateTexture) {
|
||||
// create texture
|
||||
const vector2f texSize(1.0f, 1.0f);
|
||||
const vector2f dataSize(uvDims, uvDims);
|
||||
|
@ -439,7 +451,7 @@ bool GasGiant::AddTextureFaceResult(GasGiantJobs::STextureFaceResult *res)
|
|||
m_surfaceTexture->Update(tcd, dataSize, Graphics::TEXTURE_RGBA_8888);
|
||||
|
||||
#if DUMP_TO_TEXTURE
|
||||
for (int iFace = 0; iFace<NUM_PATCHES; iFace++) {
|
||||
for (int iFace = 0; iFace < NUM_PATCHES; iFace++) {
|
||||
char filename[1024];
|
||||
snprintf(filename, 1024, "%s%d.png", GetSystemBody()->GetName().c_str(), iFace);
|
||||
textureDump(filename, uvDims, uvDims, m_jobColorBuffers[iFace].get());
|
||||
|
@ -447,12 +459,12 @@ bool GasGiant::AddTextureFaceResult(GasGiantJobs::STextureFaceResult *res)
|
|||
#endif
|
||||
|
||||
// cleanup the temporary color buffer storage
|
||||
for(int i=0; i<NUM_PATCHES; i++) {
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
m_jobColorBuffers[i].reset();
|
||||
}
|
||||
|
||||
// change the planet texture for the new higher resolution texture
|
||||
if( m_surfaceMaterial.Get() ) {
|
||||
if (m_surfaceMaterial.Get()) {
|
||||
m_surfaceMaterial->texture0 = m_surfaceTexture.Get();
|
||||
m_surfaceTextureSmall.Reset();
|
||||
}
|
||||
|
@ -468,13 +480,13 @@ bool GasGiant::AddGPUGenResult(GasGiantJobs::SGPUGenResult *res)
|
|||
m_hasGpuJobRequest = false;
|
||||
assert(!m_gpuJob.HasJob());
|
||||
const Sint32 uvDims = res->data().uvDims;
|
||||
assert( uvDims > 0 && uvDims <= 4096 );
|
||||
assert(uvDims > 0 && uvDims <= 4096);
|
||||
|
||||
#if DUMP_TO_TEXTURE
|
||||
for(int iFace=0; iFace<NUM_PATCHES; iFace++) {
|
||||
std::unique_ptr<Color, FreeDeleter> buffer(static_cast<Color*>(malloc(uvDims*uvDims*4)));
|
||||
Graphics::Texture* pTex = res->data().texture.Get();
|
||||
Graphics::TextureGL* pGLTex = static_cast<Graphics::TextureGL*>(pTex);
|
||||
for (int iFace = 0; iFace < NUM_PATCHES; iFace++) {
|
||||
std::unique_ptr<Color, FreeDeleter> buffer(static_cast<Color *>(malloc(uvDims * uvDims * 4)));
|
||||
Graphics::Texture *pTex = res->data().texture.Get();
|
||||
Graphics::TextureGL *pGLTex = static_cast<Graphics::TextureGL *>(pTex);
|
||||
pGLTex->Bind();
|
||||
glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + iFace, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.get());
|
||||
pGLTex->Unbind();
|
||||
|
@ -496,7 +508,7 @@ bool GasGiant::AddGPUGenResult(GasGiantJobs::SGPUGenResult *res)
|
|||
m_surfaceTexture->BuildMipmaps();
|
||||
|
||||
// change the planet texture for the new higher resolution texture
|
||||
if( m_surfaceMaterial.Get() ) {
|
||||
if (m_surfaceMaterial.Get()) {
|
||||
m_surfaceMaterial->texture0 = m_surfaceTexture.Get();
|
||||
m_surfaceTextureSmall.Reset();
|
||||
}
|
||||
|
@ -506,14 +518,15 @@ bool GasGiant::AddGPUGenResult(GasGiantJobs::SGPUGenResult *res)
|
|||
}
|
||||
|
||||
// in patch surface coords, [0,1]
|
||||
inline vector3d GetSpherePointFromCorners(const double x, const double y, const vector3d *corners) {
|
||||
return (corners[0] + x*(1.0-y)*(corners[1]-corners[0]) + x*y*(corners[2]-corners[0]) + (1.0-x)*y*(corners[3]-corners[0])).Normalized();
|
||||
inline vector3d GetSpherePointFromCorners(const double x, const double y, const vector3d *corners)
|
||||
{
|
||||
return (corners[0] + x * (1.0 - y) * (corners[1] - corners[0]) + x * y * (corners[2] - corners[0]) + (1.0 - x) * y * (corners[3] - corners[0])).Normalized();
|
||||
}
|
||||
|
||||
void GasGiant::GenerateTexture()
|
||||
{
|
||||
using namespace GasGiantJobs;
|
||||
for(int i=0; i<NUM_PATCHES; i++) {
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
if (m_hasGpuJobRequest || m_hasJobRequest[i])
|
||||
return;
|
||||
}
|
||||
|
@ -531,25 +544,25 @@ void GasGiant::GenerateTexture()
|
|||
m_surfaceTextureSmall.Reset(Pi::renderer->CreateTexture(texDesc));
|
||||
|
||||
const Terrain *pTerrain = GetTerrain();
|
||||
const double fracStep = 1.0 / double(s_texture_size_small-1);
|
||||
const double fracStep = 1.0 / double(s_texture_size_small - 1);
|
||||
|
||||
Graphics::TextureCubeData tcd;
|
||||
std::unique_ptr<Color> bufs[NUM_PATCHES];
|
||||
for(int i=0; i<NUM_PATCHES; i++) {
|
||||
Color *colors = new Color[ (s_texture_size_small*s_texture_size_small) ];
|
||||
for( Uint32 v=0; v<s_texture_size_small; v++ ) {
|
||||
for( Uint32 u=0; u<s_texture_size_small; u++ ) {
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
Color *colors = new Color[(s_texture_size_small * s_texture_size_small)];
|
||||
for (Uint32 v = 0; v < s_texture_size_small; v++) {
|
||||
for (Uint32 u = 0; u < s_texture_size_small; u++) {
|
||||
// where in this row & colum are we now.
|
||||
const double ustep = double(u) * fracStep;
|
||||
const double vstep = double(v) * fracStep;
|
||||
|
||||
// get point on the surface of the sphere
|
||||
const vector3d p = GetSpherePointFromCorners(ustep, vstep, &GetPatchFaces(i,0));
|
||||
const vector3d p = GetSpherePointFromCorners(ustep, vstep, &GetPatchFaces(i, 0));
|
||||
// get colour using `p`
|
||||
const vector3d colour = pTerrain->GetColor(p, 0.0, p);
|
||||
|
||||
// convert to ubyte and store
|
||||
Color* col = colors + (u + (v * s_texture_size_small));
|
||||
Color *col = colors + (u + (v * s_texture_size_small));
|
||||
col[0].r = Uint8(colour.x * 255.0);
|
||||
col[0].g = Uint8(colour.y * 255.0);
|
||||
col[0].b = Uint8(colour.z * 255.0);
|
||||
|
@ -570,19 +583,15 @@ void GasGiant::GenerateTexture()
|
|||
}
|
||||
|
||||
// create small texture
|
||||
if( !bEnableGPUJobs )
|
||||
{
|
||||
for(int i=0; i<NUM_PATCHES; i++)
|
||||
{
|
||||
if (!bEnableGPUJobs) {
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
assert(!m_hasJobRequest[i]);
|
||||
assert(!m_job[i].HasJob());
|
||||
m_hasJobRequest[i] = true;
|
||||
GasGiantJobs::STextureFaceRequest *ssrd = new GasGiantJobs::STextureFaceRequest(&GetPatchFaces(i,0), GetSystemBody()->GetPath(), i, s_texture_size_cpu[Pi::detail.planets], GetTerrain());
|
||||
GasGiantJobs::STextureFaceRequest *ssrd = new GasGiantJobs::STextureFaceRequest(&GetPatchFaces(i, 0), GetSystemBody()->GetPath(), i, s_texture_size_cpu[Pi::detail.planets], GetTerrain());
|
||||
m_job[i] = Pi::GetAsyncJobQueue()->Queue(new GasGiantJobs::SingleTextureFaceJob(ssrd));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// use m_surfaceTexture texture?
|
||||
// create texture
|
||||
const vector2f texSize(1.0f, 1.0f);
|
||||
|
@ -597,15 +606,15 @@ void GasGiant::GenerateTexture()
|
|||
Output("Color Fractal name: %s\n", ColorFracName.c_str());
|
||||
|
||||
Uint32 GasGiantType = Graphics::OGL::GEN_JUPITER_TEXTURE;
|
||||
if( ColorFracName == GGSaturn ) {
|
||||
if (ColorFracName == GGSaturn) {
|
||||
GasGiantType = Graphics::OGL::GEN_SATURN_TEXTURE;
|
||||
} else if( ColorFracName == GGSaturn2 ) {
|
||||
} else if (ColorFracName == GGSaturn2) {
|
||||
GasGiantType = Graphics::OGL::GEN_SATURN2_TEXTURE;
|
||||
} else if( ColorFracName == GGNeptune ) {
|
||||
} else if (ColorFracName == GGNeptune) {
|
||||
GasGiantType = Graphics::OGL::GEN_NEPTUNE_TEXTURE;
|
||||
} else if( ColorFracName == GGNeptune2 ) {
|
||||
} else if (ColorFracName == GGNeptune2) {
|
||||
GasGiantType = Graphics::OGL::GEN_NEPTUNE2_TEXTURE;
|
||||
} else if( ColorFracName == GGUranus ) {
|
||||
} else if (ColorFracName == GGUranus) {
|
||||
GasGiantType = Graphics::OGL::GEN_URANUS_TEXTURE;
|
||||
}
|
||||
const Uint32 octaves = (Pi::config->Int("AMD_MESA_HACKS") == 0) ? s_noiseOctaves[Pi::detail.planets] : std::min(5U, s_noiseOctaves[Pi::detail.planets]);
|
||||
|
@ -614,11 +623,11 @@ void GasGiant::GenerateTexture()
|
|||
assert(!m_hasGpuJobRequest);
|
||||
assert(!m_gpuJob.HasJob());
|
||||
|
||||
Random rng(GetSystemBody()->GetSeed()+4609837);
|
||||
Random rng(GetSystemBody()->GetSeed() + 4609837);
|
||||
const std::string parentname = GetSystemBody()->GetParent()->GetName();
|
||||
const float hueShift = (parentname == "Sol") ? 0.0f : float(((rng.Double() * 2.0) - 1.0) * 0.9);
|
||||
|
||||
GasGiantJobs::GenFaceQuad *pQuad = new GasGiantJobs::GenFaceQuad(Pi::renderer, vector2f(s_texture_size_gpu[Pi::detail.planets], s_texture_size_gpu[Pi::detail.planets]), s_quadRenderState, GasGiantType );
|
||||
GasGiantJobs::GenFaceQuad *pQuad = new GasGiantJobs::GenFaceQuad(Pi::renderer, vector2f(s_texture_size_gpu[Pi::detail.planets], s_texture_size_gpu[Pi::detail.planets]), s_quadRenderState, GasGiantType);
|
||||
|
||||
GasGiantJobs::SGPUGenRequest *pGPUReq = new GasGiantJobs::SGPUGenRequest(GetSystemBody()->GetPath(), s_texture_size_gpu[Pi::detail.planets], GetTerrain(), GetSystemBody()->GetRadius(), hueShift, pQuad, m_builtTexture.Get());
|
||||
m_gpuJob = Pi::GetSyncJobQueue()->Queue(new GasGiantJobs::SingleGPUGenJob(pGPUReq));
|
||||
|
@ -630,13 +639,11 @@ void GasGiant::Update()
|
|||
{
|
||||
PROFILE_SCOPED()
|
||||
// assuming that we haven't already generated the texture from the render call.
|
||||
if( m_timeDelay > 0.0f )
|
||||
{
|
||||
if (m_timeDelay > 0.0f) {
|
||||
m_timeDelay -= Pi::game->GetTimeStep();
|
||||
if( m_timeDelay <= 0.0001f && !m_surfaceTexture.Valid() )
|
||||
{
|
||||
if (m_timeDelay <= 0.0001f && !m_surfaceTexture.Valid()) {
|
||||
// Use the fact that we have a patch as a latch to prevent repeat generation requests.
|
||||
if( m_patches[0].get() )
|
||||
if (m_patches[0].get())
|
||||
return;
|
||||
|
||||
BuildFirstPatches();
|
||||
|
@ -648,11 +655,9 @@ void GasGiant::Update()
|
|||
void GasGiant::Render(Graphics::Renderer *renderer, const matrix4x4d &modelView, vector3d campos, const float radius, const std::vector<Camera::Shadow> &shadows)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
if( !m_surfaceTexture.Valid() )
|
||||
{
|
||||
if (!m_surfaceTexture.Valid()) {
|
||||
// Use the fact that we have a patch as a latch to prevent repeat generation requests.
|
||||
if( !m_patches[0].get() )
|
||||
{
|
||||
if (!m_patches[0].get()) {
|
||||
BuildFirstPatches();
|
||||
}
|
||||
}
|
||||
|
@ -668,7 +673,7 @@ void GasGiant::Render(Graphics::Renderer *renderer, const matrix4x4d &modelView,
|
|||
matrix4x4d proj;
|
||||
matrix4x4ftod(renderer->GetCurrentModelView(), modv);
|
||||
matrix4x4ftod(renderer->GetCurrentProjection(), proj);
|
||||
Graphics::Frustum frustum( modv, proj );
|
||||
Graphics::Frustum frustum(modv, proj);
|
||||
|
||||
// no frustum test of entire gasSphere, since Space::Render does this
|
||||
// for each body using its GetBoundingRadius() value
|
||||
|
@ -694,7 +699,7 @@ void GasGiant::Render(Graphics::Renderer *renderer, const matrix4x4d &modelView,
|
|||
// make atmosphere sphere slightly bigger than required so
|
||||
// that the edges of the pixel shader atmosphere jizz doesn't
|
||||
// show ugly polygonal angles
|
||||
DrawAtmosphereSurface(renderer, trans, campos, m_materialParameters.atmosphere.atmosRadius*1.01, m_atmosRenderState, m_atmosphereMaterial);
|
||||
DrawAtmosphereSurface(renderer, trans, campos, m_materialParameters.atmosphere.atmosRadius * 1.01, m_atmosRenderState, m_atmosphereMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -706,7 +711,7 @@ void GasGiant::Render(Graphics::Renderer *renderer, const matrix4x4d &modelView,
|
|||
{
|
||||
// give planet some ambient lighting if the viewer is close to it
|
||||
double camdist = campos.Length();
|
||||
camdist = 0.1 / (camdist*camdist);
|
||||
camdist = 0.1 / (camdist * camdist);
|
||||
// why the fuck is this returning 0.1 when we are sat on the planet??
|
||||
// JJ: Because campos is relative to a unit-radius planet - 1.0 at the surface
|
||||
// XXX oh well, it is the value we want anyway...
|
||||
|
@ -718,7 +723,7 @@ void GasGiant::Render(Graphics::Renderer *renderer, const matrix4x4d &modelView,
|
|||
|
||||
renderer->SetTransform(modelView);
|
||||
|
||||
for (int i=0; i<NUM_PATCHES; i++) {
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
m_patches[i]->Render(renderer, campos, modelView, frustum);
|
||||
}
|
||||
|
||||
|
@ -773,7 +778,7 @@ void GasGiant::SetUpMaterials()
|
|||
void GasGiant::BuildFirstPatches()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
if( s_patchContext.Get() == nullptr ) {
|
||||
if (s_patchContext.Get() == nullptr) {
|
||||
s_patchContext.Reset(new GasPatchContext(127));
|
||||
}
|
||||
|
||||
|
@ -802,10 +807,10 @@ void GasGiant::Init()
|
|||
SplitData(cfg.String("texture_size_3"), s_texture_size_cpu[3], s_texture_size_gpu[3], s_noiseOctaves[3]);
|
||||
SplitData(cfg.String("texture_size_4"), s_texture_size_cpu[4], s_texture_size_gpu[4], s_noiseOctaves[4]);
|
||||
|
||||
s_initialCPUDelayTime = Clamp(cfg.Float("cpu_delay_time", 60.0f), 0.0f, 120.0f);
|
||||
s_initialGPUDelayTime = Clamp(cfg.Float("gpu_delay_time", 5.0f), 0.0f, 120.0f);
|
||||
s_initialCPUDelayTime = Clamp(cfg.Float("cpu_delay_time", 60.0f), 0.0f, 120.0f);
|
||||
s_initialGPUDelayTime = Clamp(cfg.Float("gpu_delay_time", 5.0f), 0.0f, 120.0f);
|
||||
|
||||
if( s_patchContext.Get() == nullptr ) {
|
||||
if (s_patchContext.Get() == nullptr) {
|
||||
s_patchContext.Reset(new GasPatchContext(127));
|
||||
}
|
||||
CreateRenderTarget(s_texture_size_gpu[Pi::detail.planets], s_texture_size_gpu[Pi::detail.planets]);
|
||||
|
@ -817,7 +822,8 @@ void GasGiant::Uninit()
|
|||
}
|
||||
|
||||
//static
|
||||
void GasGiant::CreateRenderTarget(const Uint16 width, const Uint16 height) {
|
||||
void GasGiant::CreateRenderTarget(const Uint16 width, const Uint16 height)
|
||||
{
|
||||
/* @fluffyfreak here's a rendertarget implementation you can use for oculusing and other things. It's pretty simple:
|
||||
- fill out a RenderTargetDesc struct and call Renderer::CreateRenderTarget
|
||||
- pass target to Renderer::SetRenderTarget to start rendering to texture
|
||||
|
@ -828,7 +834,7 @@ void GasGiant::CreateRenderTarget(const Uint16 width, const Uint16 height) {
|
|||
In that case, leave the color format to NONE so the initial texture is not created, then use SetColorTexture to attach your own.
|
||||
*/
|
||||
Graphics::RenderStateDesc rsd;
|
||||
rsd.depthTest = false;
|
||||
rsd.depthTest = false;
|
||||
rsd.depthWrite = false;
|
||||
rsd.blendMode = Graphics::BLEND_ALPHA;
|
||||
s_quadRenderState = Pi::renderer->CreateRenderState(rsd);
|
||||
|
@ -838,8 +844,8 @@ void GasGiant::CreateRenderTarget(const Uint16 width, const Uint16 height) {
|
|||
Graphics::RenderTargetDesc rtDesc(
|
||||
width,
|
||||
height,
|
||||
Graphics::TEXTURE_NONE, // don't create a texture
|
||||
Graphics::TEXTURE_NONE, // don't create a depth buffer
|
||||
Graphics::TEXTURE_NONE, // don't create a texture
|
||||
Graphics::TEXTURE_NONE, // don't create a depth buffer
|
||||
false);
|
||||
s_renderTarget = Pi::renderer->CreateRenderTarget(rtDesc);
|
||||
}
|
||||
|
@ -851,11 +857,13 @@ void GasGiant::SetRenderTargetCubemap(const Uint32 face, Graphics::Texture *pTex
|
|||
}
|
||||
|
||||
//static
|
||||
void GasGiant::BeginRenderTarget() {
|
||||
void GasGiant::BeginRenderTarget()
|
||||
{
|
||||
Pi::renderer->SetRenderTarget(s_renderTarget);
|
||||
}
|
||||
|
||||
//static
|
||||
void GasGiant::EndRenderTarget() {
|
||||
void GasGiant::EndRenderTarget()
|
||||
{
|
||||
Pi::renderer->SetRenderTarget(nullptr);
|
||||
}
|
||||
|
|
|
@ -6,19 +6,21 @@
|
|||
|
||||
#include <SDL_stdinc.h>
|
||||
|
||||
#include "vector3.h"
|
||||
#include "Random.h"
|
||||
#include "BaseSphere.h"
|
||||
#include "Camera.h"
|
||||
#include "GasGiantJobs.h"
|
||||
#include "JobQueue.h"
|
||||
#include "Random.h"
|
||||
#include "graphics/Drawables.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "terrain/Terrain.h"
|
||||
#include "BaseSphere.h"
|
||||
#include "JobQueue.h"
|
||||
#include "GasGiantJobs.h"
|
||||
#include "vector3.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
namespace Graphics { class Renderer; }
|
||||
namespace Graphics {
|
||||
class Renderer;
|
||||
}
|
||||
class SystemBody;
|
||||
class GasGiant;
|
||||
class GasPatch;
|
||||
|
@ -26,7 +28,7 @@ class GasPatchContext;
|
|||
namespace {
|
||||
class STextureFaceResult;
|
||||
class SGPUGenResult;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
#define NUM_PATCHES 6
|
||||
|
||||
|
@ -53,7 +55,7 @@ public:
|
|||
static void OnChangeDetailLevel();
|
||||
|
||||
static void CreateRenderTarget(const Uint16 width, const Uint16 height);
|
||||
static void SetRenderTargetCubemap(const Uint32, Graphics::Texture*, const bool unBind = true);
|
||||
static void SetRenderTargetCubemap(const Uint32, Graphics::Texture *, const bool unBind = true);
|
||||
static void BeginRenderTarget();
|
||||
static void EndRenderTarget();
|
||||
|
||||
|
|
|
@ -1,43 +1,46 @@
|
|||
// Copyright © 2008-2015 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "GasGiant.h"
|
||||
#include "GasGiantJobs.h"
|
||||
#include "perlin.h"
|
||||
#include "Pi.h"
|
||||
#include "Game.h"
|
||||
#include "GasGiant.h"
|
||||
#include "Pi.h"
|
||||
#include "RefCounted.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/opengl/GenGasGiantColourMaterial.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/Frustum.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/TextureBuilder.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "graphics/Types.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "graphics/opengl/GenGasGiantColourMaterial.h"
|
||||
#include "libs.h"
|
||||
#include "perlin.h"
|
||||
#include "vcacheopt/vcacheopt.h"
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
namespace GasGiantJobs
|
||||
{
|
||||
namespace GasGiantJobs {
|
||||
static const vector3d s_patchFaces[NUM_PATCHES][4] =
|
||||
{
|
||||
{ p5, p1, p4, p8 }, // +x
|
||||
{ p2, p6, p7, p3 }, // -x
|
||||
{
|
||||
{ p5, p1, p4, p8 }, // +x
|
||||
{ p2, p6, p7, p3 }, // -x
|
||||
|
||||
{ p2, p1, p5, p6 }, // +y
|
||||
{ p7, p8, p4, p3 }, // -y
|
||||
{ p2, p1, p5, p6 }, // +y
|
||||
{ p7, p8, p4, p3 }, // -y
|
||||
|
||||
{ p6, p5, p8, p7 }, // +z - NB: these are actually reversed!
|
||||
{ p1, p2, p3, p4 } // -z
|
||||
};
|
||||
const vector3d& GetPatchFaces(const Uint32 patch,const Uint32 face) { return s_patchFaces[patch][face]; }
|
||||
{ p6, p5, p8, p7 }, // +z - NB: these are actually reversed!
|
||||
{ p1, p2, p3, p4 } // -z
|
||||
};
|
||||
const vector3d &GetPatchFaces(const Uint32 patch, const Uint32 face) { return s_patchFaces[patch][face]; }
|
||||
|
||||
STextureFaceRequest::STextureFaceRequest(const vector3d *v_, const SystemPath &sysPath_, const Sint32 face_, const Sint32 uvDIMs_, Terrain *pTerrain_) :
|
||||
corners(v_), sysPath(sysPath_), face(face_), uvDIMs(uvDIMs_), pTerrain(pTerrain_)
|
||||
corners(v_),
|
||||
sysPath(sysPath_),
|
||||
face(face_),
|
||||
uvDIMs(uvDIMs_),
|
||||
pTerrain(pTerrain_)
|
||||
{
|
||||
colors = new Color[NumTexels()];
|
||||
}
|
||||
|
@ -49,10 +52,10 @@ namespace GasGiantJobs
|
|||
PROFILE_SCOPED()
|
||||
//MsgTimer timey;
|
||||
|
||||
assert( corners != nullptr );
|
||||
double fracStep = 1.0 / double(UVDims()-1);
|
||||
for( Sint32 v=0; v<UVDims(); v++ ) {
|
||||
for( Sint32 u=0; u<UVDims(); u++ ) {
|
||||
assert(corners != nullptr);
|
||||
double fracStep = 1.0 / double(UVDims() - 1);
|
||||
for (Sint32 v = 0; v < UVDims(); v++) {
|
||||
for (Sint32 u = 0; u < UVDims(); u++) {
|
||||
// where in this row & colum are we now.
|
||||
const double ustep = double(u) * fracStep;
|
||||
const double vstep = double(v) * fracStep;
|
||||
|
@ -63,7 +66,7 @@ namespace GasGiantJobs
|
|||
const vector3d colour = pTerrain->GetColor(p, 0.0, p);
|
||||
|
||||
// convert to ubyte and store
|
||||
Color* col = colors + (u + (v * UVDims()));
|
||||
Color *col = colors + (u + (v * UVDims()));
|
||||
col[0].r = Uint8(colour.x * 255.0);
|
||||
col[0].g = Uint8(colour.y * 255.0);
|
||||
col[0].b = Uint8(colour.z * 255.0);
|
||||
|
@ -80,7 +83,7 @@ namespace GasGiantJobs
|
|||
SingleTextureFaceJob::~SingleTextureFaceJob()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
if(mpResults) {
|
||||
if (mpResults) {
|
||||
mpResults->OnCancel();
|
||||
delete mpResults;
|
||||
mpResults = nullptr;
|
||||
|
@ -103,7 +106,7 @@ namespace GasGiantJobs
|
|||
void SingleTextureFaceJob::OnFinish() // runs in primary thread of the context
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
GasGiant::OnAddTextureFaceResult( mData->SysPath(), mpResults );
|
||||
GasGiant::OnAddTextureFaceResult(mData->SysPath(), mpResults);
|
||||
mpResults = nullptr;
|
||||
}
|
||||
|
||||
|
@ -151,9 +154,9 @@ namespace GasGiantJobs
|
|||
|
||||
Graphics::VertexArray vertices(Graphics::ATTRIB_POSITION | Graphics::ATTRIB_UV0);
|
||||
|
||||
vertices.Add(vector3f(0.0f, 0.0f, 0.0f), vector2f(0.0f, texSize.y));
|
||||
vertices.Add(vector3f(0.0f, size.y, 0.0f), vector2f(0.0f, 0.0f));
|
||||
vertices.Add(vector3f(size.x, 0.0f, 0.0f), vector2f(texSize.x, texSize.y));
|
||||
vertices.Add(vector3f(0.0f, 0.0f, 0.0f), vector2f(0.0f, texSize.y));
|
||||
vertices.Add(vector3f(0.0f, size.y, 0.0f), vector2f(0.0f, 0.0f));
|
||||
vertices.Add(vector3f(size.x, 0.0f, 0.0f), vector2f(texSize.x, texSize.y));
|
||||
vertices.Add(vector3f(size.x, size.y, 0.0f), vector2f(texSize.x, 0.0f));
|
||||
|
||||
//Create vtx & index buffers and copy data
|
||||
|
@ -168,14 +171,21 @@ namespace GasGiantJobs
|
|||
m_vertexBuffer->Populate(vertices);
|
||||
}
|
||||
|
||||
void GenFaceQuad::Draw(Graphics::Renderer *r) {
|
||||
void GenFaceQuad::Draw(Graphics::Renderer *r)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
r->DrawBuffer(m_vertexBuffer.get(), m_renderState, m_material.get(), Graphics::TRIANGLE_STRIP);
|
||||
}
|
||||
|
||||
// ********************************************************************************
|
||||
SGPUGenRequest::SGPUGenRequest(const SystemPath &sysPath_, const Sint32 uvDIMs_, Terrain *pTerrain_, const float planetRadius_, const float hueAdjust_, GenFaceQuad* pQuad_, Graphics::Texture *pTex_) :
|
||||
m_texture(pTex_), sysPath(sysPath_), uvDIMs(uvDIMs_), pTerrain(pTerrain_), planetRadius(planetRadius_), hueAdjust(hueAdjust_), pQuad(pQuad_)
|
||||
SGPUGenRequest::SGPUGenRequest(const SystemPath &sysPath_, const Sint32 uvDIMs_, Terrain *pTerrain_, const float planetRadius_, const float hueAdjust_, GenFaceQuad *pQuad_, Graphics::Texture *pTex_) :
|
||||
m_texture(pTex_),
|
||||
sysPath(sysPath_),
|
||||
uvDIMs(uvDIMs_),
|
||||
pTerrain(pTerrain_),
|
||||
planetRadius(planetRadius_),
|
||||
hueAdjust(hueAdjust_),
|
||||
pQuad(pQuad_)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
assert(m_texture.Valid());
|
||||
|
@ -184,12 +194,12 @@ namespace GasGiantJobs
|
|||
void SGPUGenRequest::SetupMaterialParams(const int face)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
m_specialParams.v = &GetPatchFaces(face,0);
|
||||
m_specialParams.v = &GetPatchFaces(face, 0);
|
||||
m_specialParams.fracStep = 1.0f / float(uvDIMs);
|
||||
m_specialParams.planetRadius = planetRadius;
|
||||
m_specialParams.time = 0.0f;
|
||||
|
||||
for(Uint32 i=0; i<3; i++) {
|
||||
for (Uint32 i = 0; i < 3; i++) {
|
||||
m_specialParams.frequency[i] = float(pTerrain->GetFracDef(i).frequency);
|
||||
}
|
||||
|
||||
|
@ -199,23 +209,31 @@ namespace GasGiantJobs
|
|||
}
|
||||
|
||||
// ********************************************************************************
|
||||
void SGPUGenResult::addResult(Graphics::Texture *t_, Sint32 uvDims_) {
|
||||
void SGPUGenResult::addResult(Graphics::Texture *t_, Sint32 uvDims_)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
mData = SGPUGenData(t_, uvDims_);
|
||||
}
|
||||
|
||||
void SGPUGenResult::OnCancel() {
|
||||
if( mData.texture ) { mData.texture.Reset(); }
|
||||
void SGPUGenResult::OnCancel()
|
||||
{
|
||||
if (mData.texture) {
|
||||
mData.texture.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ********************************************************************************
|
||||
// Overloaded JobGPU class to handle generating the mesh for each patch
|
||||
// ********************************************************************************
|
||||
SingleGPUGenJob::SingleGPUGenJob(SGPUGenRequest *data) : mData(data), mpResults(nullptr) { /* empty */ }
|
||||
SingleGPUGenJob::SingleGPUGenJob(SGPUGenRequest *data) :
|
||||
mData(data),
|
||||
mpResults(nullptr)
|
||||
{ /* empty */
|
||||
}
|
||||
SingleGPUGenJob::~SingleGPUGenJob()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
if(mpResults) {
|
||||
if (mpResults) {
|
||||
mpResults->OnCancel();
|
||||
delete mpResults;
|
||||
mpResults = nullptr;
|
||||
|
@ -241,14 +259,13 @@ namespace GasGiantJobs
|
|||
}
|
||||
|
||||
GasGiant::BeginRenderTarget();
|
||||
for( Uint32 iFace=0; iFace<NUM_PATCHES; iFace++ )
|
||||
{
|
||||
for (Uint32 iFace = 0; iFace < NUM_PATCHES; iFace++) {
|
||||
// render the scene
|
||||
GasGiant::SetRenderTargetCubemap(iFace, mData->Texture());
|
||||
Pi::renderer->BeginFrame();
|
||||
|
||||
// draw to the texture here
|
||||
mData->SetupMaterialParams( iFace );
|
||||
mData->SetupMaterialParams(iFace);
|
||||
mData->Quad()->Draw(Pi::renderer);
|
||||
|
||||
Pi::renderer->EndFrame();
|
||||
|
@ -266,7 +283,7 @@ namespace GasGiantJobs
|
|||
|
||||
// add this patches data
|
||||
SGPUGenResult *sr = new SGPUGenResult();
|
||||
sr->addResult( mData->Texture(), mData->UVDims() );
|
||||
sr->addResult(mData->Texture(), mData->UVDims());
|
||||
|
||||
// store the result
|
||||
mpResults = sr;
|
||||
|
@ -277,8 +294,7 @@ namespace GasGiantJobs
|
|||
void SingleGPUGenJob::OnFinish() // runs in primary thread of the context
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
GasGiant::OnAddGPUGenResult( mData->SysPath(), mpResults );
|
||||
GasGiant::OnAddGPUGenResult(mData->SysPath(), mpResults);
|
||||
mpResults = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace GasGiantJobs
|
||||
|
|
|
@ -6,22 +6,21 @@
|
|||
|
||||
#include <SDL_stdinc.h>
|
||||
|
||||
#include "vector3.h"
|
||||
#include "Random.h"
|
||||
#include "Camera.h"
|
||||
#include "graphics/Drawables.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/opengl/GenGasGiantColourMaterial.h"
|
||||
#include "graphics/TextureBuilder.h"
|
||||
#include "terrain/Terrain.h"
|
||||
#include "BaseSphere.h"
|
||||
#include "Camera.h"
|
||||
#include "GeoSphere.h"
|
||||
#include "JobQueue.h"
|
||||
#include "Random.h"
|
||||
#include "graphics/Drawables.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/TextureBuilder.h"
|
||||
#include "graphics/opengl/GenGasGiantColourMaterial.h"
|
||||
#include "terrain/Terrain.h"
|
||||
#include "vector3.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
namespace GasGiantJobs
|
||||
{
|
||||
namespace GasGiantJobs {
|
||||
//#define DUMP_PARAMS 1
|
||||
|
||||
// generate root face patches of the cube/sphere
|
||||
|
@ -34,7 +33,7 @@ namespace GasGiantJobs
|
|||
static const vector3d p7 = (vector3d(-1, -1, -1)).Normalized();
|
||||
static const vector3d p8 = (vector3d(1, -1, -1)).Normalized();
|
||||
|
||||
const vector3d& GetPatchFaces(const Uint32 patch,const Uint32 face);
|
||||
const vector3d &GetPatchFaces(const Uint32 patch, const Uint32 face);
|
||||
|
||||
class STextureFaceRequest {
|
||||
public:
|
||||
|
@ -46,18 +45,19 @@ namespace GasGiantJobs
|
|||
|
||||
Sint32 Face() const { return face; }
|
||||
inline Sint32 UVDims() const { return uvDIMs; }
|
||||
Color* Colors() const { return colors; }
|
||||
const SystemPath& SysPath() const { return sysPath; }
|
||||
Color *Colors() const { return colors; }
|
||||
const SystemPath &SysPath() const { return sysPath; }
|
||||
|
||||
protected:
|
||||
// deliberately prevent copy constructor access
|
||||
STextureFaceRequest(const STextureFaceRequest &r) = delete;
|
||||
|
||||
inline Sint32 NumTexels() const { return uvDIMs*uvDIMs; }
|
||||
inline Sint32 NumTexels() const { return uvDIMs * uvDIMs; }
|
||||
|
||||
// in patch surface coords, [0,1]
|
||||
inline vector3d GetSpherePoint(const double x, const double y) const {
|
||||
return (corners[0] + x*(1.0 - y)*(corners[1] - corners[0]) + x*y*(corners[2] - corners[0]) + (1.0 - x)*y*(corners[3] - corners[0])).Normalized();
|
||||
inline vector3d GetSpherePoint(const double x, const double y) const
|
||||
{
|
||||
return (corners[0] + x * (1.0 - y) * (corners[1] - corners[0]) + x * y * (corners[2] - corners[0]) + (1.0 - x) * y * (corners[3] - corners[0])).Normalized();
|
||||
}
|
||||
|
||||
// these are created with the request and are given to the resulting patches
|
||||
|
@ -74,24 +74,34 @@ namespace GasGiantJobs
|
|||
public:
|
||||
struct STextureFaceData {
|
||||
STextureFaceData() {}
|
||||
STextureFaceData(Color *c_, Sint32 uvDims_) : colors(c_), uvDims(uvDims_) {}
|
||||
STextureFaceData(const STextureFaceData &r) : colors(r.colors), uvDims(r.uvDims) {}
|
||||
STextureFaceData(Color *c_, Sint32 uvDims_) :
|
||||
colors(c_),
|
||||
uvDims(uvDims_) {}
|
||||
STextureFaceData(const STextureFaceData &r) :
|
||||
colors(r.colors),
|
||||
uvDims(r.uvDims) {}
|
||||
Color *colors;
|
||||
Sint32 uvDims;
|
||||
};
|
||||
|
||||
STextureFaceResult(const int32_t face_) : mFace(face_) {}
|
||||
STextureFaceResult(const int32_t face_) :
|
||||
mFace(face_) {}
|
||||
|
||||
void addResult(Color *c_, Sint32 uvDims_) {
|
||||
void addResult(Color *c_, Sint32 uvDims_)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
mData = STextureFaceData(c_, uvDims_);
|
||||
}
|
||||
|
||||
inline const STextureFaceData& data() const { return mData; }
|
||||
inline const STextureFaceData &data() const { return mData; }
|
||||
inline int32_t face() const { return mFace; }
|
||||
|
||||
void OnCancel() {
|
||||
if (mData.colors) { delete[] mData.colors; mData.colors = NULL; }
|
||||
void OnCancel()
|
||||
{
|
||||
if (mData.colors) {
|
||||
delete[] mData.colors;
|
||||
mData.colors = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -105,10 +115,13 @@ namespace GasGiantJobs
|
|||
// ********************************************************************************
|
||||
// Overloaded PureJob class to handle generating the mesh for each patch
|
||||
// ********************************************************************************
|
||||
class SingleTextureFaceJob : public Job
|
||||
{
|
||||
class SingleTextureFaceJob : public Job {
|
||||
public:
|
||||
SingleTextureFaceJob(STextureFaceRequest *data) : mData(data), mpResults(nullptr) { /* empty */ }
|
||||
SingleTextureFaceJob(STextureFaceRequest *data) :
|
||||
mData(data),
|
||||
mpResults(nullptr)
|
||||
{ /* empty */
|
||||
}
|
||||
virtual ~SingleTextureFaceJob();
|
||||
|
||||
virtual void OnRun();
|
||||
|
@ -130,8 +143,13 @@ namespace GasGiantJobs
|
|||
GenFaceQuad(Graphics::Renderer *r, const vector2f &size, Graphics::RenderState *state, const Uint32 GGQuality);
|
||||
virtual void Draw(Graphics::Renderer *r);
|
||||
|
||||
void SetMaterial(Graphics::Material *mat) { assert(mat); m_material.reset(mat); }
|
||||
Graphics::Material* GetMaterial() const { return m_material.get(); }
|
||||
void SetMaterial(Graphics::Material *mat)
|
||||
{
|
||||
assert(mat);
|
||||
m_material.reset(mat);
|
||||
}
|
||||
Graphics::Material *GetMaterial() const { return m_material.get(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<Graphics::Material> m_material;
|
||||
std::unique_ptr<Graphics::VertexBuffer> m_vertexBuffer;
|
||||
|
@ -141,19 +159,19 @@ namespace GasGiantJobs
|
|||
// ********************************************************************************
|
||||
class SGPUGenRequest {
|
||||
public:
|
||||
SGPUGenRequest(const SystemPath &sysPath_, const Sint32 uvDIMs_, Terrain *pTerrain_, const float planetRadius_, const float hueAdjust_, GenFaceQuad* pQuad_, Graphics::Texture *pTex_);
|
||||
SGPUGenRequest(const SystemPath &sysPath_, const Sint32 uvDIMs_, Terrain *pTerrain_, const float planetRadius_, const float hueAdjust_, GenFaceQuad *pQuad_, Graphics::Texture *pTex_);
|
||||
|
||||
inline Sint32 UVDims() const { return uvDIMs; }
|
||||
Graphics::Texture* Texture() const { return m_texture.Get(); }
|
||||
GenFaceQuad* Quad() const { return pQuad; }
|
||||
const SystemPath& SysPath() const { return sysPath; }
|
||||
Graphics::Texture *Texture() const { return m_texture.Get(); }
|
||||
GenFaceQuad *Quad() const { return pQuad; }
|
||||
const SystemPath &SysPath() const { return sysPath; }
|
||||
void SetupMaterialParams(const int face);
|
||||
|
||||
protected:
|
||||
// deliberately prevent copy constructor access
|
||||
SGPUGenRequest(const SGPUGenRequest &r) = delete;
|
||||
|
||||
inline Sint32 NumTexels() const { return uvDIMs*uvDIMs; }
|
||||
inline Sint32 NumTexels() const { return uvDIMs * uvDIMs; }
|
||||
|
||||
// this is created with the request and are given to the resulting patches
|
||||
RefCountedPtr<Graphics::Texture> m_texture;
|
||||
|
@ -163,7 +181,7 @@ namespace GasGiantJobs
|
|||
Terrain *pTerrain;
|
||||
const float planetRadius;
|
||||
const float hueAdjust;
|
||||
GenFaceQuad* pQuad;
|
||||
GenFaceQuad *pQuad;
|
||||
Graphics::GenGasGiantColourMaterialParameters m_specialParams;
|
||||
};
|
||||
|
||||
|
@ -172,8 +190,12 @@ namespace GasGiantJobs
|
|||
public:
|
||||
struct SGPUGenData {
|
||||
SGPUGenData() {}
|
||||
SGPUGenData(Graphics::Texture *t_, Sint32 uvDims_) : texture(t_), uvDims(uvDims_) {}
|
||||
SGPUGenData(const SGPUGenData &r) : texture(r.texture), uvDims(r.uvDims) {}
|
||||
SGPUGenData(Graphics::Texture *t_, Sint32 uvDims_) :
|
||||
texture(t_),
|
||||
uvDims(uvDims_) {}
|
||||
SGPUGenData(const SGPUGenData &r) :
|
||||
texture(r.texture),
|
||||
uvDims(r.uvDims) {}
|
||||
RefCountedPtr<Graphics::Texture> texture;
|
||||
Sint32 uvDims;
|
||||
};
|
||||
|
@ -182,7 +204,7 @@ namespace GasGiantJobs
|
|||
|
||||
void addResult(Graphics::Texture *t_, Sint32 uvDims_);
|
||||
|
||||
inline const SGPUGenData& data() const { return mData; }
|
||||
inline const SGPUGenData &data() const { return mData; }
|
||||
|
||||
void OnCancel();
|
||||
|
||||
|
@ -196,8 +218,7 @@ namespace GasGiantJobs
|
|||
// ********************************************************************************
|
||||
// Overloaded JobGPU class to handle generating the mesh for each patch
|
||||
// ********************************************************************************
|
||||
class SingleGPUGenJob : public Job
|
||||
{
|
||||
class SingleGPUGenJob : public Job {
|
||||
public:
|
||||
SingleGPUGenJob(SGPUGenRequest *data);
|
||||
virtual ~SingleGPUGenJob();
|
||||
|
@ -214,7 +235,6 @@ namespace GasGiantJobs
|
|||
std::unique_ptr<SGPUGenRequest> mData;
|
||||
SGPUGenResult *mpResults;
|
||||
};
|
||||
};
|
||||
|
||||
}; // namespace GasGiantJobs
|
||||
|
||||
#endif /* _GASGIANTJOBS_H */
|
||||
|
|
186
src/GeoPatch.cpp
186
src/GeoPatch.cpp
|
@ -1,58 +1,67 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "GeoPatchContext.h"
|
||||
#include "GeoPatch.h"
|
||||
#include "GeoPatchContext.h"
|
||||
#include "GeoPatchJobs.h"
|
||||
#include "GeoSphere.h"
|
||||
#include "perlin.h"
|
||||
#include "MathUtil.h"
|
||||
#include "Pi.h"
|
||||
#include "RefCounted.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "Sphere.h"
|
||||
#include "graphics/Frustum.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "MathUtil.h"
|
||||
#include "Sphere.h"
|
||||
#include "libs.h"
|
||||
#include "perlin.h"
|
||||
#include "vcacheopt/vcacheopt.h"
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
// tri edge lengths
|
||||
static const double GEOPATCH_SUBDIVIDE_AT_CAMDIST = 5.0;
|
||||
|
||||
GeoPatch::GeoPatch(const RefCountedPtr<GeoPatchContext> &ctx_, GeoSphere *gs,
|
||||
const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_,
|
||||
const int depth, const GeoPatchID &ID_)
|
||||
: ctx(ctx_), v0(v0_), v1(v1_), v2(v2_), v3(v3_),
|
||||
heights(nullptr), normals(nullptr), colors(nullptr),
|
||||
parent(nullptr), geosphere(gs),
|
||||
m_depth(depth), mPatchID(ID_),
|
||||
const int depth, const GeoPatchID &ID_) :
|
||||
ctx(ctx_),
|
||||
v0(v0_),
|
||||
v1(v1_),
|
||||
v2(v2_),
|
||||
v3(v3_),
|
||||
heights(nullptr),
|
||||
normals(nullptr),
|
||||
colors(nullptr),
|
||||
parent(nullptr),
|
||||
geosphere(gs),
|
||||
m_depth(depth),
|
||||
mPatchID(ID_),
|
||||
mHasJobRequest(false)
|
||||
{
|
||||
|
||||
clipCentroid = (v0+v1+v2+v3) * 0.25;
|
||||
clipCentroid = (v0 + v1 + v2 + v3) * 0.25;
|
||||
centroid = clipCentroid.Normalized();
|
||||
clipRadius = 0.0;
|
||||
clipRadius = std::max(clipRadius, (v0-clipCentroid).Length());
|
||||
clipRadius = std::max(clipRadius, (v1-clipCentroid).Length());
|
||||
clipRadius = std::max(clipRadius, (v2-clipCentroid).Length());
|
||||
clipRadius = std::max(clipRadius, (v3-clipCentroid).Length());
|
||||
clipRadius = std::max(clipRadius, (v0 - clipCentroid).Length());
|
||||
clipRadius = std::max(clipRadius, (v1 - clipCentroid).Length());
|
||||
clipRadius = std::max(clipRadius, (v2 - clipCentroid).Length());
|
||||
clipRadius = std::max(clipRadius, (v3 - clipCentroid).Length());
|
||||
double distMult;
|
||||
if (geosphere->GetSystemBody()->GetType() < SystemBody::TYPE_PLANET_ASTEROID) {
|
||||
distMult = 10.0 / Clamp(depth, 1, 10);
|
||||
} else {
|
||||
distMult = 5.0 / Clamp(depth, 1, 5);
|
||||
}
|
||||
distMult = 10.0 / Clamp(depth, 1, 10);
|
||||
} else {
|
||||
distMult = 5.0 / Clamp(depth, 1, 5);
|
||||
}
|
||||
m_roughLength = GEOPATCH_SUBDIVIDE_AT_CAMDIST / pow(2.0, depth) * distMult;
|
||||
m_needUpdateVBOs = false;
|
||||
}
|
||||
|
||||
GeoPatch::~GeoPatch() {
|
||||
GeoPatch::~GeoPatch()
|
||||
{
|
||||
mHasJobRequest = false;
|
||||
for (int i=0; i<NUM_KIDS; i++) {
|
||||
for (int i = 0; i < NUM_KIDS; i++) {
|
||||
kids[i].reset();
|
||||
}
|
||||
heights.reset();
|
||||
|
@ -70,18 +79,18 @@ void GeoPatch::UpdateVBOs(Graphics::Renderer *renderer)
|
|||
//create buffer and upload data
|
||||
Graphics::VertexBufferDesc vbd;
|
||||
vbd.attrib[0].semantic = Graphics::ATTRIB_POSITION;
|
||||
vbd.attrib[0].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[0].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[1].semantic = Graphics::ATTRIB_NORMAL;
|
||||
vbd.attrib[1].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[1].format = Graphics::ATTRIB_FORMAT_FLOAT3;
|
||||
vbd.attrib[2].semantic = Graphics::ATTRIB_DIFFUSE;
|
||||
vbd.attrib[2].format = Graphics::ATTRIB_FORMAT_UBYTE4;
|
||||
vbd.attrib[2].format = Graphics::ATTRIB_FORMAT_UBYTE4;
|
||||
vbd.attrib[3].semantic = Graphics::ATTRIB_UV0;
|
||||
vbd.attrib[3].format = Graphics::ATTRIB_FORMAT_FLOAT2;
|
||||
vbd.attrib[3].format = Graphics::ATTRIB_FORMAT_FLOAT2;
|
||||
vbd.numVertices = ctx->NUMVERTICES();
|
||||
vbd.usage = Graphics::BUFFER_USAGE_STATIC;
|
||||
m_vertexBuffer.reset(renderer->CreateVertexBuffer(vbd));
|
||||
|
||||
GeoPatchContext::VBOVertex* VBOVtxPtr = m_vertexBuffer->Map<GeoPatchContext::VBOVertex>(Graphics::BUFFER_MAP_WRITE);
|
||||
GeoPatchContext::VBOVertex *VBOVtxPtr = m_vertexBuffer->Map<GeoPatchContext::VBOVertex>(Graphics::BUFFER_MAP_WRITE);
|
||||
assert(m_vertexBuffer->GetDesc().stride == sizeof(GeoPatchContext::VBOVertex));
|
||||
|
||||
const Sint32 edgeLen = ctx->GetEdgeLen();
|
||||
|
@ -94,8 +103,8 @@ void GeoPatch::UpdateVBOs(Graphics::Renderer *renderer)
|
|||
|
||||
// ----------------------------------------------------
|
||||
// inner loops
|
||||
for (Sint32 y = 1; y<edgeLen-1; y++) {
|
||||
for (Sint32 x = 1; x<edgeLen-1; x++) {
|
||||
for (Sint32 y = 1; y < edgeLen - 1; y++) {
|
||||
for (Sint32 x = 1; x < edgeLen - 1; x++) {
|
||||
const double height = *pHts;
|
||||
minh = std::min(height, minh);
|
||||
const double xFrac = double(x - 1) * frac;
|
||||
|
@ -103,9 +112,9 @@ void GeoPatch::UpdateVBOs(Graphics::Renderer *renderer)
|
|||
const vector3d p((GetSpherePoint(xFrac, yFrac) * (height + 1.0)) - clipCentroid);
|
||||
clipRadius = std::max(clipRadius, p.Length());
|
||||
|
||||
GeoPatchContext::VBOVertex* vtxPtr = &VBOVtxPtr[x + (y*edgeLen)];
|
||||
GeoPatchContext::VBOVertex *vtxPtr = &VBOVtxPtr[x + (y * edgeLen)];
|
||||
vtxPtr->pos = vector3f(p);
|
||||
++pHts; // next height
|
||||
++pHts; // next height
|
||||
|
||||
const vector3f norma(pNorm->Normalized());
|
||||
vtxPtr->norm = norma;
|
||||
|
@ -133,13 +142,13 @@ void GeoPatch::UpdateVBOs(Graphics::Renderer *renderer)
|
|||
// vertical edges
|
||||
// left-edge
|
||||
for (Sint32 y = 1; y < edgeLen - 1; y++) {
|
||||
const Sint32 x = innerLeft-1;
|
||||
const Sint32 x = innerLeft - 1;
|
||||
const double xFrac = double(x - 1) * frac;
|
||||
const double yFrac = double(y - 1) * frac;
|
||||
const vector3d p((GetSpherePoint(xFrac, yFrac) * minhScale) - clipCentroid);
|
||||
|
||||
GeoPatchContext::VBOVertex* vtxPtr = &VBOVtxPtr[outerLeft + (y*edgeLen)];
|
||||
GeoPatchContext::VBOVertex* vtxInr = &VBOVtxPtr[innerLeft + (y*edgeLen)];
|
||||
GeoPatchContext::VBOVertex *vtxPtr = &VBOVtxPtr[outerLeft + (y * edgeLen)];
|
||||
GeoPatchContext::VBOVertex *vtxInr = &VBOVtxPtr[innerLeft + (y * edgeLen)];
|
||||
vtxPtr->pos = vector3f(p);
|
||||
vtxPtr->norm = vtxInr->norm;
|
||||
vtxPtr->col = vtxInr->col;
|
||||
|
@ -147,13 +156,13 @@ void GeoPatch::UpdateVBOs(Graphics::Renderer *renderer)
|
|||
}
|
||||
// right-edge
|
||||
for (Sint32 y = 1; y < edgeLen - 1; y++) {
|
||||
const Sint32 x = innerRight+1;
|
||||
const Sint32 x = innerRight + 1;
|
||||
const double xFrac = double(x - 1) * frac;
|
||||
const double yFrac = double(y - 1) * frac;
|
||||
const vector3d p((GetSpherePoint(xFrac, yFrac) * minhScale) - clipCentroid);
|
||||
|
||||
GeoPatchContext::VBOVertex* vtxPtr = &VBOVtxPtr[outerRight + (y*edgeLen)];
|
||||
GeoPatchContext::VBOVertex* vtxInr = &VBOVtxPtr[innerRight + (y*edgeLen)];
|
||||
GeoPatchContext::VBOVertex *vtxPtr = &VBOVtxPtr[outerRight + (y * edgeLen)];
|
||||
GeoPatchContext::VBOVertex *vtxInr = &VBOVtxPtr[innerRight + (y * edgeLen)];
|
||||
vtxPtr->pos = vector3f(p);
|
||||
vtxPtr->norm = vtxInr->norm;
|
||||
vtxPtr->col = vtxInr->col;
|
||||
|
@ -166,30 +175,28 @@ void GeoPatch::UpdateVBOs(Graphics::Renderer *renderer)
|
|||
const Sint32 outerBottom = edgeLen - 1;
|
||||
// horizontal edges
|
||||
// top-edge
|
||||
for (Sint32 x = 1; x < edgeLen - 1; x++)
|
||||
{
|
||||
const Sint32 y = innerTop-1;
|
||||
for (Sint32 x = 1; x < edgeLen - 1; x++) {
|
||||
const Sint32 y = innerTop - 1;
|
||||
const double xFrac = double(x - 1) * frac;
|
||||
const double yFrac = double(y - 1) * frac;
|
||||
const vector3d p((GetSpherePoint(xFrac, yFrac) * minhScale) - clipCentroid);
|
||||
|
||||
GeoPatchContext::VBOVertex* vtxPtr = &VBOVtxPtr[x + (outerTop*edgeLen)];
|
||||
GeoPatchContext::VBOVertex* vtxInr = &VBOVtxPtr[x + (innerTop*edgeLen)];
|
||||
GeoPatchContext::VBOVertex *vtxPtr = &VBOVtxPtr[x + (outerTop * edgeLen)];
|
||||
GeoPatchContext::VBOVertex *vtxInr = &VBOVtxPtr[x + (innerTop * edgeLen)];
|
||||
vtxPtr->pos = vector3f(p);
|
||||
vtxPtr->norm = vtxInr->norm;
|
||||
vtxPtr->col = vtxInr->col;
|
||||
vtxPtr->uv = vtxInr->uv;
|
||||
}
|
||||
// bottom-edge
|
||||
for (Sint32 x = 1; x < edgeLen - 1; x++)
|
||||
{
|
||||
const Sint32 y = innerBottom+1;
|
||||
for (Sint32 x = 1; x < edgeLen - 1; x++) {
|
||||
const Sint32 y = innerBottom + 1;
|
||||
const double xFrac = double(x - 1) * frac;
|
||||
const double yFrac = double(y - 1) * frac;
|
||||
const vector3d p((GetSpherePoint(xFrac, yFrac) * minhScale) - clipCentroid);
|
||||
|
||||
GeoPatchContext::VBOVertex* vtxPtr = &VBOVtxPtr[x + (outerBottom * edgeLen)];
|
||||
GeoPatchContext::VBOVertex* vtxInr = &VBOVtxPtr[x + (innerBottom * edgeLen)];
|
||||
GeoPatchContext::VBOVertex *vtxPtr = &VBOVtxPtr[x + (outerBottom * edgeLen)];
|
||||
GeoPatchContext::VBOVertex *vtxInr = &VBOVtxPtr[x + (innerBottom * edgeLen)];
|
||||
vtxPtr->pos = vector3f(p);
|
||||
vtxPtr->norm = vtxInr->norm;
|
||||
vtxPtr->col = vtxInr->col;
|
||||
|
@ -199,26 +206,26 @@ void GeoPatch::UpdateVBOs(Graphics::Renderer *renderer)
|
|||
// corners
|
||||
{
|
||||
// top left
|
||||
GeoPatchContext::VBOVertex* tarPtr = &VBOVtxPtr[0];
|
||||
GeoPatchContext::VBOVertex* srcPtr = &VBOVtxPtr[1];
|
||||
GeoPatchContext::VBOVertex *tarPtr = &VBOVtxPtr[0];
|
||||
GeoPatchContext::VBOVertex *srcPtr = &VBOVtxPtr[1];
|
||||
(*tarPtr) = (*srcPtr);
|
||||
}
|
||||
{
|
||||
// top right
|
||||
GeoPatchContext::VBOVertex* tarPtr = &VBOVtxPtr[(edgeLen - 1)];
|
||||
GeoPatchContext::VBOVertex* srcPtr = &VBOVtxPtr[(edgeLen - 2)];
|
||||
GeoPatchContext::VBOVertex *tarPtr = &VBOVtxPtr[(edgeLen - 1)];
|
||||
GeoPatchContext::VBOVertex *srcPtr = &VBOVtxPtr[(edgeLen - 2)];
|
||||
(*tarPtr) = (*srcPtr);
|
||||
}
|
||||
{
|
||||
// bottom left
|
||||
GeoPatchContext::VBOVertex* tarPtr = &VBOVtxPtr[(edgeLen - 1) * edgeLen];
|
||||
GeoPatchContext::VBOVertex* srcPtr = &VBOVtxPtr[(edgeLen - 2) * edgeLen];
|
||||
GeoPatchContext::VBOVertex *tarPtr = &VBOVtxPtr[(edgeLen - 1) * edgeLen];
|
||||
GeoPatchContext::VBOVertex *srcPtr = &VBOVtxPtr[(edgeLen - 2) * edgeLen];
|
||||
(*tarPtr) = (*srcPtr);
|
||||
}
|
||||
{
|
||||
// bottom right
|
||||
GeoPatchContext::VBOVertex* tarPtr = &VBOVtxPtr[(edgeLen - 1) + ((edgeLen - 1) * edgeLen)];
|
||||
GeoPatchContext::VBOVertex* srcPtr = &VBOVtxPtr[(edgeLen - 1) + ((edgeLen - 2) * edgeLen)];
|
||||
GeoPatchContext::VBOVertex *tarPtr = &VBOVtxPtr[(edgeLen - 1) + ((edgeLen - 1) * edgeLen)];
|
||||
GeoPatchContext::VBOVertex *srcPtr = &VBOVtxPtr[(edgeLen - 1) + ((edgeLen - 2) * edgeLen)];
|
||||
(*tarPtr) = (*srcPtr);
|
||||
}
|
||||
|
||||
|
@ -232,7 +239,7 @@ void GeoPatch::UpdateVBOs(Graphics::Renderer *renderer)
|
|||
|
||||
#ifdef DEBUG_BOUNDING_SPHERES
|
||||
RefCountedPtr<Graphics::Material> mat(Pi::renderer->CreateMaterial(Graphics::MaterialDescriptor()));
|
||||
m_boundsphere.reset( new Graphics::Drawables::Sphere3D(Pi::renderer, mat, Pi::renderer->CreateRenderState(Graphics::RenderStateDesc()), 0, clipRadius) );
|
||||
m_boundsphere.reset(new Graphics::Drawables::Sphere3D(Pi::renderer, mat, Pi::renderer->CreateRenderState(Graphics::RenderStateDesc()), 0, clipRadius));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -254,18 +261,19 @@ void GeoPatch::Render(Graphics::Renderer *renderer, const vector3d &campos, cons
|
|||
const vector3d cenDir(clipCentroid.Normalized());
|
||||
const double dotProd = camDirNorm.Dot(cenDir);
|
||||
|
||||
if( dotProd < 0.25 && (camDir.LengthSqr() > (clipRadius*clipRadius)) ) {
|
||||
if (dotProd < 0.25 && (camDir.LengthSqr() > (clipRadius * clipRadius))) {
|
||||
SSphere obj;
|
||||
obj.m_centre = clipCentroid;
|
||||
obj.m_radius = clipRadius;
|
||||
|
||||
if( !s_sph.HorizonCulling(campos, obj) ) {
|
||||
if (!s_sph.HorizonCulling(campos, obj)) {
|
||||
return; // nothing below this patch is visible
|
||||
}
|
||||
}
|
||||
|
||||
if (kids[0]) {
|
||||
for (int i=0; i<NUM_KIDS; i++) kids[i]->Render(renderer, campos, modelView, frustum);
|
||||
for (int i = 0; i < NUM_KIDS; i++)
|
||||
kids[i]->Render(renderer, campos, modelView, frustum);
|
||||
} else if (heights) {
|
||||
RefCountedPtr<Graphics::Material> mat = geosphere->GetSurfaceMaterial();
|
||||
Graphics::RenderState *rs = geosphere->GetSurfRenderState();
|
||||
|
@ -281,7 +289,7 @@ void GeoPatch::Render(Graphics::Renderer *renderer, const vector3d &campos, cons
|
|||
|
||||
renderer->DrawBufferIndexed(m_vertexBuffer.get(), ctx->GetIndexBuffer(), rs, mat.Get());
|
||||
#ifdef DEBUG_BOUNDING_SPHERES
|
||||
if(m_boundsphere.get()) {
|
||||
if (m_boundsphere.get()) {
|
||||
renderer->SetWireFrameMode(true);
|
||||
m_boundsphere->Draw(renderer);
|
||||
renderer->SetWireFrameMode(false);
|
||||
|
@ -294,7 +302,7 @@ void GeoPatch::Render(Graphics::Renderer *renderer, const vector3d &campos, cons
|
|||
void GeoPatch::LODUpdate(const vector3d &campos, const Graphics::Frustum &frustum)
|
||||
{
|
||||
// there should be no LOD update when we have active split requests
|
||||
if(mHasJobRequest)
|
||||
if (mHasJobRequest)
|
||||
return;
|
||||
|
||||
bool canSplit = true;
|
||||
|
@ -305,7 +313,7 @@ void GeoPatch::LODUpdate(const vector3d &campos, const Graphics::Frustum &frustu
|
|||
if (parent) {
|
||||
centroidDist = (campos - centroid).Length();
|
||||
const bool errorSplit = (centroidDist < m_roughLength);
|
||||
if( !(canSplit && (m_depth < std::min(GEOPATCH_MAX_DEPTH, geosphere->GetMaxDepth())) && errorSplit) ) {
|
||||
if (!(canSplit && (m_depth < std::min(GEOPATCH_MAX_DEPTH, geosphere->GetMaxDepth())) && errorSplit)) {
|
||||
canSplit = false;
|
||||
}
|
||||
}
|
||||
|
@ -322,7 +330,7 @@ void GeoPatch::LODUpdate(const vector3d &campos, const Graphics::Frustum &frustu
|
|||
const vector3d cenDir(clipCentroid.Normalized());
|
||||
const double dotProd = camDirNorm.Dot(cenDir);
|
||||
|
||||
if (dotProd < 0.25 && (camDir.LengthSqr() >(clipRadius*clipRadius))) {
|
||||
if (dotProd < 0.25 && (camDir.LengthSqr() > (clipRadius * clipRadius))) {
|
||||
SSphere obj;
|
||||
obj.m_centre = clipCentroid;
|
||||
obj.m_radius = clipRadius;
|
||||
|
@ -337,22 +345,22 @@ void GeoPatch::LODUpdate(const vector3d &campos, const Graphics::Frustum &frustu
|
|||
mHasJobRequest = true;
|
||||
|
||||
SQuadSplitRequest *ssrd = new SQuadSplitRequest(v0, v1, v2, v3, centroid.Normalized(), m_depth,
|
||||
geosphere->GetSystemBody()->GetPath(), mPatchID, ctx->GetEdgeLen()-2,
|
||||
ctx->GetFrac(), geosphere->GetTerrain());
|
||||
geosphere->GetSystemBody()->GetPath(), mPatchID, ctx->GetEdgeLen() - 2,
|
||||
ctx->GetFrac(), geosphere->GetTerrain());
|
||||
|
||||
// add to the GeoSphere to be processed at end of all LODUpdate requests
|
||||
geosphere->AddQuadSplitRequest(centroidDist, ssrd, this);
|
||||
} else {
|
||||
for (int i=0; i<NUM_KIDS; i++) {
|
||||
for (int i = 0; i < NUM_KIDS; i++) {
|
||||
kids[i]->LODUpdate(campos, frustum);
|
||||
}
|
||||
}
|
||||
} else if (canMerge) {
|
||||
for (int i=0; i<NUM_KIDS; i++) {
|
||||
for (int i = 0; i < NUM_KIDS; i++) {
|
||||
canMerge &= kids[i]->canBeMerged();
|
||||
}
|
||||
if( canMerge ) {
|
||||
for (int i=0; i<NUM_KIDS; i++) {
|
||||
if (canMerge) {
|
||||
for (int i = 0; i < NUM_KIDS; i++) {
|
||||
kids[i].reset();
|
||||
}
|
||||
}
|
||||
|
@ -361,11 +369,11 @@ void GeoPatch::LODUpdate(const vector3d &campos, const Graphics::Frustum &frustu
|
|||
|
||||
void GeoPatch::RequestSinglePatch()
|
||||
{
|
||||
if( !heights ) {
|
||||
assert(!mHasJobRequest);
|
||||
if (!heights) {
|
||||
assert(!mHasJobRequest);
|
||||
mHasJobRequest = true;
|
||||
SSingleSplitRequest *ssrd = new SSingleSplitRequest(v0, v1, v2, v3, centroid.Normalized(), m_depth,
|
||||
geosphere->GetSystemBody()->GetPath(), mPatchID, ctx->GetEdgeLen()-2, ctx->GetFrac(), geosphere->GetTerrain());
|
||||
geosphere->GetSystemBody()->GetPath(), mPatchID, ctx->GetEdgeLen() - 2, ctx->GetFrac(), geosphere->GetTerrain());
|
||||
m_job = Pi::GetAsyncJobQueue()->Queue(new SinglePatchJob(ssrd));
|
||||
}
|
||||
}
|
||||
|
@ -373,38 +381,36 @@ void GeoPatch::RequestSinglePatch()
|
|||
void GeoPatch::ReceiveHeightmaps(SQuadSplitResult *psr)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
assert(NULL!=psr);
|
||||
if (m_depth<psr->depth()) {
|
||||
assert(NULL != psr);
|
||||
if (m_depth < psr->depth()) {
|
||||
// this should work because each depth should have a common history
|
||||
const Uint32 kidIdx = psr->data(0).patchID.GetPatchIdx(m_depth+1);
|
||||
if( kids[kidIdx] ) {
|
||||
const Uint32 kidIdx = psr->data(0).patchID.GetPatchIdx(m_depth + 1);
|
||||
if (kids[kidIdx]) {
|
||||
kids[kidIdx]->ReceiveHeightmaps(psr);
|
||||
} else {
|
||||
psr->OnCancel();
|
||||
}
|
||||
} else {
|
||||
assert(mHasJobRequest);
|
||||
const int nD = m_depth+1;
|
||||
for (int i=0; i<NUM_KIDS; i++)
|
||||
{
|
||||
const int nD = m_depth + 1;
|
||||
for (int i = 0; i < NUM_KIDS; i++) {
|
||||
assert(!kids[i]);
|
||||
const SQuadSplitResult::SSplitResultData& data = psr->data(i);
|
||||
assert(i==data.patchID.GetPatchIdx(nD));
|
||||
assert(0==data.patchID.GetPatchIdx(nD+1));
|
||||
const SQuadSplitResult::SSplitResultData &data = psr->data(i);
|
||||
assert(i == data.patchID.GetPatchIdx(nD));
|
||||
assert(0 == data.patchID.GetPatchIdx(nD + 1));
|
||||
kids[i].reset(new GeoPatch(ctx, geosphere,
|
||||
data.v0, data.v1, data.v2, data.v3,
|
||||
nD, data.patchID));
|
||||
}
|
||||
kids[0]->parent = kids[1]->parent = kids[2]->parent = kids[3]->parent = this;
|
||||
|
||||
for (int i=0; i<NUM_KIDS; i++)
|
||||
{
|
||||
const SQuadSplitResult::SSplitResultData& data = psr->data(i);
|
||||
for (int i = 0; i < NUM_KIDS; i++) {
|
||||
const SQuadSplitResult::SSplitResultData &data = psr->data(i);
|
||||
kids[i]->heights.reset(data.heights);
|
||||
kids[i]->normals.reset(data.normals);
|
||||
kids[i]->colors.reset(data.colors);
|
||||
}
|
||||
for (int i=0; i<NUM_KIDS; i++) {
|
||||
for (int i = 0; i < NUM_KIDS; i++) {
|
||||
kids[i]->NeedToUpdateVBOs();
|
||||
}
|
||||
mHasJobRequest = false;
|
||||
|
@ -418,7 +424,7 @@ void GeoPatch::ReceiveHeightmap(const SSingleSplitResult *psr)
|
|||
assert(nullptr != psr);
|
||||
assert(mHasJobRequest);
|
||||
{
|
||||
const SSingleSplitResult::SSplitResultData& data = psr->data();
|
||||
const SSingleSplitResult::SSplitResultData &data = psr->data();
|
||||
heights.reset(data.heights);
|
||||
normals.reset(data.normals);
|
||||
colors.reset(data.colors);
|
||||
|
@ -429,5 +435,5 @@ void GeoPatch::ReceiveHeightmap(const SSingleSplitResult *psr)
|
|||
void GeoPatch::ReceiveJobHandle(Job::Handle job)
|
||||
{
|
||||
assert(!m_job.HasJob());
|
||||
m_job = static_cast<Job::Handle&&>(job);
|
||||
m_job = static_cast<Job::Handle &&>(job);
|
||||
}
|
||||
|
|
|
@ -6,20 +6,22 @@
|
|||
|
||||
#include <SDL_stdinc.h>
|
||||
|
||||
#include "vector3.h"
|
||||
#include "GeoPatchID.h"
|
||||
#include "JobQueue.h"
|
||||
#include "Random.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "graphics/Frustum.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "terrain/Terrain.h"
|
||||
#include "GeoPatchID.h"
|
||||
#include "JobQueue.h"
|
||||
#include "vector3.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
// #define DEBUG_BOUNDING_SPHERES
|
||||
|
||||
namespace Graphics { class Renderer; }
|
||||
namespace Graphics {
|
||||
class Renderer;
|
||||
}
|
||||
class SystemBody;
|
||||
class GeoPatchContext;
|
||||
class GeoSphere;
|
||||
|
@ -53,21 +55,22 @@ private:
|
|||
std::unique_ptr<Graphics::Drawables::Sphere3D> m_boundsphere;
|
||||
#endif
|
||||
public:
|
||||
|
||||
GeoPatch(const RefCountedPtr<GeoPatchContext> &_ctx, GeoSphere *gs,
|
||||
const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_,
|
||||
const int depth, const GeoPatchID &ID_);
|
||||
|
||||
~GeoPatch();
|
||||
|
||||
inline void NeedToUpdateVBOs() {
|
||||
inline void NeedToUpdateVBOs()
|
||||
{
|
||||
m_needUpdateVBOs = (nullptr != heights);
|
||||
}
|
||||
|
||||
void UpdateVBOs(Graphics::Renderer *renderer);
|
||||
|
||||
int GetChildIdx(const GeoPatch *child) const {
|
||||
for (int i=0; i<NUM_KIDS; i++) {
|
||||
int GetChildIdx(const GeoPatch *child) const
|
||||
{
|
||||
for (int i = 0; i < NUM_KIDS; i++) {
|
||||
if (kids[i].get() == child) return i;
|
||||
}
|
||||
abort();
|
||||
|
@ -75,16 +78,18 @@ public:
|
|||
}
|
||||
|
||||
// in patch surface coords, [0,1]
|
||||
inline vector3d GetSpherePoint(const double x, const double y) const {
|
||||
return (v0 + x*(1.0-y)*(v1-v0) + x*y*(v2-v0) + (1.0-x)*y*(v3-v0)).Normalized();
|
||||
inline vector3d GetSpherePoint(const double x, const double y) const
|
||||
{
|
||||
return (v0 + x * (1.0 - y) * (v1 - v0) + x * y * (v2 - v0) + (1.0 - x) * y * (v3 - v0)).Normalized();
|
||||
}
|
||||
|
||||
void Render(Graphics::Renderer *r, const vector3d &campos, const matrix4x4d &modelView, const Graphics::Frustum &frustum);
|
||||
|
||||
inline bool canBeMerged() const {
|
||||
inline bool canBeMerged() const
|
||||
{
|
||||
bool merge = true;
|
||||
if (kids[0]) {
|
||||
for (int i=0; i<NUM_KIDS; i++) {
|
||||
for (int i = 0; i < NUM_KIDS; i++) {
|
||||
merge &= kids[i]->canBeMerged();
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +104,7 @@ public:
|
|||
void ReceiveHeightmap(const SSingleSplitResult *psr);
|
||||
void ReceiveJobHandle(Job::Handle job);
|
||||
|
||||
inline bool HasHeightData() const { return (heights.get()!=nullptr); }
|
||||
inline bool HasHeightData() const { return (heights.get() != nullptr); }
|
||||
};
|
||||
|
||||
#endif /* _GEOPATCH_H */
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "GeoPatchContext.h"
|
||||
#include "perlin.h"
|
||||
#include "Pi.h"
|
||||
#include "RefCounted.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/Frustum.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "libs.h"
|
||||
#include "perlin.h"
|
||||
#include "vcacheopt/vcacheopt.h"
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
// static instances
|
||||
int GeoPatchContext::edgeLen = 0;
|
||||
|
@ -36,7 +36,7 @@ void GeoPatchContext::GenerateIndices()
|
|||
{
|
||||
// calculate how many tri's there are
|
||||
tri_count = (VBO_COUNT_MID_IDX() / 3);
|
||||
for (int i = 0; i<4; ++i) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
tri_count += (VBO_COUNT_HI_EDGE() / 3);
|
||||
}
|
||||
|
||||
|
@ -44,30 +44,30 @@ void GeoPatchContext::GenerateIndices()
|
|||
pl_short.reserve(tri_count);
|
||||
|
||||
// add all of the middle indices
|
||||
for (int i = 0; i<VBO_COUNT_MID_IDX(); ++i) {
|
||||
for (int i = 0; i < VBO_COUNT_MID_IDX(); ++i) {
|
||||
pl_short.push_back(0);
|
||||
}
|
||||
// add the HI detail indices
|
||||
for (int i = 0; i<4; i++) {
|
||||
for (int j = 0; j<VBO_COUNT_HI_EDGE(); ++j) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < VBO_COUNT_HI_EDGE(); ++j) {
|
||||
pl_short.push_back(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// want vtx indices for tris
|
||||
idx = &pl_short[0];
|
||||
for (int x = 0; x<edgeLen - 1; x++) {
|
||||
for (int y = 0; y<edgeLen - 1; y++) {
|
||||
for (int x = 0; x < edgeLen - 1; x++) {
|
||||
for (int y = 0; y < edgeLen - 1; y++) {
|
||||
// 1st tri
|
||||
idx[0] = x + edgeLen*y;
|
||||
idx[1] = x + 1 + edgeLen*y;
|
||||
idx[2] = x + edgeLen*(y + 1);
|
||||
idx[0] = x + edgeLen * y;
|
||||
idx[1] = x + 1 + edgeLen * y;
|
||||
idx[2] = x + edgeLen * (y + 1);
|
||||
idx += 3;
|
||||
|
||||
// 2nd tri
|
||||
idx[0] = x + 1 + edgeLen*y;
|
||||
idx[1] = x + 1 + edgeLen*(y + 1);
|
||||
idx[2] = x + edgeLen*(y + 1);
|
||||
idx[0] = x + 1 + edgeLen * y;
|
||||
idx[1] = x + 1 + edgeLen * (y + 1);
|
||||
idx[2] = x + edgeLen * (y + 1);
|
||||
idx += 3;
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ void GeoPatchContext::GenerateIndices()
|
|||
assert(0 == res);
|
||||
//create buffer & copy
|
||||
indices.Reset(Pi::renderer->CreateIndexBuffer(pl_short.size(), Graphics::BUFFER_USAGE_STATIC));
|
||||
Uint32* idxPtr = indices->Map(Graphics::BUFFER_MAP_WRITE);
|
||||
Uint32 *idxPtr = indices->Map(Graphics::BUFFER_MAP_WRITE);
|
||||
for (Uint32 j = 0; j < pl_short.size(); j++) {
|
||||
idxPtr[j] = pl_short[j];
|
||||
}
|
||||
|
@ -92,9 +92,8 @@ void GeoPatchContext::GenerateIndices()
|
|||
|
||||
void GeoPatchContext::Init()
|
||||
{
|
||||
frac = 1.0 / double(edgeLen-3);
|
||||
numTris = 2*(edgeLen-1)*(edgeLen-1);
|
||||
frac = 1.0 / double(edgeLen - 3);
|
||||
numTris = 2 * (edgeLen - 1) * (edgeLen - 1);
|
||||
|
||||
GenerateIndices();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,20 +6,22 @@
|
|||
|
||||
#include <SDL_stdinc.h>
|
||||
|
||||
#include "vector3.h"
|
||||
#include "GeoPatchID.h"
|
||||
#include "Random.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/VertexBuffer.h"
|
||||
#include "terrain/Terrain.h"
|
||||
#include "GeoPatchID.h"
|
||||
#include "vector3.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
// maximumpatch depth
|
||||
#define GEOPATCH_MAX_DEPTH 15 + (2*Pi::detail.fracmult) //15
|
||||
#define GEOPATCH_MAX_DEPTH 15 + (2 * Pi::detail.fracmult) //15
|
||||
|
||||
namespace Graphics { class Renderer; }
|
||||
namespace Graphics {
|
||||
class Renderer;
|
||||
}
|
||||
class SystemBody;
|
||||
class GeoPatch;
|
||||
class GeoSphere;
|
||||
|
@ -31,12 +33,12 @@ private:
|
|||
|
||||
static double frac;
|
||||
|
||||
static inline int VBO_COUNT_HI_EDGE() { return 3*(edgeLen-1); }
|
||||
static inline int VBO_COUNT_MID_IDX() { return (4*3*(edgeLen-3)) + 2*(edgeLen-3)*(edgeLen-3)*3; }
|
||||
static inline int VBO_COUNT_HI_EDGE() { return 3 * (edgeLen - 1); }
|
||||
static inline int VBO_COUNT_MID_IDX() { return (4 * 3 * (edgeLen - 3)) + 2 * (edgeLen - 3) * (edgeLen - 3) * 3; }
|
||||
// ^^ serrated teeth bit ^^^ square inner bit
|
||||
|
||||
static inline int IDX_VBO_LO_OFFSET(const int i) { return i*sizeof(Uint32)*3*(edgeLen/2); }
|
||||
static inline int IDX_VBO_HI_OFFSET(const int i) { return (i*sizeof(Uint32)*VBO_COUNT_HI_EDGE())+IDX_VBO_LO_OFFSET(4); }
|
||||
static inline int IDX_VBO_LO_OFFSET(const int i) { return i * sizeof(Uint32) * 3 * (edgeLen / 2); }
|
||||
static inline int IDX_VBO_HI_OFFSET(const int i) { return (i * sizeof(Uint32) * VBO_COUNT_HI_EDGE()) + IDX_VBO_LO_OFFSET(4); }
|
||||
|
||||
static RefCountedPtr<Graphics::IndexBuffer> indices;
|
||||
static int prevEdgeLen;
|
||||
|
@ -44,28 +46,29 @@ private:
|
|||
static void GenerateIndices();
|
||||
|
||||
public:
|
||||
struct VBOVertex
|
||||
{
|
||||
struct VBOVertex {
|
||||
vector3f pos;
|
||||
vector3f norm;
|
||||
Color4ub col;
|
||||
vector2f uv;
|
||||
};
|
||||
|
||||
GeoPatchContext(const int _edgeLen) {
|
||||
GeoPatchContext(const int _edgeLen)
|
||||
{
|
||||
edgeLen = _edgeLen + 2; // +2 for the skirt
|
||||
Init();
|
||||
}
|
||||
|
||||
static void Refresh() {
|
||||
static void Refresh()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
static void Init();
|
||||
|
||||
static inline Graphics::IndexBuffer* GetIndexBuffer() { return indices.Get(); }
|
||||
static inline Graphics::IndexBuffer *GetIndexBuffer() { return indices.Get(); }
|
||||
|
||||
static inline int NUMVERTICES() { return edgeLen*edgeLen; }
|
||||
static inline int NUMVERTICES() { return edgeLen * edgeLen; }
|
||||
|
||||
static inline int GetEdgeLen() { return edgeLen; }
|
||||
static inline int GetNumTris() { return numTris; }
|
||||
|
|
|
@ -9,26 +9,26 @@ static const int MAX_PATCH_DEPTH = 30;
|
|||
|
||||
uint64_t GeoPatchID::NextPatchID(const int depth, const int idx) const
|
||||
{
|
||||
assert(idx>=0 && idx<4);
|
||||
assert(depth<=MAX_PATCH_DEPTH);
|
||||
assert(idx >= 0 && idx < 4);
|
||||
assert(depth <= MAX_PATCH_DEPTH);
|
||||
const uint64_t idx64 = idx;
|
||||
const uint64_t shiftDepth64 = depth*2ULL;
|
||||
assert((mPatchID & (3ULL<<shiftDepth64))==0);
|
||||
return uint64_t( mPatchID | (idx64<<shiftDepth64) );
|
||||
const uint64_t shiftDepth64 = depth * 2ULL;
|
||||
assert((mPatchID & (3ULL << shiftDepth64)) == 0);
|
||||
return uint64_t(mPatchID | (idx64 << shiftDepth64));
|
||||
}
|
||||
|
||||
int GeoPatchID::GetPatchIdx(const int depth) const
|
||||
{
|
||||
assert(depth<=MAX_PATCH_DEPTH);
|
||||
const uint64_t shiftDepth64 = depth*2ULL;
|
||||
const uint64_t idx64 = (mPatchID & (3ULL<<shiftDepth64)) >> shiftDepth64;
|
||||
assert(idx64<=uint64_t(-1));
|
||||
assert(depth <= MAX_PATCH_DEPTH);
|
||||
const uint64_t shiftDepth64 = depth * 2ULL;
|
||||
const uint64_t idx64 = (mPatchID & (3ULL << shiftDepth64)) >> shiftDepth64;
|
||||
assert(idx64 <= uint64_t(-1));
|
||||
return int(idx64);
|
||||
}
|
||||
|
||||
int GeoPatchID::GetPatchFaceIdx() const
|
||||
{
|
||||
const int res = (mPatchID & (7ULL << MAX_SHIFT_DEPTH)) >> MAX_SHIFT_DEPTH;
|
||||
assert(res>=0 && res<6);
|
||||
assert(res >= 0 && res < 6);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -6,13 +6,15 @@
|
|||
|
||||
#include <SDL_stdinc.h>
|
||||
|
||||
class GeoPatchID
|
||||
{
|
||||
class GeoPatchID {
|
||||
private:
|
||||
uint64_t mPatchID;
|
||||
|
||||
public:
|
||||
GeoPatchID(const uint64_t init) : mPatchID(init) {}
|
||||
GeoPatchID(const GeoPatchID &init) : mPatchID(init.mPatchID) {}
|
||||
GeoPatchID(const uint64_t init) :
|
||||
mPatchID(init) {}
|
||||
GeoPatchID(const GeoPatchID &init) :
|
||||
mPatchID(init.mPatchID) {}
|
||||
|
||||
static const uint64_t MAX_SHIFT_DEPTH = 61;
|
||||
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "GeoPatchJobs.h"
|
||||
#include "GeoSphere.h"
|
||||
#include "GeoPatch.h"
|
||||
#include "perlin.h"
|
||||
#include "GeoSphere.h"
|
||||
#include "Pi.h"
|
||||
#include "RefCounted.h"
|
||||
#include "libs.h"
|
||||
#include "perlin.h"
|
||||
|
||||
inline void setColour(Color3ub &r, const vector3d &v) {
|
||||
r.r=static_cast<unsigned char>(Clamp(v.x*255.0, 0.0, 255.0));
|
||||
r.g=static_cast<unsigned char>(Clamp(v.y*255.0, 0.0, 255.0));
|
||||
r.b=static_cast<unsigned char>(Clamp(v.z*255.0, 0.0, 255.0));
|
||||
inline void setColour(Color3ub &r, const vector3d &v)
|
||||
{
|
||||
r.r = static_cast<unsigned char>(Clamp(v.x * 255.0, 0.0, 255.0));
|
||||
r.g = static_cast<unsigned char>(Clamp(v.y * 255.0, 0.0, 255.0));
|
||||
r.b = static_cast<unsigned char>(Clamp(v.z * 255.0, 0.0, 255.0));
|
||||
}
|
||||
|
||||
// in patch surface coords, [0,1]
|
||||
inline vector3d GetSpherePoint(const vector3d &v0, const vector3d &v1, const vector3d &v2, const vector3d &v3, const double x, const double y) {
|
||||
return (v0 + x*(1.0-y)*(v1-v0) + x*y*(v2-v0) + (1.0-x)*y*(v3-v0)).Normalized();
|
||||
inline vector3d GetSpherePoint(const vector3d &v0, const vector3d &v1, const vector3d &v2, const vector3d &v3, const double x, const double y)
|
||||
{
|
||||
return (v0 + x * (1.0 - y) * (v1 - v0) + x * y * (v2 - v0) + (1.0 - x) * y * (v3 - v0)).Normalized();
|
||||
}
|
||||
|
||||
// ********************************************************************************
|
||||
|
@ -40,15 +42,15 @@ void SinglePatchJob::GenerateMesh(const SSingleSplitRequest *data) const
|
|||
const double fracStep = data->fracStep;
|
||||
const Terrain *pTerrain = data->pTerrain.Get();
|
||||
|
||||
const int borderedEdgeLen = edgeLen+(BORDER_SIZE*2);
|
||||
const int numBorderedVerts = borderedEdgeLen*borderedEdgeLen;
|
||||
const int borderedEdgeLen = edgeLen + (BORDER_SIZE * 2);
|
||||
const int numBorderedVerts = borderedEdgeLen * borderedEdgeLen;
|
||||
|
||||
// generate heights plus a 1 unit border
|
||||
double *bhts = data->borderHeights.get();
|
||||
vector3d *vrts = borderVertexs;
|
||||
for (int y=-BORDER_SIZE; y<borderedEdgeLen-BORDER_SIZE; y++) {
|
||||
for (int y = -BORDER_SIZE; y < borderedEdgeLen - BORDER_SIZE; y++) {
|
||||
const double yfrac = double(y) * fracStep;
|
||||
for (int x=-BORDER_SIZE; x<borderedEdgeLen-BORDER_SIZE; x++) {
|
||||
for (int x = -BORDER_SIZE; x < borderedEdgeLen - BORDER_SIZE; x++) {
|
||||
const double xfrac = double(x) * fracStep;
|
||||
const vector3d p = GetSpherePoint(v0, v1, v2, v3, xfrac, yfrac);
|
||||
const double height = pTerrain->GetHeight(p);
|
||||
|
@ -64,45 +66,45 @@ void SinglePatchJob::GenerateMesh(const SSingleSplitRequest *data) const
|
|||
vector3f *nrm = normals;
|
||||
double *hts = heights;
|
||||
vrts = borderVertexs;
|
||||
for (int y=BORDER_SIZE; y<borderedEdgeLen-BORDER_SIZE; y++) {
|
||||
for (int x=BORDER_SIZE; x<borderedEdgeLen-BORDER_SIZE; x++) {
|
||||
for (int y = BORDER_SIZE; y < borderedEdgeLen - BORDER_SIZE; y++) {
|
||||
for (int x = BORDER_SIZE; x < borderedEdgeLen - BORDER_SIZE; x++) {
|
||||
// height
|
||||
const double height = borderHeights[x + y*borderedEdgeLen];
|
||||
assert(hts!=&heights[edgeLen*edgeLen]);
|
||||
const double height = borderHeights[x + y * borderedEdgeLen];
|
||||
assert(hts != &heights[edgeLen * edgeLen]);
|
||||
*(hts++) = height;
|
||||
|
||||
// normal
|
||||
const vector3d &x1 = vrts[(x-1) + y*borderedEdgeLen];
|
||||
const vector3d &x2 = vrts[(x+1) + y*borderedEdgeLen];
|
||||
const vector3d &y1 = vrts[x + (y-1)*borderedEdgeLen];
|
||||
const vector3d &y2 = vrts[x + (y+1)*borderedEdgeLen];
|
||||
const vector3d n = ((x2-x1).Cross(y2-y1)).Normalized();
|
||||
assert(nrm!=&normals[edgeLen*edgeLen]);
|
||||
const vector3d &x1 = vrts[(x - 1) + y * borderedEdgeLen];
|
||||
const vector3d &x2 = vrts[(x + 1) + y * borderedEdgeLen];
|
||||
const vector3d &y1 = vrts[x + (y - 1) * borderedEdgeLen];
|
||||
const vector3d &y2 = vrts[x + (y + 1) * borderedEdgeLen];
|
||||
const vector3d n = ((x2 - x1).Cross(y2 - y1)).Normalized();
|
||||
assert(nrm != &normals[edgeLen * edgeLen]);
|
||||
*(nrm++) = vector3f(n);
|
||||
|
||||
// color
|
||||
const vector3d p = GetSpherePoint(v0, v1, v2, v3, (x-BORDER_SIZE)*fracStep, (y-BORDER_SIZE)*fracStep);
|
||||
const vector3d p = GetSpherePoint(v0, v1, v2, v3, (x - BORDER_SIZE) * fracStep, (y - BORDER_SIZE) * fracStep);
|
||||
setColour(*col, pTerrain->GetColor(p, height, n));
|
||||
assert(col!=&colors[edgeLen*edgeLen]);
|
||||
assert(col != &colors[edgeLen * edgeLen]);
|
||||
++col;
|
||||
}
|
||||
}
|
||||
assert(hts == &heights[edgeLen*edgeLen]);
|
||||
assert(nrm == &normals[edgeLen*edgeLen]);
|
||||
assert(col == &colors[edgeLen*edgeLen]);
|
||||
assert(hts == &heights[edgeLen * edgeLen]);
|
||||
assert(nrm == &normals[edgeLen * edgeLen]);
|
||||
assert(col == &colors[edgeLen * edgeLen]);
|
||||
}
|
||||
|
||||
// ********************************************************************************
|
||||
// Overloaded PureJob class to handle generating the mesh for each patch
|
||||
// ********************************************************************************
|
||||
void SinglePatchJob::OnFinish() // runs in primary thread of the context
|
||||
void SinglePatchJob::OnFinish() // runs in primary thread of the context
|
||||
{
|
||||
GeoSphere::OnAddSingleSplitResult( mData->sysPath, mpResults );
|
||||
GeoSphere::OnAddSingleSplitResult(mData->sysPath, mpResults);
|
||||
mpResults = nullptr;
|
||||
BasePatchJob::OnFinish();
|
||||
}
|
||||
|
||||
void SinglePatchJob::OnRun() // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
||||
void SinglePatchJob::OnRun() // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
||||
{
|
||||
BasePatchJob::OnRun();
|
||||
|
||||
|
@ -115,14 +117,14 @@ void SinglePatchJob::OnRun() // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
|||
SSingleSplitResult *sr = new SSingleSplitResult(srd.patchID.GetPatchFaceIdx(), srd.depth);
|
||||
sr->addResult(srd.heights, srd.normals, srd.colors,
|
||||
srd.v0, srd.v1, srd.v2, srd.v3,
|
||||
srd.patchID.NextPatchID(srd.depth+1, 0));
|
||||
srd.patchID.NextPatchID(srd.depth + 1, 0));
|
||||
// store the result
|
||||
mpResults = sr;
|
||||
}
|
||||
|
||||
SinglePatchJob::~SinglePatchJob()
|
||||
{
|
||||
if(mpResults) {
|
||||
if (mpResults) {
|
||||
mpResults->OnCancel();
|
||||
delete mpResults;
|
||||
mpResults = nullptr;
|
||||
|
@ -132,14 +134,14 @@ SinglePatchJob::~SinglePatchJob()
|
|||
// ********************************************************************************
|
||||
// Overloaded PureJob class to handle generating the mesh for each patch
|
||||
// ********************************************************************************
|
||||
void QuadPatchJob::OnFinish() // runs in primary thread of the context
|
||||
void QuadPatchJob::OnFinish() // runs in primary thread of the context
|
||||
{
|
||||
GeoSphere::OnAddQuadSplitResult( mData->sysPath, mpResults );
|
||||
GeoSphere::OnAddQuadSplitResult(mData->sysPath, mpResults);
|
||||
mpResults = nullptr;
|
||||
BasePatchJob::OnFinish();
|
||||
}
|
||||
|
||||
void QuadPatchJob::OnRun() // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
||||
void QuadPatchJob::OnRun() // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
||||
{
|
||||
BasePatchJob::OnRun();
|
||||
|
||||
|
@ -147,29 +149,28 @@ void QuadPatchJob::OnRun() // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
|||
|
||||
GenerateBorderedData(mData.get());
|
||||
|
||||
const vector3d v01 = (srd.v0+srd.v1).Normalized();
|
||||
const vector3d v12 = (srd.v1+srd.v2).Normalized();
|
||||
const vector3d v23 = (srd.v2+srd.v3).Normalized();
|
||||
const vector3d v30 = (srd.v3+srd.v0).Normalized();
|
||||
const vector3d cn = (srd.centroid).Normalized();
|
||||
const vector3d v01 = (srd.v0 + srd.v1).Normalized();
|
||||
const vector3d v12 = (srd.v1 + srd.v2).Normalized();
|
||||
const vector3d v23 = (srd.v2 + srd.v3).Normalized();
|
||||
const vector3d v30 = (srd.v3 + srd.v0).Normalized();
|
||||
const vector3d cn = (srd.centroid).Normalized();
|
||||
const vector3d vecs[4][4] = {
|
||||
{srd.v0, v01, cn, v30},
|
||||
{v01, srd.v1, v12, cn},
|
||||
{cn, v12, srd.v2, v23},
|
||||
{v30, cn, v23, srd.v3}
|
||||
{ srd.v0, v01, cn, v30 },
|
||||
{ v01, srd.v1, v12, cn },
|
||||
{ cn, v12, srd.v2, v23 },
|
||||
{ v30, cn, v23, srd.v3 }
|
||||
};
|
||||
|
||||
const int borderedEdgeLen = (srd.edgeLen*2)+(BORDER_SIZE*2)-1;
|
||||
const int borderedEdgeLen = (srd.edgeLen * 2) + (BORDER_SIZE * 2) - 1;
|
||||
const int offxy[4][2] = {
|
||||
{0,0},
|
||||
{srd.edgeLen-1,0},
|
||||
{srd.edgeLen-1,srd.edgeLen-1},
|
||||
{0,srd.edgeLen-1}
|
||||
{ 0, 0 },
|
||||
{ srd.edgeLen - 1, 0 },
|
||||
{ srd.edgeLen - 1, srd.edgeLen - 1 },
|
||||
{ 0, srd.edgeLen - 1 }
|
||||
};
|
||||
|
||||
SQuadSplitResult *sr = new SQuadSplitResult(srd.patchID.GetPatchFaceIdx(), srd.depth);
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// fill out the data
|
||||
GenerateSubPatchData(srd.heights[i], srd.normals[i], srd.colors[i], srd.borderHeights.get(), srd.borderVertexs.get(),
|
||||
vecs[i][0], vecs[i][1], vecs[i][2], vecs[i][3],
|
||||
|
@ -179,14 +180,14 @@ void QuadPatchJob::OnRun() // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
|||
// add this patches data
|
||||
sr->addResult(i, srd.heights[i], srd.normals[i], srd.colors[i],
|
||||
vecs[i][0], vecs[i][1], vecs[i][2], vecs[i][3],
|
||||
srd.patchID.NextPatchID(srd.depth+1, i));
|
||||
srd.patchID.NextPatchID(srd.depth + 1, i));
|
||||
}
|
||||
mpResults = sr;
|
||||
}
|
||||
|
||||
QuadPatchJob::~QuadPatchJob()
|
||||
{
|
||||
if(mpResults) {
|
||||
if (mpResults) {
|
||||
mpResults->OnCancel();
|
||||
delete mpResults;
|
||||
mpResults = NULL;
|
||||
|
@ -196,24 +197,24 @@ QuadPatchJob::~QuadPatchJob()
|
|||
// Generates full-detail vertices, and also non-edge normals and colors
|
||||
void QuadPatchJob::GenerateBorderedData(const SQuadSplitRequest *data) const
|
||||
{
|
||||
const vector3d &v0 = data->v0;
|
||||
const vector3d &v1 = data->v1;
|
||||
const vector3d &v2 = data->v2;
|
||||
const vector3d &v3 = data->v3;
|
||||
const int edgeLen = data->edgeLen;
|
||||
const double fracStep = data->fracStep;
|
||||
const vector3d &v0 = data->v0;
|
||||
const vector3d &v1 = data->v1;
|
||||
const vector3d &v2 = data->v2;
|
||||
const vector3d &v3 = data->v3;
|
||||
const int edgeLen = data->edgeLen;
|
||||
const double fracStep = data->fracStep;
|
||||
const Terrain *pTerrain = data->pTerrain.Get();
|
||||
|
||||
const int borderedEdgeLen = (edgeLen * 2) + (BORDER_SIZE * 2) - 1;
|
||||
const int numBorderedVerts = borderedEdgeLen*borderedEdgeLen;
|
||||
const int numBorderedVerts = borderedEdgeLen * borderedEdgeLen;
|
||||
|
||||
// generate heights plus a N=BORDER_SIZE unit border
|
||||
double *bhts = data->borderHeights.get();
|
||||
vector3d *vrts = data->borderVertexs.get();
|
||||
for ( int y = -BORDER_SIZE; y < (borderedEdgeLen - BORDER_SIZE); y++ ) {
|
||||
const double yfrac = double(y) * (fracStep*0.5);
|
||||
for ( int x = -BORDER_SIZE; x < (borderedEdgeLen - BORDER_SIZE); x++ ) {
|
||||
const double xfrac = double(x) * (fracStep*0.5);
|
||||
for (int y = -BORDER_SIZE; y < (borderedEdgeLen - BORDER_SIZE); y++) {
|
||||
const double yfrac = double(y) * (fracStep * 0.5);
|
||||
for (int x = -BORDER_SIZE; x < (borderedEdgeLen - BORDER_SIZE); x++) {
|
||||
const double xfrac = double(x) * (fracStep * 0.5);
|
||||
const vector3d p = GetSpherePoint(v0, v1, v2, v3, xfrac, yfrac);
|
||||
const double height = pTerrain->GetHeight(p);
|
||||
assert(height >= 0.0f && height <= 1.0f);
|
||||
|
@ -245,9 +246,9 @@ void QuadPatchJob::GenerateSubPatchData(
|
|||
double *hts = heights;
|
||||
|
||||
// step over the small square
|
||||
for ( int y = 0; y < edgeLen; y++ ) {
|
||||
for (int y = 0; y < edgeLen; y++) {
|
||||
const int by = (y + BORDER_SIZE) + yoff;
|
||||
for ( int x = 0; x < edgeLen; x++ ) {
|
||||
for (int x = 0; x < edgeLen; x++) {
|
||||
const int bx = (x + BORDER_SIZE) + xoff;
|
||||
|
||||
// height
|
||||
|
@ -271,7 +272,7 @@ void QuadPatchJob::GenerateSubPatchData(
|
|||
++col;
|
||||
}
|
||||
}
|
||||
assert(hts == &heights[edgeLen*edgeLen]);
|
||||
assert(nrm == &normals[edgeLen*edgeLen]);
|
||||
assert(col == &colors[edgeLen*edgeLen]);
|
||||
assert(hts == &heights[edgeLen * edgeLen]);
|
||||
assert(nrm == &normals[edgeLen * edgeLen]);
|
||||
assert(col == &colors[edgeLen * edgeLen]);
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
|
||||
#include <SDL_stdinc.h>
|
||||
|
||||
#include "vector3.h"
|
||||
#include "GeoPatchID.h"
|
||||
#include "JobQueue.h"
|
||||
#include "Random.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "terrain/Terrain.h"
|
||||
#include "GeoPatchID.h"
|
||||
#include "JobQueue.h"
|
||||
#include "vector3.h"
|
||||
|
||||
class GeoSphere;
|
||||
|
||||
|
@ -21,14 +21,22 @@ class SBaseRequest {
|
|||
public:
|
||||
SBaseRequest(const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_, const vector3d &cn,
|
||||
const uint32_t depth_, const SystemPath &sysPath_, const GeoPatchID &patchID_, const int edgeLen_, const double fracStep_,
|
||||
Terrain *pTerrain_)
|
||||
: v0(v0_), v1(v1_), v2(v2_), v3(v3_), centroid(cn), depth(depth_),
|
||||
sysPath(sysPath_), patchID(patchID_), edgeLen(edgeLen_), fracStep(fracStep_),
|
||||
Terrain *pTerrain_) :
|
||||
v0(v0_),
|
||||
v1(v1_),
|
||||
v2(v2_),
|
||||
v3(v3_),
|
||||
centroid(cn),
|
||||
depth(depth_),
|
||||
sysPath(sysPath_),
|
||||
patchID(patchID_),
|
||||
edgeLen(edgeLen_),
|
||||
fracStep(fracStep_),
|
||||
pTerrain(pTerrain_)
|
||||
{
|
||||
}
|
||||
|
||||
inline int NUMVERTICES(const int el) const { return el*el; }
|
||||
inline int NUMVERTICES(const int el) const { return el * el; }
|
||||
|
||||
const vector3d v0, v1, v2, v3;
|
||||
const vector3d centroid;
|
||||
|
@ -48,17 +56,16 @@ class SQuadSplitRequest : public SBaseRequest {
|
|||
public:
|
||||
SQuadSplitRequest(const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_, const vector3d &cn,
|
||||
const uint32_t depth_, const SystemPath &sysPath_, const GeoPatchID &patchID_, const int edgeLen_, const double fracStep_,
|
||||
Terrain *pTerrain_)
|
||||
: SBaseRequest(v0_, v1_, v2_, v3_, cn, depth_, sysPath_, patchID_, edgeLen_, fracStep_, pTerrain_)
|
||||
Terrain *pTerrain_) :
|
||||
SBaseRequest(v0_, v1_, v2_, v3_, cn, depth_, sysPath_, patchID_, edgeLen_, fracStep_, pTerrain_)
|
||||
{
|
||||
const int numVerts = NUMVERTICES(edgeLen_);
|
||||
for( int i=0 ; i<4 ; ++i )
|
||||
{
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
heights[i] = new double[numVerts];
|
||||
normals[i] = new vector3f[numVerts];
|
||||
colors[i] = new Color3ub[numVerts];
|
||||
}
|
||||
const int numBorderedVerts = NUMVERTICES((edgeLen_*2)+(BORDER_SIZE*2)-1);
|
||||
const int numBorderedVerts = NUMVERTICES((edgeLen_ * 2) + (BORDER_SIZE * 2) - 1);
|
||||
borderHeights.reset(new double[numBorderedVerts]);
|
||||
borderVertexs.reset(new vector3d[numBorderedVerts]);
|
||||
}
|
||||
|
@ -81,15 +88,15 @@ class SSingleSplitRequest : public SBaseRequest {
|
|||
public:
|
||||
SSingleSplitRequest(const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_, const vector3d &cn,
|
||||
const uint32_t depth_, const SystemPath &sysPath_, const GeoPatchID &patchID_, const int edgeLen_, const double fracStep_,
|
||||
Terrain *pTerrain_)
|
||||
: SBaseRequest(v0_, v1_, v2_, v3_, cn, depth_, sysPath_, patchID_, edgeLen_, fracStep_, pTerrain_)
|
||||
Terrain *pTerrain_) :
|
||||
SBaseRequest(v0_, v1_, v2_, v3_, cn, depth_, sysPath_, patchID_, edgeLen_, fracStep_, pTerrain_)
|
||||
{
|
||||
const int numVerts = NUMVERTICES(edgeLen_);
|
||||
heights = new double[numVerts];
|
||||
normals = new vector3f[numVerts];
|
||||
colors = new Color3ub[numVerts];
|
||||
|
||||
const int numBorderedVerts = NUMVERTICES(edgeLen_+(BORDER_SIZE*2));
|
||||
const int numBorderedVerts = NUMVERTICES(edgeLen_ + (BORDER_SIZE * 2));
|
||||
borderHeights.reset(new double[numBorderedVerts]);
|
||||
borderVertexs.reset(new vector3d[numBorderedVerts]);
|
||||
}
|
||||
|
@ -111,12 +118,26 @@ protected:
|
|||
class SBaseSplitResult {
|
||||
public:
|
||||
struct SSplitResultData {
|
||||
SSplitResultData() : patchID(0) {}
|
||||
SSplitResultData() :
|
||||
patchID(0) {}
|
||||
SSplitResultData(double *heights_, vector3f *n_, Color3ub *c_, const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_, const GeoPatchID &patchID_) :
|
||||
heights(heights_), normals(n_), colors(c_), v0(v0_), v1(v1_), v2(v2_), v3(v3_), patchID(patchID_)
|
||||
heights(heights_),
|
||||
normals(n_),
|
||||
colors(c_),
|
||||
v0(v0_),
|
||||
v1(v1_),
|
||||
v2(v2_),
|
||||
v3(v3_),
|
||||
patchID(patchID_)
|
||||
{}
|
||||
SSplitResultData(const SSplitResultData &r) :
|
||||
normals(r.normals), colors(r.colors), v0(r.v0), v1(r.v1), v2(r.v2), v3(r.v3), patchID(r.patchID)
|
||||
normals(r.normals),
|
||||
colors(r.colors),
|
||||
v0(r.v0),
|
||||
v1(r.v1),
|
||||
v2(r.v2),
|
||||
v3(r.v3),
|
||||
patchID(r.patchID)
|
||||
{}
|
||||
|
||||
double *heights;
|
||||
|
@ -126,7 +147,9 @@ public:
|
|||
GeoPatchID patchID;
|
||||
};
|
||||
|
||||
SBaseSplitResult(const int32_t face_, const int32_t depth_) : mFace(face_), mDepth(depth_) {}
|
||||
SBaseSplitResult(const int32_t face_, const int32_t depth_) :
|
||||
mFace(face_),
|
||||
mDepth(depth_) {}
|
||||
virtual ~SBaseSplitResult() {}
|
||||
|
||||
inline int32_t face() const { return mFace; }
|
||||
|
@ -136,7 +159,9 @@ public:
|
|||
|
||||
protected:
|
||||
// deliberately prevent copy constructor access
|
||||
SBaseSplitResult(const SBaseSplitResult &r) : mFace(0), mDepth(0) {}
|
||||
SBaseSplitResult(const SBaseSplitResult &r) :
|
||||
mFace(0),
|
||||
mDepth(0) {}
|
||||
|
||||
const int32_t mFace;
|
||||
const int32_t mDepth;
|
||||
|
@ -144,38 +169,51 @@ protected:
|
|||
|
||||
class SQuadSplitResult : public SBaseSplitResult {
|
||||
static const int NUM_RESULT_DATA = 4;
|
||||
|
||||
public:
|
||||
SQuadSplitResult(const int32_t face_, const int32_t depth_) : SBaseSplitResult(face_, depth_)
|
||||
SQuadSplitResult(const int32_t face_, const int32_t depth_) :
|
||||
SBaseSplitResult(face_, depth_)
|
||||
{
|
||||
}
|
||||
|
||||
void addResult(const int kidIdx, double *h_, vector3f *n_, Color3ub *c_, const vector3d &v0_, const vector3d &v1_, const vector3d &v2_, const vector3d &v3_, const GeoPatchID &patchID_)
|
||||
{
|
||||
assert(kidIdx>=0 && kidIdx<NUM_RESULT_DATA);
|
||||
assert(kidIdx >= 0 && kidIdx < NUM_RESULT_DATA);
|
||||
mData[kidIdx] = (SSplitResultData(h_, n_, c_, v0_, v1_, v2_, v3_, patchID_));
|
||||
}
|
||||
|
||||
inline const SSplitResultData& data(const int32_t idx) const { return mData[idx]; }
|
||||
inline const SSplitResultData &data(const int32_t idx) const { return mData[idx]; }
|
||||
|
||||
virtual void OnCancel()
|
||||
{
|
||||
for( int i=0; i<NUM_RESULT_DATA; ++i ) {
|
||||
if( mData[i].heights ) {delete [] mData[i].heights; mData[i].heights = NULL;}
|
||||
if( mData[i].normals ) {delete [] mData[i].normals; mData[i].normals = NULL;}
|
||||
if( mData[i].colors ) {delete [] mData[i].colors; mData[i].colors = NULL;}
|
||||
for (int i = 0; i < NUM_RESULT_DATA; ++i) {
|
||||
if (mData[i].heights) {
|
||||
delete[] mData[i].heights;
|
||||
mData[i].heights = NULL;
|
||||
}
|
||||
if (mData[i].normals) {
|
||||
delete[] mData[i].normals;
|
||||
mData[i].normals = NULL;
|
||||
}
|
||||
if (mData[i].colors) {
|
||||
delete[] mData[i].colors;
|
||||
mData[i].colors = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
// deliberately prevent copy constructor access
|
||||
SQuadSplitResult(const SQuadSplitResult &r) : SBaseSplitResult(r) {}
|
||||
SQuadSplitResult(const SQuadSplitResult &r) :
|
||||
SBaseSplitResult(r) {}
|
||||
|
||||
SSplitResultData mData[NUM_RESULT_DATA];
|
||||
};
|
||||
|
||||
class SSingleSplitResult : public SBaseSplitResult {
|
||||
public:
|
||||
SSingleSplitResult(const int32_t face_, const int32_t depth_) : SBaseSplitResult(face_, depth_)
|
||||
SSingleSplitResult(const int32_t face_, const int32_t depth_) :
|
||||
SBaseSplitResult(face_, depth_)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -184,20 +222,30 @@ public:
|
|||
mData = (SSplitResultData(h_, n_, c_, v0_, v1_, v2_, v3_, patchID_));
|
||||
}
|
||||
|
||||
inline const SSplitResultData& data() const { return mData; }
|
||||
inline const SSplitResultData &data() const { return mData; }
|
||||
|
||||
virtual void OnCancel()
|
||||
{
|
||||
{
|
||||
if( mData.heights ) {delete [] mData.heights; mData.heights = NULL;}
|
||||
if( mData.normals ) {delete [] mData.normals; mData.normals = NULL;}
|
||||
if( mData.colors ) {delete [] mData.colors; mData.colors = NULL;}
|
||||
if (mData.heights) {
|
||||
delete[] mData.heights;
|
||||
mData.heights = NULL;
|
||||
}
|
||||
if (mData.normals) {
|
||||
delete[] mData.normals;
|
||||
mData.normals = NULL;
|
||||
}
|
||||
if (mData.colors) {
|
||||
delete[] mData.colors;
|
||||
mData.colors = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
// deliberately prevent copy constructor access
|
||||
SSingleSplitResult(const SSingleSplitResult &r) : SBaseSplitResult(r) {}
|
||||
SSingleSplitResult(const SSingleSplitResult &r) :
|
||||
SBaseSplitResult(r) {}
|
||||
|
||||
SSplitResultData mData;
|
||||
};
|
||||
|
@ -207,11 +255,10 @@ class GeoPatch;
|
|||
// ********************************************************************************
|
||||
// Overloaded PureJob class to handle generating the mesh for each patch
|
||||
// ********************************************************************************
|
||||
class BasePatchJob : public Job
|
||||
{
|
||||
class BasePatchJob : public Job {
|
||||
public:
|
||||
BasePatchJob() {}
|
||||
virtual void OnRun() {} // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
||||
virtual void OnRun() {} // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
||||
virtual void OnFinish() {}
|
||||
virtual void OnCancel() {}
|
||||
};
|
||||
|
@ -219,14 +266,17 @@ public:
|
|||
// ********************************************************************************
|
||||
// Overloaded PureJob class to handle generating the mesh for each patch
|
||||
// ********************************************************************************
|
||||
class SinglePatchJob : public BasePatchJob
|
||||
{
|
||||
class SinglePatchJob : public BasePatchJob {
|
||||
public:
|
||||
SinglePatchJob(SSingleSplitRequest *data) : mData(data), mpResults(NULL) { /* empty */ }
|
||||
SinglePatchJob(SSingleSplitRequest *data) :
|
||||
mData(data),
|
||||
mpResults(NULL)
|
||||
{ /* empty */
|
||||
}
|
||||
~SinglePatchJob();
|
||||
|
||||
virtual void OnRun(); // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
||||
virtual void OnFinish(); // runs in primary thread of the context
|
||||
virtual void OnRun(); // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
||||
virtual void OnFinish(); // runs in primary thread of the context
|
||||
|
||||
private:
|
||||
// Generates full-detail vertices, and also non-edge normals and colors
|
||||
|
@ -239,14 +289,17 @@ private:
|
|||
// ********************************************************************************
|
||||
// Overloaded PureJob class to handle generating the mesh for each patch
|
||||
// ********************************************************************************
|
||||
class QuadPatchJob : public BasePatchJob
|
||||
{
|
||||
class QuadPatchJob : public BasePatchJob {
|
||||
public:
|
||||
QuadPatchJob(SQuadSplitRequest *data) : mData(data), mpResults(NULL) { /* empty */ }
|
||||
QuadPatchJob(SQuadSplitRequest *data) :
|
||||
mData(data),
|
||||
mpResults(NULL)
|
||||
{ /* empty */
|
||||
}
|
||||
~QuadPatchJob();
|
||||
|
||||
virtual void OnRun(); // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
||||
virtual void OnFinish(); // runs in primary thread of the context
|
||||
virtual void OnRun(); // RUNS IN ANOTHER THREAD!! MUST BE THREAD SAFE!
|
||||
virtual void OnFinish(); // runs in primary thread of the context
|
||||
|
||||
private:
|
||||
// Generates full-detail vertices, and also non-edge normals and colors
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "GeoSphere.h"
|
||||
#include "GeoPatchContext.h"
|
||||
#include "GeoPatch.h"
|
||||
#include "GeoPatchContext.h"
|
||||
#include "GeoPatchJobs.h"
|
||||
#include "perlin.h"
|
||||
#include "Pi.h"
|
||||
#include "RefCounted.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/Frustum.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/Texture.h"
|
||||
#include "graphics/TextureBuilder.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "libs.h"
|
||||
#include "perlin.h"
|
||||
#include "vcacheopt/vcacheopt.h"
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
RefCountedPtr<GeoPatchContext> GeoSphere::s_patchContext;
|
||||
|
||||
|
@ -40,7 +40,7 @@ static const double gs_targetPatchTriLength(100.0);
|
|||
// { 1, 4, 3, 2 }
|
||||
// };
|
||||
|
||||
static std::vector<GeoSphere*> s_allGeospheres;
|
||||
static std::vector<GeoSphere *> s_allGeospheres;
|
||||
|
||||
void GeoSphere::Init()
|
||||
{
|
||||
|
@ -49,7 +49,7 @@ void GeoSphere::Init()
|
|||
|
||||
void GeoSphere::Uninit()
|
||||
{
|
||||
assert (s_patchContext.Unique());
|
||||
assert(s_patchContext.Unique());
|
||||
s_patchContext.Reset();
|
||||
}
|
||||
|
||||
|
@ -67,8 +67,7 @@ static void print_info(const SystemBody *sbody, const Terrain *terrain)
|
|||
void GeoSphere::UpdateAllGeoSpheres()
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
for(std::vector<GeoSphere*>::iterator i = s_allGeospheres.begin(); i != s_allGeospheres.end(); ++i)
|
||||
{
|
||||
for (std::vector<GeoSphere *>::iterator i = s_allGeospheres.begin(); i != s_allGeospheres.end(); ++i) {
|
||||
(*i)->Update();
|
||||
}
|
||||
}
|
||||
|
@ -79,8 +78,7 @@ void GeoSphere::OnChangeDetailLevel()
|
|||
s_patchContext.Reset(new GeoPatchContext(detail_edgeLen[Pi::detail.planets > 4 ? 4 : Pi::detail.planets]));
|
||||
|
||||
// reinit the geosphere terrain data
|
||||
for(std::vector<GeoSphere*>::iterator i = s_allGeospheres.begin(); i != s_allGeospheres.end(); ++i)
|
||||
{
|
||||
for (std::vector<GeoSphere *>::iterator i = s_allGeospheres.begin(); i != s_allGeospheres.end(); ++i) {
|
||||
// clearout anything we don't need
|
||||
(*i)->Reset();
|
||||
|
||||
|
@ -94,14 +92,14 @@ void GeoSphere::OnChangeDetailLevel()
|
|||
bool GeoSphere::OnAddQuadSplitResult(const SystemPath &path, SQuadSplitResult *res)
|
||||
{
|
||||
// Find the correct GeoSphere via it's system path, and give it the split result
|
||||
for(std::vector<GeoSphere*>::iterator i=s_allGeospheres.begin(), iEnd=s_allGeospheres.end(); i!=iEnd; ++i) {
|
||||
if( path == (*i)->GetSystemBody()->GetPath() ) {
|
||||
for (std::vector<GeoSphere *>::iterator i = s_allGeospheres.begin(), iEnd = s_allGeospheres.end(); i != iEnd; ++i) {
|
||||
if (path == (*i)->GetSystemBody()->GetPath()) {
|
||||
(*i)->AddQuadSplitResult(res);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// GeoSphere not found to return the data to, cancel and delete it instead
|
||||
if( res ) {
|
||||
if (res) {
|
||||
res->OnCancel();
|
||||
delete res;
|
||||
}
|
||||
|
@ -112,14 +110,14 @@ bool GeoSphere::OnAddQuadSplitResult(const SystemPath &path, SQuadSplitResult *r
|
|||
bool GeoSphere::OnAddSingleSplitResult(const SystemPath &path, SSingleSplitResult *res)
|
||||
{
|
||||
// Find the correct GeoSphere via it's system path, and give it the split result
|
||||
for(std::vector<GeoSphere*>::iterator i=s_allGeospheres.begin(), iEnd=s_allGeospheres.end(); i!=iEnd; ++i) {
|
||||
if( path == (*i)->GetSystemBody()->GetPath() ) {
|
||||
for (std::vector<GeoSphere *>::iterator i = s_allGeospheres.begin(), iEnd = s_allGeospheres.end(); i != iEnd; ++i) {
|
||||
if (path == (*i)->GetSystemBody()->GetPath()) {
|
||||
(*i)->AddSingleSplitResult(res);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// GeoSphere not found to return the data to, cancel and delete it instead
|
||||
if( res ) {
|
||||
if (res) {
|
||||
res->OnCancel();
|
||||
delete res;
|
||||
}
|
||||
|
@ -129,9 +127,8 @@ bool GeoSphere::OnAddSingleSplitResult(const SystemPath &path, SSingleSplitResul
|
|||
void GeoSphere::Reset()
|
||||
{
|
||||
{
|
||||
std::deque<SSingleSplitResult*>::iterator iter = mSingleSplitResults.begin();
|
||||
while(iter!=mSingleSplitResults.end())
|
||||
{
|
||||
std::deque<SSingleSplitResult *>::iterator iter = mSingleSplitResults.begin();
|
||||
while (iter != mSingleSplitResults.end()) {
|
||||
// finally pass SplitResults
|
||||
SSingleSplitResult *psr = (*iter);
|
||||
assert(psr);
|
||||
|
@ -148,9 +145,8 @@ void GeoSphere::Reset()
|
|||
}
|
||||
|
||||
{
|
||||
std::deque<SQuadSplitResult*>::iterator iter = mQuadSplitResults.begin();
|
||||
while(iter!=mQuadSplitResults.end())
|
||||
{
|
||||
std::deque<SQuadSplitResult *>::iterator iter = mQuadSplitResults.begin();
|
||||
while (iter != mQuadSplitResults.end()) {
|
||||
// finally pass SplitResults
|
||||
SQuadSplitResult *psr = (*iter);
|
||||
assert(psr);
|
||||
|
@ -166,7 +162,7 @@ void GeoSphere::Reset()
|
|||
mQuadSplitResults.clear();
|
||||
}
|
||||
|
||||
for (int p=0; p<NUM_PATCHES; p++) {
|
||||
for (int p = 0; p < NUM_PATCHES; p++) {
|
||||
// delete patches
|
||||
if (m_patches[p]) {
|
||||
m_patches[p].reset();
|
||||
|
@ -178,9 +174,13 @@ void GeoSphere::Reset()
|
|||
m_initStage = eBuildFirstPatches;
|
||||
}
|
||||
|
||||
GeoSphere::GeoSphere(const SystemBody *body) : BaseSphere(body),
|
||||
m_hasTempCampos(false), m_tempCampos(0.0), m_tempFrustum(800, 600, 0.5, 1.0, 1000.0),
|
||||
m_initStage(eBuildFirstPatches), m_maxDepth(0)
|
||||
GeoSphere::GeoSphere(const SystemBody *body) :
|
||||
BaseSphere(body),
|
||||
m_hasTempCampos(false),
|
||||
m_tempCampos(0.0),
|
||||
m_tempFrustum(800, 600, 0.5, 1.0, 1000.0),
|
||||
m_initStage(eBuildFirstPatches),
|
||||
m_maxDepth(0)
|
||||
{
|
||||
print_info(body, m_terrain.Get());
|
||||
|
||||
|
@ -202,8 +202,8 @@ bool GeoSphere::AddQuadSplitResult(SQuadSplitResult *res)
|
|||
{
|
||||
bool result = false;
|
||||
assert(res);
|
||||
assert(mQuadSplitResults.size()<MAX_SPLIT_OPERATIONS);
|
||||
if(mQuadSplitResults.size()<MAX_SPLIT_OPERATIONS) {
|
||||
assert(mQuadSplitResults.size() < MAX_SPLIT_OPERATIONS);
|
||||
if (mQuadSplitResults.size() < MAX_SPLIT_OPERATIONS) {
|
||||
mQuadSplitResults.push_back(res);
|
||||
result = true;
|
||||
}
|
||||
|
@ -214,8 +214,8 @@ bool GeoSphere::AddSingleSplitResult(SSingleSplitResult *res)
|
|||
{
|
||||
bool result = false;
|
||||
assert(res);
|
||||
assert(mSingleSplitResults.size()<MAX_SPLIT_OPERATIONS);
|
||||
if(mSingleSplitResults.size()<MAX_SPLIT_OPERATIONS) {
|
||||
assert(mSingleSplitResults.size() < MAX_SPLIT_OPERATIONS);
|
||||
if (mSingleSplitResults.size() < MAX_SPLIT_OPERATIONS) {
|
||||
mSingleSplitResults.push_back(res);
|
||||
result = true;
|
||||
}
|
||||
|
@ -226,15 +226,14 @@ void GeoSphere::ProcessSplitResults()
|
|||
{
|
||||
// now handle the single split results that define the base level of the quad tree
|
||||
{
|
||||
std::deque<SSingleSplitResult*>::iterator iter = mSingleSplitResults.begin();
|
||||
while(iter!=mSingleSplitResults.end())
|
||||
{
|
||||
std::deque<SSingleSplitResult *>::iterator iter = mSingleSplitResults.begin();
|
||||
while (iter != mSingleSplitResults.end()) {
|
||||
// finally pass SplitResults
|
||||
SSingleSplitResult *psr = (*iter);
|
||||
assert(psr);
|
||||
|
||||
const int32_t faceIdx = psr->face();
|
||||
if( m_patches[faceIdx] ) {
|
||||
if (m_patches[faceIdx]) {
|
||||
m_patches[faceIdx]->ReceiveHeightmap(psr);
|
||||
} else {
|
||||
psr->OnCancel();
|
||||
|
@ -251,15 +250,14 @@ void GeoSphere::ProcessSplitResults()
|
|||
|
||||
// now handle the quad split results
|
||||
{
|
||||
std::deque<SQuadSplitResult*>::iterator iter = mQuadSplitResults.begin();
|
||||
while(iter!=mQuadSplitResults.end())
|
||||
{
|
||||
std::deque<SQuadSplitResult *>::iterator iter = mQuadSplitResults.begin();
|
||||
while (iter != mQuadSplitResults.end()) {
|
||||
// finally pass SplitResults
|
||||
SQuadSplitResult *psr = (*iter);
|
||||
assert(psr);
|
||||
|
||||
const int32_t faceIdx = psr->face();
|
||||
if( m_patches[faceIdx] ) {
|
||||
if (m_patches[faceIdx]) {
|
||||
m_patches[faceIdx]->ReceiveHeightmaps(psr);
|
||||
} else {
|
||||
psr->OnCancel();
|
||||
|
@ -278,20 +276,20 @@ void GeoSphere::ProcessSplitResults()
|
|||
void GeoSphere::BuildFirstPatches()
|
||||
{
|
||||
assert(!m_patches[0]);
|
||||
if(m_patches[0])
|
||||
if (m_patches[0])
|
||||
return;
|
||||
|
||||
CalculateMaxPatchDepth();
|
||||
|
||||
// generate root face patches of the cube/sphere
|
||||
static const vector3d p1 = (vector3d( 1, 1, 1)).Normalized();
|
||||
static const vector3d p1 = (vector3d(1, 1, 1)).Normalized();
|
||||
static const vector3d p2 = (vector3d(-1, 1, 1)).Normalized();
|
||||
static const vector3d p3 = (vector3d(-1,-1, 1)).Normalized();
|
||||
static const vector3d p4 = (vector3d( 1,-1, 1)).Normalized();
|
||||
static const vector3d p5 = (vector3d( 1, 1,-1)).Normalized();
|
||||
static const vector3d p6 = (vector3d(-1, 1,-1)).Normalized();
|
||||
static const vector3d p7 = (vector3d(-1,-1,-1)).Normalized();
|
||||
static const vector3d p8 = (vector3d( 1,-1,-1)).Normalized();
|
||||
static const vector3d p3 = (vector3d(-1, -1, 1)).Normalized();
|
||||
static const vector3d p4 = (vector3d(1, -1, 1)).Normalized();
|
||||
static const vector3d p5 = (vector3d(1, 1, -1)).Normalized();
|
||||
static const vector3d p6 = (vector3d(-1, 1, -1)).Normalized();
|
||||
static const vector3d p7 = (vector3d(-1, -1, -1)).Normalized();
|
||||
static const vector3d p8 = (vector3d(1, -1, -1)).Normalized();
|
||||
|
||||
const uint64_t maxShiftDepth = GeoPatchID::MAX_SHIFT_DEPTH;
|
||||
|
||||
|
@ -302,7 +300,7 @@ void GeoSphere::BuildFirstPatches()
|
|||
m_patches[4].reset(new GeoPatch(s_patchContext, this, p3, p2, p6, p7, 0, (4ULL << maxShiftDepth)));
|
||||
m_patches[5].reset(new GeoPatch(s_patchContext, this, p8, p7, p6, p5, 0, (5ULL << maxShiftDepth)));
|
||||
|
||||
for (int i=0; i<NUM_PATCHES; i++) {
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
m_patches[i]->RequestSinglePatch();
|
||||
}
|
||||
|
||||
|
@ -315,7 +313,7 @@ void GeoSphere::CalculateMaxPatchDepth()
|
|||
// calculate length of each edge segment (quad) times 4 due to that being the number around the sphere (1 per side, 4 sides for Root).
|
||||
double edgeMetres = circumference / double(s_patchContext->GetEdgeLen() * 8);
|
||||
// find out what depth we reach the desired resolution
|
||||
while (edgeMetres>gs_targetPatchTriLength && m_maxDepth<GEOPATCH_MAX_DEPTH) {
|
||||
while (edgeMetres > gs_targetPatchTriLength && m_maxDepth < GEOPATCH_MAX_DEPTH) {
|
||||
edgeMetres *= 0.5;
|
||||
++m_maxDepth;
|
||||
}
|
||||
|
@ -323,33 +321,30 @@ void GeoSphere::CalculateMaxPatchDepth()
|
|||
|
||||
void GeoSphere::Update()
|
||||
{
|
||||
switch(m_initStage)
|
||||
{
|
||||
switch (m_initStage) {
|
||||
case eBuildFirstPatches:
|
||||
BuildFirstPatches();
|
||||
break;
|
||||
case eRequestedFirstPatches:
|
||||
{
|
||||
ProcessSplitResults();
|
||||
uint8_t numValidPatches = 0;
|
||||
for (int i=0; i<NUM_PATCHES; i++) {
|
||||
if(m_patches[i]->HasHeightData()) {
|
||||
++numValidPatches;
|
||||
}
|
||||
case eRequestedFirstPatches: {
|
||||
ProcessSplitResults();
|
||||
uint8_t numValidPatches = 0;
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
if (m_patches[i]->HasHeightData()) {
|
||||
++numValidPatches;
|
||||
}
|
||||
m_initStage = (NUM_PATCHES==numValidPatches) ? eReceivedFirstPatches : eRequestedFirstPatches;
|
||||
} break;
|
||||
case eReceivedFirstPatches:
|
||||
{
|
||||
for (int i=0; i<NUM_PATCHES; i++) {
|
||||
m_patches[i]->NeedToUpdateVBOs();
|
||||
}
|
||||
m_initStage = eDefaultUpdateState;
|
||||
} break;
|
||||
}
|
||||
m_initStage = (NUM_PATCHES == numValidPatches) ? eReceivedFirstPatches : eRequestedFirstPatches;
|
||||
} break;
|
||||
case eReceivedFirstPatches: {
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
m_patches[i]->NeedToUpdateVBOs();
|
||||
}
|
||||
m_initStage = eDefaultUpdateState;
|
||||
} break;
|
||||
case eDefaultUpdateState:
|
||||
if(m_hasTempCampos) {
|
||||
if (m_hasTempCampos) {
|
||||
ProcessSplitResults();
|
||||
for (int i=0; i<NUM_PATCHES; i++) {
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
m_patches[i]->LODUpdate(m_tempCampos, m_tempFrustum);
|
||||
}
|
||||
ProcessQuadSplitRequests();
|
||||
|
@ -374,7 +369,7 @@ void GeoSphere::ProcessQuadSplitRequests()
|
|||
};
|
||||
std::sort(mQuadSplitRequests.begin(), mQuadSplitRequests.end(), RequestDistanceSort());
|
||||
|
||||
for(auto iter : mQuadSplitRequests) {
|
||||
for (auto iter : mQuadSplitRequests) {
|
||||
SQuadSplitRequest *ssrd = iter.mpRequest;
|
||||
iter.mpRequester->ReceiveJobHandle(Pi::GetAsyncJobQueue()->Queue(new QuadPatchJob(ssrd)));
|
||||
}
|
||||
|
@ -388,7 +383,7 @@ void GeoSphere::Render(Graphics::Renderer *renderer, const matrix4x4d &modelView
|
|||
m_tempCampos = campos;
|
||||
m_hasTempCampos = true;
|
||||
|
||||
if(m_initStage < eDefaultUpdateState)
|
||||
if (m_initStage < eDefaultUpdateState)
|
||||
return;
|
||||
|
||||
matrix4x4d trans = modelView;
|
||||
|
@ -398,7 +393,7 @@ void GeoSphere::Render(Graphics::Renderer *renderer, const matrix4x4d &modelView
|
|||
matrix4x4d proj;
|
||||
matrix4x4ftod(renderer->GetCurrentModelView(), modv);
|
||||
matrix4x4ftod(renderer->GetCurrentProjection(), proj);
|
||||
Graphics::Frustum frustum( modv, proj );
|
||||
Graphics::Frustum frustum(modv, proj);
|
||||
m_tempFrustum = frustum;
|
||||
|
||||
// no frustum test of entire geosphere, since Space::Render does this
|
||||
|
@ -428,7 +423,7 @@ void GeoSphere::Render(Graphics::Renderer *renderer, const matrix4x4d &modelView
|
|||
// that the edges of the pixel shader atmosphere jizz doesn't
|
||||
// show ugly polygonal angles
|
||||
DrawAtmosphereSurface(renderer, trans, campos,
|
||||
m_materialParameters.atmosphere.atmosRadius*1.01,
|
||||
m_materialParameters.atmosphere.atmosRadius * 1.01,
|
||||
m_atmosRenderState, m_atmosphereMaterial);
|
||||
}
|
||||
}
|
||||
|
@ -450,7 +445,7 @@ void GeoSphere::Render(Graphics::Renderer *renderer, const matrix4x4d &modelView
|
|||
else {
|
||||
// give planet some ambient lighting if the viewer is close to it
|
||||
double camdist = campos.Length();
|
||||
camdist = 0.1 / (camdist*camdist);
|
||||
camdist = 0.1 / (camdist * camdist);
|
||||
// why the fuck is this returning 0.1 when we are sat on the planet??
|
||||
// JJ: Because campos is relative to a unit-radius planet - 1.0 at the surface
|
||||
// XXX oh well, it is the value we want anyway...
|
||||
|
@ -462,7 +457,7 @@ void GeoSphere::Render(Graphics::Renderer *renderer, const matrix4x4d &modelView
|
|||
|
||||
renderer->SetTransform(modelView);
|
||||
|
||||
for (int i=0; i<NUM_PATCHES; i++) {
|
||||
for (int i = 0; i < NUM_PATCHES; i++) {
|
||||
m_patches[i]->Render(renderer, campos, modelView, frustum);
|
||||
}
|
||||
|
||||
|
@ -499,8 +494,7 @@ void GeoSphere::SetUpMaterials()
|
|||
//dim star (emits and receives light)
|
||||
surfDesc.lighting = true;
|
||||
surfDesc.quality &= ~Graphics::HAS_ATMOSPHERE;
|
||||
}
|
||||
else if (GetSystemBody()->GetSuperType() == SystemBody::SUPERTYPE_STAR) {
|
||||
} else if (GetSystemBody()->GetSuperType() == SystemBody::SUPERTYPE_STAR) {
|
||||
//normal star
|
||||
surfDesc.lighting = false;
|
||||
surfDesc.quality &= ~Graphics::HAS_ATMOSPHERE;
|
||||
|
@ -509,7 +503,7 @@ void GeoSphere::SetUpMaterials()
|
|||
//planetoid with or without atmosphere
|
||||
const SystemBody::AtmosphereParameters ap(GetSystemBody()->CalcAtmosphereParams());
|
||||
surfDesc.lighting = true;
|
||||
if(ap.atmosDensity > 0.0) {
|
||||
if (ap.atmosDensity > 0.0) {
|
||||
surfDesc.quality |= Graphics::HAS_ATMOSPHERE;
|
||||
} else {
|
||||
surfDesc.quality &= ~Graphics::HAS_ATMOSPHERE;
|
||||
|
@ -523,8 +517,8 @@ void GeoSphere::SetUpMaterials()
|
|||
}
|
||||
m_surfaceMaterial.Reset(Pi::renderer->CreateMaterial(surfDesc));
|
||||
|
||||
m_texHi.Reset( Graphics::TextureBuilder::Model("textures/high.dds").GetOrCreateTexture(Pi::renderer, "model") );
|
||||
m_texLo.Reset( Graphics::TextureBuilder::Model("textures/low.dds").GetOrCreateTexture(Pi::renderer, "model") );
|
||||
m_texHi.Reset(Graphics::TextureBuilder::Model("textures/high.dds").GetOrCreateTexture(Pi::renderer, "model"));
|
||||
m_texLo.Reset(Graphics::TextureBuilder::Model("textures/low.dds").GetOrCreateTexture(Pi::renderer, "model"));
|
||||
m_surfaceMaterial->texture0 = m_texHi.Get();
|
||||
m_surfaceMaterial->texture1 = m_texLo.Get();
|
||||
|
||||
|
|
|
@ -6,19 +6,21 @@
|
|||
|
||||
#include <SDL_stdinc.h>
|
||||
|
||||
#include "vector3.h"
|
||||
#include "Random.h"
|
||||
#include "Camera.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "graphics/RenderState.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "terrain/Terrain.h"
|
||||
#include "GeoPatchID.h"
|
||||
#include "BaseSphere.h"
|
||||
#include "Camera.h"
|
||||
#include "GeoPatchID.h"
|
||||
#include "Random.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/RenderState.h"
|
||||
#include "terrain/Terrain.h"
|
||||
#include "vector3.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
namespace Graphics { class Renderer; }
|
||||
namespace Graphics {
|
||||
class Renderer;
|
||||
}
|
||||
class SystemBody;
|
||||
class GeoPatch;
|
||||
class GeoPatchContext;
|
||||
|
@ -36,7 +38,8 @@ public:
|
|||
virtual void Update() override;
|
||||
virtual void Render(Graphics::Renderer *renderer, const matrix4x4d &modelView, vector3d campos, const float radius, const std::vector<Camera::Shadow> &shadows) override;
|
||||
|
||||
virtual double GetHeight(const vector3d &p) const override final {
|
||||
virtual double GetHeight(const vector3d &p) const override final
|
||||
{
|
||||
const double h = m_terrain->GetHeight(p);
|
||||
#ifdef DEBUG
|
||||
// XXX don't remove this. Fix your fractals instead
|
||||
|
@ -68,12 +71,13 @@ public:
|
|||
|
||||
inline Sint32 GetMaxDepth() const { return m_maxDepth; }
|
||||
|
||||
void AddQuadSplitRequest(double, SQuadSplitRequest*, GeoPatch*);
|
||||
void AddQuadSplitRequest(double, SQuadSplitRequest *, GeoPatch *);
|
||||
|
||||
private:
|
||||
void BuildFirstPatches();
|
||||
void CalculateMaxPatchDepth();
|
||||
inline vector3d GetColor(const vector3d &p, double height, const vector3d &norm) const {
|
||||
inline vector3d GetColor(const vector3d &p, double height, const vector3d &norm) const
|
||||
{
|
||||
return m_terrain->GetColor(p, height, norm);
|
||||
}
|
||||
void ProcessQuadSplitRequests();
|
||||
|
@ -81,7 +85,9 @@ private:
|
|||
std::unique_ptr<GeoPatch> m_patches[6];
|
||||
struct TDistanceRequest {
|
||||
TDistanceRequest(double dist, SQuadSplitRequest *pRequest, GeoPatch *pRequester) :
|
||||
mDistance(dist), mpRequest(pRequest), mpRequester(pRequester) {}
|
||||
mDistance(dist),
|
||||
mpRequest(pRequest),
|
||||
mpRequester(pRequester) {}
|
||||
double mDistance;
|
||||
SQuadSplitRequest *mpRequest;
|
||||
GeoPatch *mpRequester;
|
||||
|
@ -89,8 +95,8 @@ private:
|
|||
std::deque<TDistanceRequest> mQuadSplitRequests;
|
||||
|
||||
static const uint32_t MAX_SPLIT_OPERATIONS = 128;
|
||||
std::deque<SQuadSplitResult*> mQuadSplitResults;
|
||||
std::deque<SSingleSplitResult*> mSingleSplitResults;
|
||||
std::deque<SQuadSplitResult *> mQuadSplitResults;
|
||||
std::deque<SSingleSplitResult *> mSingleSplitResults;
|
||||
|
||||
bool m_hasTempCampos;
|
||||
vector3d m_tempCampos;
|
||||
|
@ -104,7 +110,7 @@ private:
|
|||
RefCountedPtr<Graphics::Texture> m_texLo;
|
||||
|
||||
enum EGSInitialisationStage {
|
||||
eBuildFirstPatches=0,
|
||||
eBuildFirstPatches = 0,
|
||||
eRequestedFirstPatches,
|
||||
eReceivedFirstPatches,
|
||||
eDefaultUpdateState
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
const float UPDATE_INTERVAL = 0.1f;
|
||||
const Uint16 MAX_POINTS = 100;
|
||||
|
||||
HudTrail::HudTrail(Body *b, const Color& c)
|
||||
: m_body(b)
|
||||
, m_updateTime(0.f)
|
||||
, m_color(c)
|
||||
HudTrail::HudTrail(Body *b, const Color &c) :
|
||||
m_body(b),
|
||||
m_updateTime(0.f),
|
||||
m_color(c)
|
||||
{
|
||||
m_currentFrame = b->GetFrame();
|
||||
|
||||
|
@ -30,12 +30,12 @@ void HudTrail::Update(float time)
|
|||
m_updateTime = 0.f;
|
||||
const Frame *bodyFrame = m_body->GetFrame();
|
||||
|
||||
if( !m_currentFrame ) {
|
||||
if (!m_currentFrame) {
|
||||
m_currentFrame = bodyFrame;
|
||||
m_trailPoints.clear();
|
||||
}
|
||||
|
||||
if( bodyFrame==m_currentFrame )
|
||||
if (bodyFrame == m_currentFrame)
|
||||
m_trailPoints.push_back(m_body->GetInterpPosition());
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ void HudTrail::Render(Graphics::Renderer *r)
|
|||
float alpha = 1.f;
|
||||
const float decrement = 1.f / m_trailPoints.size();
|
||||
const Color tcolor = m_color;
|
||||
for (size_t i = m_trailPoints.size()-1; i > 0; i--) {
|
||||
for (size_t i = m_trailPoints.size() - 1; i > 0; i--) {
|
||||
tvts.push_back(-vector3f(curpos - m_trailPoints[i]));
|
||||
alpha -= decrement;
|
||||
colors.push_back(tcolor);
|
||||
|
|
|
@ -6,15 +6,14 @@
|
|||
|
||||
// trail drawn after an object to track motion
|
||||
|
||||
#include "libs.h"
|
||||
#include "Body.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/Drawables.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "libs.h"
|
||||
|
||||
class HudTrail
|
||||
{
|
||||
class HudTrail {
|
||||
public:
|
||||
HudTrail(Body *b, const Color&);
|
||||
HudTrail(Body *b, const Color &);
|
||||
void Update(float time);
|
||||
void Render(Graphics::Renderer *r);
|
||||
void Reset(const Frame *newFrame);
|
||||
|
|
|
@ -2,31 +2,32 @@
|
|||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "HyperspaceCloud.h"
|
||||
#include "libs.h"
|
||||
#include "Game.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "Lang.h"
|
||||
#include "perlin.h"
|
||||
#include "Pi.h"
|
||||
#include "Player.h"
|
||||
#include "Ship.h"
|
||||
#include "Space.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Material.h"
|
||||
#include "graphics/RenderState.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/VertexArray.h"
|
||||
#include "graphics/RenderState.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "GameSaveError.h"
|
||||
#include "libs.h"
|
||||
#include "perlin.h"
|
||||
|
||||
using namespace Graphics;
|
||||
|
||||
/** How long does a hyperspace cloud last for? 2 Days? */
|
||||
#define HYPERCLOUD_DURATION (60.0*60.0*24.0*2.0)
|
||||
#define HYPERCLOUD_DURATION (60.0 * 60.0 * 24.0 * 2.0)
|
||||
|
||||
HyperspaceCloud::HyperspaceCloud(Ship *s, double dueDate, bool isArrival) : m_isBeingKilled(false)
|
||||
HyperspaceCloud::HyperspaceCloud(Ship *s, double dueDate, bool isArrival) :
|
||||
m_isBeingKilled(false)
|
||||
{
|
||||
m_flags = Body::FLAG_CAN_MOVE_FRAME |
|
||||
Body::FLAG_LABEL_HIDDEN;
|
||||
Body::FLAG_LABEL_HIDDEN;
|
||||
m_ship = s;
|
||||
SetPhysRadius(0.0);
|
||||
SetClipRadius(1200.0);
|
||||
|
@ -37,7 +38,8 @@ HyperspaceCloud::HyperspaceCloud(Ship *s, double dueDate, bool isArrival) : m_is
|
|||
InitGraphics();
|
||||
}
|
||||
|
||||
HyperspaceCloud::HyperspaceCloud() : m_isBeingKilled(false)
|
||||
HyperspaceCloud::HyperspaceCloud() :
|
||||
m_isBeingKilled(false)
|
||||
{
|
||||
m_ship = 0;
|
||||
SetPhysRadius(0.0);
|
||||
|
@ -54,7 +56,7 @@ void HyperspaceCloud::InitGraphics()
|
|||
m_graphic.material.reset(Pi::renderer->CreateMaterial(desc));
|
||||
|
||||
Graphics::RenderStateDesc rsd;
|
||||
rsd.blendMode = BLEND_ALPHA_ONE;
|
||||
rsd.blendMode = BLEND_ALPHA_ONE;
|
||||
rsd.depthWrite = false;
|
||||
m_graphic.renderState = Pi::renderer->CreateRenderState(rsd);
|
||||
}
|
||||
|
@ -80,8 +82,7 @@ void HyperspaceCloud::SaveToJson(Json &jsonObj, Space *space)
|
|||
hyperspaceCloudObj["birth_date"] = m_birthdate;
|
||||
hyperspaceCloudObj["due"] = m_due;
|
||||
hyperspaceCloudObj["is_arrival"] = m_isArrival;
|
||||
if (m_ship)
|
||||
{
|
||||
if (m_ship) {
|
||||
Json shipObj = Json::object(); // Create JSON object to contain ship data.
|
||||
m_ship->ToJson(shipObj, space);
|
||||
hyperspaceCloudObj["ship"] = shipObj; // Add ship object to hyperpace cloud object.
|
||||
|
@ -102,10 +103,9 @@ void HyperspaceCloud::LoadFromJson(const Json &jsonObj, Space *space)
|
|||
m_due = hyperspaceCloudObj["due"];
|
||||
m_isArrival = hyperspaceCloudObj["is_arrival"];
|
||||
|
||||
if (hyperspaceCloudObj["ship"].is_object())
|
||||
{
|
||||
if (hyperspaceCloudObj["ship"].is_object()) {
|
||||
Json shipObj = hyperspaceCloudObj["ship"];
|
||||
m_ship = static_cast<Ship*>(Body::FromJson(shipObj, space));
|
||||
m_ship = static_cast<Ship *>(Body::FromJson(shipObj, space));
|
||||
}
|
||||
} catch (Json::type_error &) {
|
||||
throw SavedGameCorruptException();
|
||||
|
@ -120,7 +120,7 @@ void HyperspaceCloud::PostLoadFixup(Space *space)
|
|||
|
||||
void HyperspaceCloud::TimeStepUpdate(const float timeStep)
|
||||
{
|
||||
if( m_isBeingKilled )
|
||||
if (m_isBeingKilled)
|
||||
return;
|
||||
|
||||
SetPosition(GetPosition() + m_vel * timeStep);
|
||||
|
@ -144,8 +144,7 @@ void HyperspaceCloud::TimeStepUpdate(const float timeStep)
|
|||
}
|
||||
|
||||
// cloud expiration
|
||||
if( m_birthdate + HYPERCLOUD_DURATION <= Pi::game->GetTime() )
|
||||
{
|
||||
if (m_birthdate + HYPERCLOUD_DURATION <= Pi::game->GetTime()) {
|
||||
Pi::game->RemoveHyperspaceCloud(this);
|
||||
Pi::game->GetSpace()->KillBody(this);
|
||||
m_isBeingKilled = true;
|
||||
|
@ -162,8 +161,8 @@ Ship *HyperspaceCloud::EvictShip()
|
|||
static void make_circle_thing(VertexArray &va, float radius, const Color &colCenter, const Color &colEdge)
|
||||
{
|
||||
va.Add(vector3f(0.f, 0.f, 0.f), colCenter);
|
||||
for (float ang=0; ang<float(M_PI)*2.f; ang+=0.1f) {
|
||||
va.Add(vector3f(radius*sin(ang), radius*cos(ang), 0.0f), colEdge);
|
||||
for (float ang = 0; ang < float(M_PI) * 2.f; ang += 0.1f) {
|
||||
va.Add(vector3f(radius * sin(ang), radius * cos(ang), 0.0f), colEdge);
|
||||
}
|
||||
va.Add(vector3f(0.f, radius, 0.f), colEdge);
|
||||
}
|
||||
|
@ -171,13 +170,13 @@ static void make_circle_thing(VertexArray &va, float radius, const Color &colCen
|
|||
void HyperspaceCloud::UpdateInterpTransform(double alpha)
|
||||
{
|
||||
m_interpOrient = matrix3x3d::Identity();
|
||||
const vector3d oldPos = GetPosition() - m_vel*Pi::game->GetTimeStep();
|
||||
m_interpPos = alpha*GetPosition() + (1.0-alpha)*oldPos;
|
||||
const vector3d oldPos = GetPosition() - m_vel * Pi::game->GetTimeStep();
|
||||
m_interpPos = alpha * GetPosition() + (1.0 - alpha) * oldPos;
|
||||
}
|
||||
|
||||
void HyperspaceCloud::Render(Renderer *renderer, const Camera *camera, const vector3d &viewCoords, const matrix4x4d &viewTransform)
|
||||
{
|
||||
if( m_isBeingKilled )
|
||||
if (m_isBeingKilled)
|
||||
return;
|
||||
|
||||
matrix4x4d trans = matrix4x4d::Identity();
|
||||
|
@ -185,17 +184,17 @@ void HyperspaceCloud::Render(Renderer *renderer, const Camera *camera, const vec
|
|||
|
||||
// face the camera dammit
|
||||
vector3d zaxis = viewCoords.NormalizedSafe();
|
||||
vector3d xaxis = vector3d(0,1,0).Cross(zaxis).Normalized();
|
||||
vector3d xaxis = vector3d(0, 1, 0).Cross(zaxis).Normalized();
|
||||
vector3d yaxis = zaxis.Cross(xaxis);
|
||||
matrix4x4d rot = matrix4x4d::MakeRotMatrix(xaxis, yaxis, zaxis).Inverse();
|
||||
renderer->SetTransform(trans * rot);
|
||||
|
||||
// precise to the rendered frame (better than PHYSICS_HZ granularity)
|
||||
const double preciseTime = Pi::game->GetTime() + Pi::GetGameTickAlpha()*Pi::game->GetTimeStep();
|
||||
const double preciseTime = Pi::game->GetTime() + Pi::GetGameTickAlpha() * Pi::game->GetTimeStep();
|
||||
|
||||
// Flickering gradient circle, departure clouds are red and arrival clouds blue
|
||||
// XXX could just alter the scale instead of recreating the model
|
||||
const float radius = 1000.0f + 200.0f*float(noise(vector3d(10.0*preciseTime, 0, 0)));
|
||||
const float radius = 1000.0f + 200.0f * float(noise(vector3d(10.0 * preciseTime, 0, 0)));
|
||||
m_graphic.vertices->Clear();
|
||||
Color outerColor = m_isArrival ? Color::BLUE : Color::RED;
|
||||
outerColor.a = 0;
|
||||
|
|
|
@ -13,9 +13,9 @@ namespace Graphics {
|
|||
class Renderer;
|
||||
class VertexArray;
|
||||
class RenderState;
|
||||
}
|
||||
} // namespace Graphics
|
||||
|
||||
class HyperspaceCloud: public Body {
|
||||
class HyperspaceCloud : public Body {
|
||||
public:
|
||||
OBJDEF(HyperspaceCloud, Body, HYPERSPACECLOUD);
|
||||
HyperspaceCloud(Ship *, double dateDue, bool isArrival);
|
||||
|
@ -32,6 +32,7 @@ public:
|
|||
void SetIsArrival(bool isArrival);
|
||||
bool IsArrival() const { return m_isArrival; }
|
||||
virtual void UpdateInterpTransform(double alpha) override;
|
||||
|
||||
protected:
|
||||
virtual void SaveToJson(Json &jsonObj, Space *space) override;
|
||||
virtual void LoadFromJson(const Json &jsonObj, Space *space) override;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "IniConfig.h"
|
||||
#include "FileSystem.h"
|
||||
#include "StringRange.h"
|
||||
#include "libs.h"
|
||||
#include "utils.h"
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace FileSystem {
|
|||
class FileData;
|
||||
class FileSource;
|
||||
class FileSourceFS;
|
||||
}
|
||||
} // namespace FileSystem
|
||||
|
||||
class IniConfig {
|
||||
public:
|
||||
|
@ -38,12 +38,14 @@ public:
|
|||
float Float(const std::string &key, float defval = 0.0f) const { return Float("", key, defval); }
|
||||
std::string String(const std::string &key, const std::string &defval = std::string()) const { return String("", key, defval); }
|
||||
|
||||
bool HasSection(const std::string §ion) const {
|
||||
bool HasSection(const std::string §ion) const
|
||||
{
|
||||
SectionMapType::const_iterator it = m_map.find(section);
|
||||
return (it != m_map.end()) && (!it->second.empty());
|
||||
}
|
||||
|
||||
bool HasEntry(const std::string §ion, const std::string &key) const {
|
||||
bool HasEntry(const std::string §ion, const std::string &key) const
|
||||
{
|
||||
SectionMapType::const_iterator it = m_map.find(section);
|
||||
return (it != m_map.end()) && it->second.count(key);
|
||||
}
|
||||
|
|
144
src/Input.cpp
144
src/Input.cpp
|
@ -7,22 +7,22 @@
|
|||
|
||||
void Input::Init()
|
||||
{
|
||||
GameConfig *config = Pi::config;
|
||||
GameConfig *config = Pi::config;
|
||||
|
||||
joystickEnabled = (config->Int("EnableJoystick")) ? true : false;
|
||||
joystickEnabled = (config->Int("EnableJoystick")) ? true : false;
|
||||
mouseYInvert = (config->Int("InvertMouseY")) ? true : false;
|
||||
|
||||
InitJoysticks();
|
||||
InitJoysticks();
|
||||
}
|
||||
|
||||
void Input::InitGame()
|
||||
{
|
||||
//reset input states
|
||||
//reset input states
|
||||
keyState.clear();
|
||||
keyModState = 0;
|
||||
std::fill(mouseButton, mouseButton + COUNTOF(mouseButton), 0);
|
||||
std::fill(mouseMotion, mouseMotion + COUNTOF(mouseMotion), 0);
|
||||
for (std::map<SDL_JoystickID,JoystickState>::iterator stick = joysticks.begin(); stick != joysticks.end(); ++stick) {
|
||||
for (std::map<SDL_JoystickID, JoystickState>::iterator stick = joysticks.begin(); stick != joysticks.end(); ++stick) {
|
||||
JoystickState &state = stick->second;
|
||||
std::fill(state.buttons.begin(), state.buttons.end(), false);
|
||||
std::fill(state.hats.begin(), state.hats.end(), 0);
|
||||
|
@ -30,84 +30,84 @@ void Input::InitGame()
|
|||
}
|
||||
}
|
||||
|
||||
KeyBindings::ActionBinding* Input::AddActionBinding(std::string id, BindingGroup* group, KeyBindings::ActionBinding binding)
|
||||
KeyBindings::ActionBinding *Input::AddActionBinding(std::string id, BindingGroup *group, KeyBindings::ActionBinding binding)
|
||||
{
|
||||
// TODO: should we throw an error if we attempt to bind over an already-bound action?
|
||||
group->bindings[id] = BindingGroup::ENTRY_ACTION;
|
||||
// TODO: should we throw an error if we attempt to bind over an already-bound action?
|
||||
group->bindings[id] = BindingGroup::ENTRY_ACTION;
|
||||
|
||||
// Load from the config
|
||||
std::string config_str = Pi::config->String(id.c_str());
|
||||
if (config_str.length() > 0) binding.SetFromString(config_str);
|
||||
// Load from the config
|
||||
std::string config_str = Pi::config->String(id.c_str());
|
||||
if (config_str.length() > 0) binding.SetFromString(config_str);
|
||||
|
||||
return &(actionBindings[id] = binding);
|
||||
return &(actionBindings[id] = binding);
|
||||
}
|
||||
|
||||
KeyBindings::AxisBinding* Input::AddAxisBinding(std::string id, BindingGroup* group, KeyBindings::AxisBinding binding)
|
||||
KeyBindings::AxisBinding *Input::AddAxisBinding(std::string id, BindingGroup *group, KeyBindings::AxisBinding binding)
|
||||
{
|
||||
// TODO: should we throw an error if we attempt to bind over an already-bound axis?
|
||||
group->bindings[id] = BindingGroup::ENTRY_AXIS;
|
||||
// TODO: should we throw an error if we attempt to bind over an already-bound axis?
|
||||
group->bindings[id] = BindingGroup::ENTRY_AXIS;
|
||||
|
||||
// Load from the config
|
||||
std::string config_str = Pi::config->String(id.c_str());
|
||||
if (config_str.length() > 0) binding.SetFromString(config_str);
|
||||
// Load from the config
|
||||
std::string config_str = Pi::config->String(id.c_str());
|
||||
if (config_str.length() > 0) binding.SetFromString(config_str);
|
||||
|
||||
return &(axisBindings[id] = binding);
|
||||
return &(axisBindings[id] = binding);
|
||||
}
|
||||
|
||||
void Input::HandleSDLEvent(SDL_Event &event)
|
||||
{
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
keyState[event.key.keysym.sym] = true;
|
||||
keyModState = event.key.keysym.mod;
|
||||
onKeyPress.emit(&event.key.keysym);
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
keyState[event.key.keysym.sym] = false;
|
||||
keyModState = event.key.keysym.mod;
|
||||
onKeyRelease.emit(&event.key.keysym);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (event.button.button < COUNTOF(mouseButton)) {
|
||||
mouseButton[event.button.button] = 1;
|
||||
onMouseButtonDown.emit(event.button.button,
|
||||
event.button.x, event.button.y);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (event.button.button < COUNTOF(mouseButton)) {
|
||||
mouseButton[event.button.button] = 0;
|
||||
onMouseButtonUp.emit(event.button.button,
|
||||
event.button.x, event.button.y);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
onMouseWheel.emit(event.wheel.y > 0); // true = up
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
mouseMotion[0] += event.motion.xrel;
|
||||
mouseMotion[1] += event.motion.yrel;
|
||||
break;
|
||||
case SDL_JOYAXISMOTION:
|
||||
if (!joysticks[event.jaxis.which].joystick)
|
||||
break;
|
||||
if (event.jaxis.value == -32768)
|
||||
joysticks[event.jaxis.which].axes[event.jaxis.axis] = 1.f;
|
||||
else
|
||||
joysticks[event.jaxis.which].axes[event.jaxis.axis] = -event.jaxis.value / 32767.f;
|
||||
break;
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
if (!joysticks[event.jaxis.which].joystick)
|
||||
break;
|
||||
joysticks[event.jbutton.which].buttons[event.jbutton.button] = event.jbutton.state != 0;
|
||||
break;
|
||||
case SDL_JOYHATMOTION:
|
||||
if (!joysticks[event.jaxis.which].joystick)
|
||||
break;
|
||||
joysticks[event.jhat.which].hats[event.jhat.hat] = event.jhat.value;
|
||||
break;
|
||||
}
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
keyState[event.key.keysym.sym] = true;
|
||||
keyModState = event.key.keysym.mod;
|
||||
onKeyPress.emit(&event.key.keysym);
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
keyState[event.key.keysym.sym] = false;
|
||||
keyModState = event.key.keysym.mod;
|
||||
onKeyRelease.emit(&event.key.keysym);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (event.button.button < COUNTOF(mouseButton)) {
|
||||
mouseButton[event.button.button] = 1;
|
||||
onMouseButtonDown.emit(event.button.button,
|
||||
event.button.x, event.button.y);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (event.button.button < COUNTOF(mouseButton)) {
|
||||
mouseButton[event.button.button] = 0;
|
||||
onMouseButtonUp.emit(event.button.button,
|
||||
event.button.x, event.button.y);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
onMouseWheel.emit(event.wheel.y > 0); // true = up
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
mouseMotion[0] += event.motion.xrel;
|
||||
mouseMotion[1] += event.motion.yrel;
|
||||
break;
|
||||
case SDL_JOYAXISMOTION:
|
||||
if (!joysticks[event.jaxis.which].joystick)
|
||||
break;
|
||||
if (event.jaxis.value == -32768)
|
||||
joysticks[event.jaxis.which].axes[event.jaxis.axis] = 1.f;
|
||||
else
|
||||
joysticks[event.jaxis.which].axes[event.jaxis.axis] = -event.jaxis.value / 32767.f;
|
||||
break;
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
if (!joysticks[event.jaxis.which].joystick)
|
||||
break;
|
||||
joysticks[event.jbutton.which].buttons[event.jbutton.button] = event.jbutton.state != 0;
|
||||
break;
|
||||
case SDL_JOYHATMOTION:
|
||||
if (!joysticks[event.jaxis.which].joystick)
|
||||
break;
|
||||
joysticks[event.jhat.which].hats[event.jhat.hat] = event.jhat.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Input::InitJoysticks()
|
||||
|
@ -139,7 +139,7 @@ std::string Input::JoystickName(int joystick)
|
|||
std::string Input::JoystickGUIDString(int joystick)
|
||||
{
|
||||
const int guidBufferLen = 33; // as documented by SDL
|
||||
char guidBuffer[guidBufferLen];
|
||||
char guidBuffer[guidBufferLen];
|
||||
|
||||
SDL_JoystickGetGUIDString(joysticks[joystick].guid, guidBuffer, guidBufferLen);
|
||||
return std::string(guidBuffer);
|
||||
|
|
32
src/Input.h
32
src/Input.h
|
@ -4,14 +4,15 @@
|
|||
#ifndef INPUT_H
|
||||
#define INPUT_H
|
||||
|
||||
#include "utils.h"
|
||||
#include "KeyBindings.h"
|
||||
#include "utils.h"
|
||||
|
||||
class Input {
|
||||
// TODO: better decouple these two classes.
|
||||
friend class Pi;
|
||||
|
||||
public:
|
||||
Input() { };
|
||||
Input(){};
|
||||
void Init();
|
||||
void InitGame();
|
||||
|
||||
|
@ -27,25 +28,27 @@ public:
|
|||
};
|
||||
|
||||
struct BindingPage {
|
||||
BindingGroup* GetBindingGroup(std::string id) { return &groups[id]; }
|
||||
BindingGroup *GetBindingGroup(std::string id) { return &groups[id]; }
|
||||
|
||||
std::map<std::string, BindingGroup> groups;
|
||||
};
|
||||
|
||||
BindingPage* GetBindingPage(std::string id) { return &bindingPages[id]; }
|
||||
BindingPage *GetBindingPage(std::string id) { return &bindingPages[id]; }
|
||||
std::map<std::string, BindingPage> GetBindingPages() { return bindingPages; }
|
||||
|
||||
// Creates a new action binding, copying the provided binding.
|
||||
// The returned binding pointer points to the actual binding.
|
||||
KeyBindings::ActionBinding* AddActionBinding(std::string id, BindingGroup* group, KeyBindings::ActionBinding binding);
|
||||
KeyBindings::ActionBinding* GetActionBinding(std::string id) {
|
||||
KeyBindings::ActionBinding *AddActionBinding(std::string id, BindingGroup *group, KeyBindings::ActionBinding binding);
|
||||
KeyBindings::ActionBinding *GetActionBinding(std::string id)
|
||||
{
|
||||
return actionBindings.count(id) ? &actionBindings[id] : nullptr;
|
||||
}
|
||||
|
||||
// Creates a new axis binding, copying the provided binding.
|
||||
// The returned binding pointer points to the actual binding.
|
||||
KeyBindings::AxisBinding* AddAxisBinding(std::string id, BindingGroup* group, KeyBindings::AxisBinding binding);
|
||||
KeyBindings::AxisBinding* GetAxisBinding(std::string id) {
|
||||
KeyBindings::AxisBinding *AddAxisBinding(std::string id, BindingGroup *group, KeyBindings::AxisBinding binding);
|
||||
KeyBindings::AxisBinding *GetAxisBinding(std::string id)
|
||||
{
|
||||
return axisBindings.count(id) ? &axisBindings[id] : nullptr;
|
||||
}
|
||||
|
||||
|
@ -85,12 +88,13 @@ public:
|
|||
int MouseButtonState(int button) { return mouseButton[button]; }
|
||||
void SetMouseButtonState(int button, bool state) { mouseButton[button] = state; }
|
||||
|
||||
void GetMouseMotion(int motion[2]) {
|
||||
memcpy(motion, mouseMotion, sizeof(int)*2);
|
||||
void GetMouseMotion(int motion[2])
|
||||
{
|
||||
memcpy(motion, mouseMotion, sizeof(int) * 2);
|
||||
}
|
||||
|
||||
sigc::signal<void, SDL_Keysym*> onKeyPress;
|
||||
sigc::signal<void, SDL_Keysym*> onKeyRelease;
|
||||
sigc::signal<void, SDL_Keysym *> onKeyPress;
|
||||
sigc::signal<void, SDL_Keysym *> onKeyRelease;
|
||||
sigc::signal<void, int, int, int> onMouseButtonUp;
|
||||
sigc::signal<void, int, int, int> onMouseButtonDown;
|
||||
sigc::signal<void, bool> onMouseWheel;
|
||||
|
@ -99,14 +103,14 @@ private:
|
|||
void HandleSDLEvent(SDL_Event &ev);
|
||||
void InitJoysticks();
|
||||
|
||||
std::map<SDL_Keycode,bool> keyState;
|
||||
std::map<SDL_Keycode, bool> keyState;
|
||||
int keyModState;
|
||||
char mouseButton[6];
|
||||
int mouseMotion[2];
|
||||
|
||||
bool joystickEnabled;
|
||||
bool mouseYInvert;
|
||||
std::map<SDL_JoystickID,JoystickState> joysticks;
|
||||
std::map<SDL_JoystickID, JoystickState> joysticks;
|
||||
|
||||
std::map<std::string, BindingPage> bindingPages;
|
||||
std::map<std::string, KeyBindings::ActionBinding> actionBindings;
|
||||
|
|
|
@ -2,24 +2,25 @@
|
|||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "Intro.h"
|
||||
#include "Pi.h"
|
||||
#include "Lang.h"
|
||||
#include "Easing.h"
|
||||
#include "Lang.h"
|
||||
#include "Pi.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "graphics/TextureBuilder.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "scenegraph/SceneGraph.h"
|
||||
#include "scenegraph/ModelSkin.h"
|
||||
#include "scenegraph/SceneGraph.h"
|
||||
#include <algorithm>
|
||||
|
||||
struct PiRngWrapper {
|
||||
unsigned int operator()(unsigned int n) {
|
||||
unsigned int operator()(unsigned int n)
|
||||
{
|
||||
return Pi::rng.Int32(n);
|
||||
}
|
||||
};
|
||||
|
||||
Intro::Intro(Graphics::Renderer *r, int width, int height)
|
||||
: Cutscene(r, width, height)
|
||||
Intro::Intro(Graphics::Renderer *r, int width, int height) :
|
||||
Cutscene(r, width, height)
|
||||
{
|
||||
using Graphics::Light;
|
||||
|
||||
|
@ -38,21 +39,21 @@ Intro::Intro(Graphics::Renderer *r, int width, int height)
|
|||
SceneGraph::Model *model = Pi::FindModel(ShipType::types[i].modelName)->MakeInstance();
|
||||
model->SetThrust(vector3f(0.f, 0.f, -0.6f), vector3f(0.f));
|
||||
if (ShipType::types[i].isGlobalColorDefined) model->SetThrusterColor(ShipType::types[i].globalThrusterColor);
|
||||
for (int j=0; j<THRUSTER_MAX; j++) {
|
||||
for (int j = 0; j < THRUSTER_MAX; j++) {
|
||||
if (!ShipType::types[i].isDirectionColorDefined[j]) continue;
|
||||
vector3f dir;
|
||||
switch (j) {
|
||||
case THRUSTER_FORWARD: dir = vector3f(0.0, 0.0, 1.0); break;
|
||||
case THRUSTER_REVERSE: dir = vector3f(0.0, 0.0, -1.0); break;
|
||||
case THRUSTER_LEFT: dir = vector3f(1.0, 0.0, 0.0); break;
|
||||
case THRUSTER_RIGHT: dir = vector3f(-1.0, 0.0, 0.0); break;
|
||||
case THRUSTER_UP: dir = vector3f(1.0, 0.0, 0.0); break;
|
||||
case THRUSTER_DOWN: dir = vector3f(-1.0, 0.0, 0.0); break;
|
||||
case THRUSTER_FORWARD: dir = vector3f(0.0, 0.0, 1.0); break;
|
||||
case THRUSTER_REVERSE: dir = vector3f(0.0, 0.0, -1.0); break;
|
||||
case THRUSTER_LEFT: dir = vector3f(1.0, 0.0, 0.0); break;
|
||||
case THRUSTER_RIGHT: dir = vector3f(-1.0, 0.0, 0.0); break;
|
||||
case THRUSTER_UP: dir = vector3f(1.0, 0.0, 0.0); break;
|
||||
case THRUSTER_DOWN: dir = vector3f(-1.0, 0.0, 0.0); break;
|
||||
}
|
||||
model->SetThrusterColor(dir, ShipType::types[i].directionThrusterColor[j]);
|
||||
}
|
||||
const Uint32 numMats = model->GetNumMaterials();
|
||||
for( Uint32 m=0; m<numMats; m++ ) {
|
||||
for (Uint32 m = 0; m < numMats; m++) {
|
||||
RefCountedPtr<Graphics::Material> mat = model->GetMaterialByIndex(m);
|
||||
mat->specialParameter0 = nullptr;
|
||||
}
|
||||
|
@ -69,16 +70,16 @@ Intro::Intro(Graphics::Renderer *r, int width, int height)
|
|||
|
||||
// double-width viewport, centred, then offset 1/6th to centre on the left
|
||||
// 2/3rds of the screen, to the left of the menu
|
||||
m_spinnerLeft = int(float(w)*-.5f - float(w)/6.f);
|
||||
m_spinnerWidth = w*2;
|
||||
m_spinnerRatio = w*2.f/h;
|
||||
m_spinnerLeft = int(float(w) * -.5f - float(w) / 6.f);
|
||||
m_spinnerWidth = w * 2;
|
||||
m_spinnerRatio = w * 2.f / h;
|
||||
|
||||
m_needReset = true;
|
||||
}
|
||||
|
||||
Intro::~Intro()
|
||||
{
|
||||
for (std::vector<SceneGraph::Model*>::iterator i = m_models.begin(); i != m_models.end(); ++i)
|
||||
for (std::vector<SceneGraph::Model *>::iterator i = m_models.begin(); i != m_models.end(); ++i)
|
||||
delete (*i);
|
||||
}
|
||||
|
||||
|
@ -88,18 +89,18 @@ void Intro::Reset(float _time)
|
|||
if (m_modelIndex == m_models.size()) m_modelIndex = 0;
|
||||
m_skin.SetRandomColors(Pi::rng);
|
||||
m_skin.Apply(m_model);
|
||||
if(m_model->SupportsPatterns())
|
||||
m_model->SetPattern(Pi::rng.Int32(0, m_model->GetNumPatterns()-1));
|
||||
if (m_model->SupportsPatterns())
|
||||
m_model->SetPattern(Pi::rng.Int32(0, m_model->GetNumPatterns() - 1));
|
||||
m_zoomBegin = -10000.0f;
|
||||
m_zoomEnd = -m_model->GetDrawClipRadius()*1.7f;
|
||||
m_zoomEnd = -m_model->GetDrawClipRadius() * 1.7f;
|
||||
m_dist = m_zoomBegin;
|
||||
m_startTime = _time;
|
||||
m_needReset = false;
|
||||
}
|
||||
|
||||
// stage end times
|
||||
static const float ZOOM_IN_END = 2.0f;
|
||||
static const float WAIT_END = 12.0f;
|
||||
static const float ZOOM_IN_END = 2.0f;
|
||||
static const float WAIT_END = 12.0f;
|
||||
static const float ZOOM_OUT_END = 14.0f;
|
||||
|
||||
void Intro::Draw(float _time)
|
||||
|
@ -107,11 +108,11 @@ void Intro::Draw(float _time)
|
|||
if (m_needReset)
|
||||
Reset(_time);
|
||||
|
||||
float duration = _time-m_startTime;
|
||||
float duration = _time - m_startTime;
|
||||
|
||||
// zoom in
|
||||
if (duration < ZOOM_IN_END)
|
||||
m_dist = Clamp(Easing::Quad::EaseOut(duration, m_zoomBegin, m_zoomEnd-m_zoomBegin, 2.0f), m_zoomBegin, m_zoomEnd);
|
||||
m_dist = Clamp(Easing::Quad::EaseOut(duration, m_zoomBegin, m_zoomEnd - m_zoomBegin, 2.0f), m_zoomBegin, m_zoomEnd);
|
||||
|
||||
// wait
|
||||
else if (duration < WAIT_END) {
|
||||
|
@ -120,7 +121,7 @@ void Intro::Draw(float _time)
|
|||
|
||||
// zoom out
|
||||
else if (duration < ZOOM_OUT_END)
|
||||
m_dist = Clamp(Easing::Quad::EaseIn(duration-WAIT_END, m_zoomEnd, m_zoomBegin-m_zoomEnd, 2.0f), m_zoomBegin, m_zoomEnd);
|
||||
m_dist = Clamp(Easing::Quad::EaseIn(duration - WAIT_END, m_zoomEnd, m_zoomBegin - m_zoomEnd, 2.0f), m_zoomBegin, m_zoomEnd);
|
||||
|
||||
// done
|
||||
else
|
||||
|
@ -136,7 +137,7 @@ void Intro::Draw(float _time)
|
|||
|
||||
// XXX all this stuff will be gone when intro uses a Camera
|
||||
// rotate background by time, and a bit extra Z so it's not so flat
|
||||
matrix4x4d brot = matrix4x4d::RotateXMatrix(-0.25*_time) * matrix4x4d::RotateZMatrix(0.6);
|
||||
matrix4x4d brot = matrix4x4d::RotateXMatrix(-0.25 * _time) * matrix4x4d::RotateZMatrix(0.6);
|
||||
m_renderer->ClearDepthBuffer();
|
||||
m_background->Draw(brot);
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
#ifndef _INTRO_H
|
||||
#define _INTRO_H
|
||||
|
||||
#include "Cutscene.h"
|
||||
#include "Background.h"
|
||||
#include "Cutscene.h"
|
||||
#include "ShipType.h"
|
||||
#include "scenegraph/ModelSkin.h"
|
||||
|
||||
|
@ -19,7 +19,7 @@ private:
|
|||
void Reset(float time);
|
||||
bool m_needReset;
|
||||
|
||||
std::vector<SceneGraph::Model*> m_models;
|
||||
std::vector<SceneGraph::Model *> m_models;
|
||||
SceneGraph::ModelSkin m_skin;
|
||||
|
||||
float m_startTime;
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
template <typename Container, typename T = void>
|
||||
class IterationProxy {
|
||||
public:
|
||||
IterationProxy(Container& container) : m_container(container) { }
|
||||
IterationProxy(Container &container) :
|
||||
m_container(container) {}
|
||||
typename Container::iterator begin() { return m_container.begin(); }
|
||||
typename Container::iterator end() { return m_container.end(); }
|
||||
typename Container::const_iterator begin() const { return m_container.begin(); }
|
||||
|
@ -21,16 +22,17 @@ public:
|
|||
typename Container::const_iterator cend() { return m_container.cend(); }
|
||||
|
||||
private:
|
||||
Container& m_container;
|
||||
Container &m_container;
|
||||
};
|
||||
|
||||
// This specialized version is for containers that provide a random access iterator, we provide an operator[] in this case
|
||||
template <typename Container>
|
||||
class IterationProxy<Container,
|
||||
typename std::enable_if<std::is_same<typename std::iterator_traits<typename Container::iterator>::iterator_category,
|
||||
std::random_access_iterator_tag>::value>::type> {
|
||||
std::random_access_iterator_tag>::value>::type> {
|
||||
public:
|
||||
IterationProxy(Container& container) : m_container(container) { }
|
||||
IterationProxy(Container &container) :
|
||||
m_container(container) {}
|
||||
typename Container::iterator begin() { return m_container.begin(); }
|
||||
typename Container::iterator end() { return m_container.end(); }
|
||||
typename Container::const_iterator begin() const { return m_container.begin(); }
|
||||
|
@ -42,10 +44,10 @@ public:
|
|||
typename Container::const_reference operator[](int i) const { return *(m_container.begin() + i); }
|
||||
|
||||
private:
|
||||
Container& m_container;
|
||||
Container &m_container;
|
||||
};
|
||||
|
||||
template <typename Container>
|
||||
inline IterationProxy<Container> MakeIterationProxy(Container& container) { return IterationProxy<Container>(container); }
|
||||
inline IterationProxy<Container> MakeIterationProxy(Container &container) { return IterationProxy<Container>(container); }
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,11 @@ Job::~Job()
|
|||
//static
|
||||
unsigned long long Job::Handle::s_nextId(0);
|
||||
|
||||
Job::Handle::Handle(Job* job, JobQueue* queue, JobClient* client) : m_id(++s_nextId), m_job(job), m_queue(queue), m_client(client)
|
||||
Job::Handle::Handle(Job *job, JobQueue *queue, JobClient *client) :
|
||||
m_id(++s_nextId),
|
||||
m_job(job),
|
||||
m_queue(queue),
|
||||
m_client(client)
|
||||
{
|
||||
assert(!m_job->GetHandle());
|
||||
m_job->SetHandle(this);
|
||||
|
@ -31,7 +35,7 @@ void Job::Handle::Unlink()
|
|||
assert(m_job->GetHandle() == this);
|
||||
m_job->ClearHandle();
|
||||
}
|
||||
JobClient* client = m_client; // This Job::Handle may be deleted by the client, so clear it before
|
||||
JobClient *client = m_client; // This Job::Handle may be deleted by the client, so clear it before
|
||||
m_job = nullptr;
|
||||
m_queue = nullptr;
|
||||
m_client = nullptr;
|
||||
|
@ -39,7 +43,11 @@ void Job::Handle::Unlink()
|
|||
client->RemoveJob(this); // This might delete this Job::Handle, so the object must be cleared before
|
||||
}
|
||||
|
||||
Job::Handle::Handle(Handle&& other) : m_id(other.m_id), m_job(other.m_job), m_queue(other.m_queue), m_client(other.m_client)
|
||||
Job::Handle::Handle(Handle &&other) :
|
||||
m_id(other.m_id),
|
||||
m_job(other.m_job),
|
||||
m_queue(other.m_queue),
|
||||
m_client(other.m_client)
|
||||
{
|
||||
if (m_job) {
|
||||
assert(m_job->GetHandle() == &other);
|
||||
|
@ -51,7 +59,7 @@ Job::Handle::Handle(Handle&& other) : m_id(other.m_id), m_job(other.m_job), m_qu
|
|||
other.m_client = nullptr;
|
||||
}
|
||||
|
||||
Job::Handle& Job::Handle::operator=(Handle&& other)
|
||||
Job::Handle &Job::Handle::operator=(Handle &&other)
|
||||
{
|
||||
if (m_job && m_queue)
|
||||
m_queue->Cancel(m_job);
|
||||
|
@ -81,12 +89,11 @@ Job::Handle::~Handle()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
AsyncJobQueue::AsyncJobQueue(Uint32 numRunners) :
|
||||
m_shutdown(false)
|
||||
{
|
||||
// Want to limit this for now to the maximum number of threads defined in the class
|
||||
numRunners = std::min( numRunners, MAX_THREADS );
|
||||
numRunners = std::min(numRunners, MAX_THREADS);
|
||||
|
||||
m_queueLock = SDL_CreateMutex();
|
||||
m_queueWaitCond = SDL_CreateCond();
|
||||
|
@ -112,7 +119,7 @@ AsyncJobQueue::~AsyncJobQueue()
|
|||
// else is running one of our functions). Both the flag and the mutex
|
||||
// must be owned by the runner, because we may not exist when it's
|
||||
// checked.
|
||||
for (std::vector<JobRunner*>::iterator i = m_runners.begin(); i != m_runners.end(); ++i) {
|
||||
for (std::vector<JobRunner *>::iterator i = m_runners.begin(); i != m_runners.end(); ++i) {
|
||||
SDL_LockMutex((*i)->GetQueueDestroyingLock());
|
||||
(*i)->SetQueueDestroyed();
|
||||
SDL_UnlockMutex((*i)->GetQueueDestroyingLock());
|
||||
|
@ -120,20 +127,20 @@ AsyncJobQueue::~AsyncJobQueue()
|
|||
|
||||
const uint32_t numThreads = m_runners.size();
|
||||
// delete the runners. this will tear down their underlying threads
|
||||
for (std::vector<JobRunner*>::iterator i = m_runners.begin(); i != m_runners.end(); ++i)
|
||||
for (std::vector<JobRunner *>::iterator i = m_runners.begin(); i != m_runners.end(); ++i)
|
||||
delete (*i);
|
||||
|
||||
// delete any remaining jobs
|
||||
for (std::deque<Job*>::iterator i = m_queue.begin(); i != m_queue.end(); ++i)
|
||||
for (std::deque<Job *>::iterator i = m_queue.begin(); i != m_queue.end(); ++i)
|
||||
delete (*i);
|
||||
for (uint32_t threadIdx=0; threadIdx<numThreads; threadIdx++) {
|
||||
for (std::deque<Job*>::iterator i = m_finished[threadIdx].begin(); i != m_finished[threadIdx].end(); ++i) {
|
||||
for (uint32_t threadIdx = 0; threadIdx < numThreads; threadIdx++) {
|
||||
for (std::deque<Job *>::iterator i = m_finished[threadIdx].begin(); i != m_finished[threadIdx].end(); ++i) {
|
||||
delete (*i);
|
||||
}
|
||||
}
|
||||
|
||||
// only us left now, we can clean up and get out of here
|
||||
for (uint32_t threadIdx=0; threadIdx<numThreads; threadIdx++) {
|
||||
for (uint32_t threadIdx = 0; threadIdx < numThreads; threadIdx++) {
|
||||
SDL_DestroyMutex(m_finishedLock[threadIdx]);
|
||||
}
|
||||
SDL_DestroyCond(m_queueWaitCond);
|
||||
|
@ -177,7 +184,6 @@ Job *AsyncJobQueue::GetJob()
|
|||
job = m_queue.front();
|
||||
m_queue.pop_front();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(m_queueLock);
|
||||
|
@ -200,9 +206,9 @@ Uint32 AsyncJobQueue::FinishJobs()
|
|||
Uint32 finished = 0;
|
||||
|
||||
const uint32_t numRunners = m_runners.size();
|
||||
for( uint32_t i=0; i<numRunners ; ++i) {
|
||||
for (uint32_t i = 0; i < numRunners; ++i) {
|
||||
SDL_LockMutex(m_finishedLock[i]);
|
||||
if( m_finished[i].empty() ) {
|
||||
if (m_finished[i].empty()) {
|
||||
SDL_UnlockMutex(m_finishedLock[i]);
|
||||
continue;
|
||||
}
|
||||
|
@ -213,7 +219,7 @@ Uint32 AsyncJobQueue::FinishJobs()
|
|||
assert(job);
|
||||
|
||||
// if its already been cancelled then its taken care of, so we just forget about it
|
||||
if(!job->cancelled) {
|
||||
if (!job->cancelled) {
|
||||
job->UnlinkHandle();
|
||||
job->OnFinish();
|
||||
finished++;
|
||||
|
@ -225,16 +231,17 @@ Uint32 AsyncJobQueue::FinishJobs()
|
|||
return finished;
|
||||
}
|
||||
|
||||
void AsyncJobQueue::Cancel(Job *job) {
|
||||
void AsyncJobQueue::Cancel(Job *job)
|
||||
{
|
||||
// lock both queues, so we know that all jobs will stay put
|
||||
SDL_LockMutex(m_queueLock);
|
||||
const uint32_t numRunners = m_runners.size();
|
||||
for( uint32_t i=0; i<numRunners ; ++i) {
|
||||
for (uint32_t i = 0; i < numRunners; ++i) {
|
||||
SDL_LockMutex(m_finishedLock[i]);
|
||||
}
|
||||
|
||||
// check the waiting list. if its there then it hasn't run yet. just forget about it
|
||||
for (std::deque<Job*>::iterator i = m_queue.begin(); i != m_queue.end(); ++i) {
|
||||
for (std::deque<Job *>::iterator i = m_queue.begin(); i != m_queue.end(); ++i) {
|
||||
if (*i == job) {
|
||||
i = m_queue.erase(i);
|
||||
delete job;
|
||||
|
@ -244,8 +251,8 @@ void AsyncJobQueue::Cancel(Job *job) {
|
|||
|
||||
// check the finshed list. if its there then it can't be cancelled, because
|
||||
// its alread finished! we remove it because the caller is saying "I don't care"
|
||||
for( uint32_t iRunner=0; iRunner<numRunners ; ++iRunner) {
|
||||
for (std::deque<Job*>::iterator i = m_finished[iRunner].begin(); i != m_finished[iRunner].end(); ++i) {
|
||||
for (uint32_t iRunner = 0; iRunner < numRunners; ++iRunner) {
|
||||
for (std::deque<Job *>::iterator i = m_finished[iRunner].begin(); i != m_finished[iRunner].end(); ++i) {
|
||||
if (*i == job) {
|
||||
i = m_finished[iRunner].erase(i);
|
||||
delete job;
|
||||
|
@ -260,7 +267,7 @@ void AsyncJobQueue::Cancel(Job *job) {
|
|||
job->OnCancel();
|
||||
|
||||
unlock:
|
||||
for( uint32_t i=0; i<numRunners ; ++i) {
|
||||
for (uint32_t i = 0; i < numRunners; ++i) {
|
||||
SDL_UnlockMutex(m_finishedLock[i]);
|
||||
}
|
||||
SDL_UnlockMutex(m_queueLock);
|
||||
|
@ -298,7 +305,7 @@ AsyncJobQueue::JobRunner::~JobRunner()
|
|||
// entry point for SDL thread. we simply get back onto a method. convenience mostly
|
||||
int AsyncJobQueue::JobRunner::Trampoline(void *data)
|
||||
{
|
||||
JobRunner *jr = static_cast<JobRunner*>(data);
|
||||
JobRunner *jr = static_cast<JobRunner *>(data);
|
||||
jr->Main();
|
||||
return 0;
|
||||
}
|
||||
|
@ -361,13 +368,12 @@ void AsyncJobQueue::JobRunner::SetQueueDestroyed()
|
|||
m_queueDestroyed = true;
|
||||
}
|
||||
|
||||
|
||||
SyncJobQueue::~SyncJobQueue()
|
||||
{
|
||||
// delete any remaining jobs
|
||||
for (Job* j : m_queue)
|
||||
for (Job *j : m_queue)
|
||||
delete j;
|
||||
for (Job* j : m_finished)
|
||||
for (Job *j : m_finished)
|
||||
delete j;
|
||||
}
|
||||
|
||||
|
@ -389,7 +395,7 @@ Uint32 SyncJobQueue::FinishJobs()
|
|||
m_finished.pop_front();
|
||||
|
||||
// if its already been cancelled then its taken care of, so we just forget about it
|
||||
if(!job->cancelled) {
|
||||
if (!job->cancelled) {
|
||||
job->UnlinkHandle();
|
||||
job->OnFinish();
|
||||
finished++;
|
||||
|
@ -400,9 +406,10 @@ Uint32 SyncJobQueue::FinishJobs()
|
|||
return finished;
|
||||
}
|
||||
|
||||
void SyncJobQueue::Cancel(Job *job) {
|
||||
void SyncJobQueue::Cancel(Job *job)
|
||||
{
|
||||
// check the waiting list. if its there then it hasn't run yet. just forget about it
|
||||
for (std::deque<Job*>::iterator i = m_queue.begin(); i != m_queue.end(); ++i) {
|
||||
for (std::deque<Job *>::iterator i = m_queue.begin(); i != m_queue.end(); ++i) {
|
||||
if (*i == job) {
|
||||
i = m_queue.erase(i);
|
||||
delete job;
|
||||
|
@ -412,7 +419,7 @@ void SyncJobQueue::Cancel(Job *job) {
|
|||
|
||||
// check the finshed list. if its there then it can't be cancelled, because
|
||||
// its alread finished! we remove it because the caller is saying "I don't care"
|
||||
for (std::deque<Job*>::iterator i = m_finished.begin(); i != m_finished.end(); ++i) {
|
||||
for (std::deque<Job *>::iterator i = m_finished.begin(); i != m_finished.end(); ++i) {
|
||||
if (*i == job) {
|
||||
i = m_finished.erase(i);
|
||||
delete job;
|
||||
|
@ -434,7 +441,7 @@ Uint32 SyncJobQueue::RunJobs(Uint32 count)
|
|||
if (m_queue.empty())
|
||||
break;
|
||||
|
||||
Job* job = m_queue.front();
|
||||
Job *job = m_queue.front();
|
||||
m_queue.pop_front();
|
||||
job->OnRun();
|
||||
executed++;
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
#ifndef JOBQUEUE_H
|
||||
#define JOBQUEUE_H
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include "SDL_thread.h"
|
||||
#include <vector>
|
||||
|
||||
static const Uint32 MAX_THREADS = 64;
|
||||
|
||||
|
@ -36,41 +36,47 @@ public:
|
|||
// moveable.
|
||||
class Handle {
|
||||
public:
|
||||
Handle() : m_id(++s_nextId), m_job(nullptr), m_queue(nullptr), m_client(nullptr) { }
|
||||
Handle(Handle&& other);
|
||||
Handle& operator=(Handle&& other);
|
||||
Handle() :
|
||||
m_id(++s_nextId),
|
||||
m_job(nullptr),
|
||||
m_queue(nullptr),
|
||||
m_client(nullptr) {}
|
||||
Handle(Handle &&other);
|
||||
Handle &operator=(Handle &&other);
|
||||
~Handle();
|
||||
|
||||
Handle(const Handle&) = delete;
|
||||
Handle& operator=(const Handle&) = delete;
|
||||
Handle(const Handle &) = delete;
|
||||
Handle &operator=(const Handle &) = delete;
|
||||
|
||||
bool HasJob() const { return m_job != nullptr; }
|
||||
Job* GetJob() const { return m_job; }
|
||||
Job *GetJob() const { return m_job; }
|
||||
|
||||
bool operator<(const Handle& other) const { return m_id < other.m_id; }
|
||||
bool operator<(const Handle &other) const { return m_id < other.m_id; }
|
||||
|
||||
private:
|
||||
friend class Job;
|
||||
friend class AsyncJobQueue;
|
||||
friend class SyncJobQueue;
|
||||
|
||||
Handle(Job* job, JobQueue* queue, JobClient* client);
|
||||
Handle(Job *job, JobQueue *queue, JobClient *client);
|
||||
void Unlink();
|
||||
|
||||
static unsigned long long s_nextId;
|
||||
|
||||
unsigned long long m_id;
|
||||
Job* m_job;
|
||||
JobQueue* m_queue;
|
||||
JobClient* m_client;
|
||||
Job *m_job;
|
||||
JobQueue *m_queue;
|
||||
JobClient *m_client;
|
||||
};
|
||||
|
||||
public:
|
||||
Job() : cancelled(false), m_handle(nullptr) {}
|
||||
Job() :
|
||||
cancelled(false),
|
||||
m_handle(nullptr) {}
|
||||
virtual ~Job();
|
||||
|
||||
Job(const Job&) = delete;
|
||||
Job& operator=(const Job&) = delete;
|
||||
Job(const Job &) = delete;
|
||||
Job &operator=(const Job &) = delete;
|
||||
|
||||
virtual void OnRun() = 0;
|
||||
virtual void OnFinish() = 0;
|
||||
|
@ -82,26 +88,25 @@ private:
|
|||
friend class JobRunner;
|
||||
|
||||
void UnlinkHandle();
|
||||
const Handle* GetHandle() const { return m_handle; }
|
||||
void SetHandle(Handle* handle) { m_handle = handle; }
|
||||
const Handle *GetHandle() const { return m_handle; }
|
||||
void SetHandle(Handle *handle) { m_handle = handle; }
|
||||
void ClearHandle() { m_handle = nullptr; }
|
||||
|
||||
bool cancelled;
|
||||
Handle* m_handle;
|
||||
Handle *m_handle;
|
||||
};
|
||||
|
||||
|
||||
// the queue management class. create one from the main thread, and feed your
|
||||
// jobs do it. it will take care of the rest
|
||||
class JobQueue {
|
||||
public:
|
||||
JobQueue() = default;
|
||||
JobQueue(const JobQueue&) = delete;
|
||||
JobQueue& operator=(const JobQueue&) = delete;
|
||||
JobQueue(const JobQueue &) = delete;
|
||||
JobQueue &operator=(const JobQueue &) = delete;
|
||||
|
||||
// numRunners is the number of jobs to run in parallel. right now its the
|
||||
// same as the number of threads, but there's no reason that it has to be
|
||||
virtual ~JobQueue() { }
|
||||
virtual ~JobQueue() {}
|
||||
|
||||
// call from the main thread to add a job to the queue. the job should be
|
||||
// allocated with new. the queue will delete it once its its completed
|
||||
|
@ -185,14 +190,14 @@ private:
|
|||
Job *GetJob();
|
||||
void Finish(Job *job, const uint8_t threadIdx);
|
||||
|
||||
std::deque<Job*> m_queue;
|
||||
std::deque<Job *> m_queue;
|
||||
SDL_mutex *m_queueLock;
|
||||
SDL_cond *m_queueWaitCond;
|
||||
|
||||
std::deque<Job*> m_finished[MAX_THREADS];
|
||||
std::deque<Job *> m_finished[MAX_THREADS];
|
||||
SDL_mutex *m_finishedLock[MAX_THREADS];
|
||||
|
||||
std::vector<JobRunner*> m_runners;
|
||||
std::vector<JobRunner *> m_runners;
|
||||
|
||||
bool m_shutdown;
|
||||
};
|
||||
|
@ -226,36 +231,46 @@ public:
|
|||
Uint32 RunJobs(Uint32 count = 1);
|
||||
|
||||
private:
|
||||
std::deque<Job*> m_queue;
|
||||
std::deque<Job*> m_finished;
|
||||
std::deque<Job *> m_queue;
|
||||
std::deque<Job *> m_finished;
|
||||
};
|
||||
|
||||
class JobClient {
|
||||
public:
|
||||
virtual void Order(Job* job) = 0;
|
||||
virtual void RemoveJob(Job::Handle* handle) = 0;
|
||||
virtual void Order(Job *job) = 0;
|
||||
virtual void RemoveJob(Job::Handle *handle) = 0;
|
||||
virtual ~JobClient() {}
|
||||
};
|
||||
|
||||
class JobSet : public JobClient {
|
||||
public:
|
||||
JobSet(JobQueue* queue) : m_queue(queue) { }
|
||||
JobSet(JobSet&& other) : m_queue(other.m_queue), m_jobs(std::move(other.m_jobs)) { other.m_queue = nullptr; }
|
||||
JobSet& operator=(JobSet&& other) { m_queue = other.m_queue; m_jobs = std::move(other.m_jobs); other.m_queue = nullptr; return *this; }
|
||||
JobSet(JobQueue *queue) :
|
||||
m_queue(queue) {}
|
||||
JobSet(JobSet &&other) :
|
||||
m_queue(other.m_queue),
|
||||
m_jobs(std::move(other.m_jobs)) { other.m_queue = nullptr; }
|
||||
JobSet &operator=(JobSet &&other)
|
||||
{
|
||||
m_queue = other.m_queue;
|
||||
m_jobs = std::move(other.m_jobs);
|
||||
other.m_queue = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JobSet(const JobSet&) = delete;
|
||||
JobSet& operator=(const JobSet& other) = delete;
|
||||
JobSet(const JobSet &) = delete;
|
||||
JobSet &operator=(const JobSet &other) = delete;
|
||||
|
||||
virtual void Order(Job* job) {
|
||||
virtual void Order(Job *job)
|
||||
{
|
||||
auto x = m_jobs.insert(m_queue->Queue(job, this));
|
||||
assert(x.second);
|
||||
}
|
||||
virtual void RemoveJob(Job::Handle* handle) { m_jobs.erase(*handle); }
|
||||
virtual void RemoveJob(Job::Handle *handle) { m_jobs.erase(*handle); }
|
||||
|
||||
bool IsEmpty() const { return m_jobs.empty(); }
|
||||
|
||||
private:
|
||||
JobQueue* m_queue;
|
||||
JobQueue *m_queue;
|
||||
std::set<Job::Handle> m_jobs;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
#include "JsonUtils.h"
|
||||
#include "utils.h"
|
||||
#include "base64/base64.hpp"
|
||||
#include "FileSystem.h"
|
||||
#include "GZipFormat.h"
|
||||
#include "base64/base64.hpp"
|
||||
#include "utils.h"
|
||||
#include <cmath>
|
||||
|
||||
extern "C" {
|
||||
#ifdef __GNUC__
|
||||
|
@ -41,10 +41,11 @@ namespace {
|
|||
static const vector3d zeroVector3d(0.0);
|
||||
static const Quaternionf identityQuaternionf(1.0f, 0.0f, 0.0f, 0.0f);
|
||||
static const Quaterniond identityQuaterniond(1.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace JsonUtils {
|
||||
Json LoadJson(RefCountedPtr<FileSystem::FileData> fd) {
|
||||
Json LoadJson(RefCountedPtr<FileSystem::FileData> fd)
|
||||
{
|
||||
if (!fd) return Json();
|
||||
|
||||
Json out;
|
||||
|
@ -94,8 +95,10 @@ namespace JsonUtils {
|
|||
Json rootNode;
|
||||
try {
|
||||
// Allow loading files in JSON format as well as CBOR
|
||||
if (plain_data[0] == '{') return Json::parse(plain_data);
|
||||
else return Json::from_cbor(plain_data);
|
||||
if (plain_data[0] == '{')
|
||||
return Json::parse(plain_data);
|
||||
else
|
||||
return Json::from_cbor(plain_data);
|
||||
} catch (Json::parse_error &e) {
|
||||
Output("error in JSON file '%s': %s\n", file->GetInfo().GetPath().c_str(), e.what());
|
||||
return nullptr;
|
||||
|
@ -104,8 +107,7 @@ namespace JsonUtils {
|
|||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace JsonUtils
|
||||
|
||||
#define USE_STRING_VERSIONS
|
||||
|
||||
|
@ -167,11 +169,9 @@ void MatrixToJson(Json &jsonObj, const matrix3x3f &mat)
|
|||
Matrix3x3fToStr(mat, str, 512);
|
||||
jsonObj = str;
|
||||
#else
|
||||
jsonObj = Json::array({
|
||||
mat[0], mat[1], mat[2],
|
||||
jsonObj = Json::array({ mat[0], mat[1], mat[2],
|
||||
mat[3], mat[4], mat[5],
|
||||
mat[6], mat[7], mat[8]
|
||||
});
|
||||
mat[6], mat[7], mat[8] });
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -184,11 +184,9 @@ void MatrixToJson(Json &jsonObj, const matrix3x3d &mat)
|
|||
Matrix3x3dToStr(mat, str, 512);
|
||||
jsonObj = str;
|
||||
#else
|
||||
jsonObj = Json::array({
|
||||
mat[0], mat[1], mat[2],
|
||||
jsonObj = Json::array({ mat[0], mat[1], mat[2],
|
||||
mat[3], mat[4], mat[5],
|
||||
mat[6], mat[7], mat[8]
|
||||
});
|
||||
mat[6], mat[7], mat[8] });
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -202,10 +200,22 @@ void MatrixToJson(Json &jsonObj, const matrix4x4f &mat)
|
|||
jsonObj = str;
|
||||
#else
|
||||
jsonObj = Json::array({
|
||||
mat[0], mat[1], mat[2], mat[3],
|
||||
mat[4], mat[5], mat[6], mat[7],
|
||||
mat[8], mat[9], mat[10], mat[11],
|
||||
mat[12], mat[13], mat[14], mat[15],
|
||||
mat[0],
|
||||
mat[1],
|
||||
mat[2],
|
||||
mat[3],
|
||||
mat[4],
|
||||
mat[5],
|
||||
mat[6],
|
||||
mat[7],
|
||||
mat[8],
|
||||
mat[9],
|
||||
mat[10],
|
||||
mat[11],
|
||||
mat[12],
|
||||
mat[13],
|
||||
mat[14],
|
||||
mat[15],
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
@ -220,10 +230,22 @@ void MatrixToJson(Json &jsonObj, const matrix4x4d &mat)
|
|||
jsonObj = str;
|
||||
#else
|
||||
jsonObj = Json::array({
|
||||
mat[0], mat[1], mat[2], mat[3],
|
||||
mat[4], mat[5], mat[6], mat[7],
|
||||
mat[8], mat[9], mat[10], mat[11],
|
||||
mat[12], mat[13], mat[14], mat[15],
|
||||
mat[0],
|
||||
mat[1],
|
||||
mat[2],
|
||||
mat[3],
|
||||
mat[4],
|
||||
mat[5],
|
||||
mat[6],
|
||||
mat[7],
|
||||
mat[8],
|
||||
mat[9],
|
||||
mat[10],
|
||||
mat[11],
|
||||
mat[12],
|
||||
mat[13],
|
||||
mat[14],
|
||||
mat[15],
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
@ -357,24 +379,24 @@ void JsonToMatrix(matrix3x3f *pMat, const Json &jsonObj)
|
|||
void JsonToMatrix(matrix3x3d *pMat, const Json &jsonObj)
|
||||
{
|
||||
PROFILE_SCOPED()
|
||||
#ifdef USE_STRING_VERSIONS
|
||||
if (!jsonObj.is_string()) {
|
||||
*pMat = matrix3x3dIdentity;
|
||||
return;
|
||||
}
|
||||
std::string matStr = jsonObj;
|
||||
StrToMatrix3x3d(matStr.c_str(), *pMat);
|
||||
#else
|
||||
(*pMat)[0] = jsonObj[0];
|
||||
(*pMat)[1] = jsonObj[1];
|
||||
(*pMat)[2] = jsonObj[2];
|
||||
(*pMat)[3] = jsonObj[3];
|
||||
(*pMat)[4] = jsonObj[4];
|
||||
(*pMat)[5] = jsonObj[5];
|
||||
(*pMat)[6] = jsonObj[6];
|
||||
(*pMat)[7] = jsonObj[7];
|
||||
(*pMat)[8] = jsonObj[8];
|
||||
#endif
|
||||
#ifdef USE_STRING_VERSIONS
|
||||
if (!jsonObj.is_string()) {
|
||||
*pMat = matrix3x3dIdentity;
|
||||
return;
|
||||
}
|
||||
std::string matStr = jsonObj;
|
||||
StrToMatrix3x3d(matStr.c_str(), *pMat);
|
||||
#else
|
||||
(*pMat)[0] = jsonObj[0];
|
||||
(*pMat)[1] = jsonObj[1];
|
||||
(*pMat)[2] = jsonObj[2];
|
||||
(*pMat)[3] = jsonObj[3];
|
||||
(*pMat)[4] = jsonObj[4];
|
||||
(*pMat)[5] = jsonObj[5];
|
||||
(*pMat)[6] = jsonObj[6];
|
||||
(*pMat)[7] = jsonObj[7];
|
||||
(*pMat)[8] = jsonObj[8];
|
||||
#endif
|
||||
}
|
||||
|
||||
void JsonToMatrix(matrix4x4f *pMat, const Json &jsonObj)
|
||||
|
|
|
@ -4,30 +4,30 @@
|
|||
#ifndef _JSON_UTILS_H
|
||||
#define _JSON_UTILS_H
|
||||
|
||||
#include "Color.h"
|
||||
#include "Json.h"
|
||||
#include "vector3.h"
|
||||
#include "Quaternion.h"
|
||||
#include "RefCounted.h"
|
||||
#include "matrix3x3.h"
|
||||
#include "matrix4x4.h"
|
||||
#include "Color.h"
|
||||
#include "RefCounted.h"
|
||||
#include "vector3.h"
|
||||
|
||||
namespace FileSystem {
|
||||
class FileSource;
|
||||
class FileData;
|
||||
}
|
||||
class FileSource;
|
||||
class FileData;
|
||||
} // namespace FileSystem
|
||||
|
||||
namespace JsonUtils {
|
||||
// Low-level load JSON from a file descriptor.
|
||||
Json LoadJson(RefCountedPtr<FileSystem::FileData> fd);
|
||||
// Load a JSON file from a path and a file source.
|
||||
Json LoadJsonFile(const std::string &filename, FileSystem::FileSource &source);
|
||||
// Load a JSON file from the game's data sources, optionally applying all
|
||||
// files with the the name <filename>.patch as Json Merge Patch (RFC 7386) files
|
||||
Json LoadJsonDataFile(const std::string &filename, bool with_merge = true);
|
||||
// Loads an optionally-gzipped, optionally-CBOR encoded JSON file from the specified source.
|
||||
Json LoadJsonSaveFile(const std::string &filename, FileSystem::FileSource &source);
|
||||
}
|
||||
// Low-level load JSON from a file descriptor.
|
||||
Json LoadJson(RefCountedPtr<FileSystem::FileData> fd);
|
||||
// Load a JSON file from a path and a file source.
|
||||
Json LoadJsonFile(const std::string &filename, FileSystem::FileSource &source);
|
||||
// Load a JSON file from the game's data sources, optionally applying all
|
||||
// files with the the name <filename>.patch as Json Merge Patch (RFC 7386) files
|
||||
Json LoadJsonDataFile(const std::string &filename, bool with_merge = true);
|
||||
// Loads an optionally-gzipped, optionally-CBOR encoded JSON file from the specified source.
|
||||
Json LoadJsonSaveFile(const std::string &filename, FileSystem::FileSource &source);
|
||||
} // namespace JsonUtils
|
||||
|
||||
// To-JSON functions. These are called explicitly, and are passed a reference to the object to fill.
|
||||
void VectorToJson(Json &jsonObj, const vector3f &vec);
|
||||
|
@ -43,10 +43,14 @@ void ColorToJson(Json &jsonObj, const Color4ub &col);
|
|||
void BinStrToJson(Json &jsonObj, const std::string &str);
|
||||
|
||||
// Drivers for automatic serialization of custom types. These are implicitly called by assigning to a Json object.
|
||||
template<typename T> void to_json(Json &obj, const vector3<T> &vec) { VectorToJson(obj, vec); }
|
||||
template<typename T> void to_json(Json &obj, const Quaternion<T> &vec) { QuaternionToJson(obj, vec); }
|
||||
template<typename T> void to_json(Json &obj, const matrix3x3<T> &mat) { MatrixToJson(obj, mat); }
|
||||
template<typename T> void to_json(Json &obj, const matrix4x4<T> &mat) { MatrixToJson(obj, mat); }
|
||||
template <typename T>
|
||||
void to_json(Json &obj, const vector3<T> &vec) { VectorToJson(obj, vec); }
|
||||
template <typename T>
|
||||
void to_json(Json &obj, const Quaternion<T> &vec) { QuaternionToJson(obj, vec); }
|
||||
template <typename T>
|
||||
void to_json(Json &obj, const matrix3x3<T> &mat) { MatrixToJson(obj, mat); }
|
||||
template <typename T>
|
||||
void to_json(Json &obj, const matrix4x4<T> &mat) { MatrixToJson(obj, mat); }
|
||||
inline void to_json(Json &obj, const Color3ub &col) { ColorToJson(obj, col); }
|
||||
inline void to_json(Json &obj, const Color4ub &col) { ColorToJson(obj, col); }
|
||||
|
||||
|
@ -63,10 +67,14 @@ void JsonToColor(Color3ub *pCol, const Json &jsonObj);
|
|||
void JsonToColor(Color4ub *pCol, const Json &jsonObj);
|
||||
std::string JsonToBinStr(const Json &jsonObj);
|
||||
|
||||
template<typename T> void from_json(const Json &obj, vector3<T> &vec) { JsonToVector(&vec, obj); }
|
||||
template<typename T> void from_json(const Json &obj, Quaternion<T> &vec) { JsonToQuaternion(&vec, obj); }
|
||||
template<typename T> void from_json(const Json &obj, matrix3x3<T> &vec) { JsonToMatrix(&vec, obj); }
|
||||
template<typename T> void from_json(const Json &obj, matrix4x4<T> &vec) { JsonToMatrix(&vec, obj); }
|
||||
template <typename T>
|
||||
void from_json(const Json &obj, vector3<T> &vec) { JsonToVector(&vec, obj); }
|
||||
template <typename T>
|
||||
void from_json(const Json &obj, Quaternion<T> &vec) { JsonToQuaternion(&vec, obj); }
|
||||
template <typename T>
|
||||
void from_json(const Json &obj, matrix3x3<T> &vec) { JsonToMatrix(&vec, obj); }
|
||||
template <typename T>
|
||||
void from_json(const Json &obj, matrix4x4<T> &vec) { JsonToMatrix(&vec, obj); }
|
||||
inline void from_json(const Json &obj, Color3ub &col) { JsonToColor(&col, obj); }
|
||||
inline void from_json(const Json &obj, Color4ub &col) { JsonToColor(&col, obj); }
|
||||
|
||||
|
|
1095
src/KeyBindings.cpp
1095
src/KeyBindings.cpp
File diff suppressed because it is too large
Load Diff
|
@ -17,64 +17,68 @@ namespace KeyBindings {
|
|||
};
|
||||
|
||||
struct KeyBinding {
|
||||
public:
|
||||
// constructors
|
||||
static bool FromString(const char *str, KeyBinding &binding);
|
||||
static KeyBinding FromString(const char *str);
|
||||
static KeyBinding FromKeyMod(SDL_Keycode key, SDL_Keymod mod);
|
||||
static KeyBinding FromJoystickButton(Uint8 joystick, Uint8 button);
|
||||
static KeyBinding FromJoystickHat(Uint8 joystick, Uint8 hat, Uint8 direction);
|
||||
public:
|
||||
// constructors
|
||||
static bool FromString(const char *str, KeyBinding &binding);
|
||||
static KeyBinding FromString(const char *str);
|
||||
static KeyBinding FromKeyMod(SDL_Keycode key, SDL_Keymod mod);
|
||||
static KeyBinding FromJoystickButton(Uint8 joystick, Uint8 button);
|
||||
static KeyBinding FromJoystickHat(Uint8 joystick, Uint8 hat, Uint8 direction);
|
||||
|
||||
KeyBinding() : type(BINDING_DISABLED) {
|
||||
u.keyboard.key = SDLK_UNKNOWN;
|
||||
u.keyboard.mod = KMOD_NONE;
|
||||
}
|
||||
KeyBinding(SDL_Keycode key, SDL_Keymod mod = KMOD_NONE) : type(KEYBOARD_KEY) {
|
||||
u.keyboard.key = key;
|
||||
u.keyboard.mod = mod;
|
||||
}
|
||||
KeyBinding() :
|
||||
type(BINDING_DISABLED)
|
||||
{
|
||||
u.keyboard.key = SDLK_UNKNOWN;
|
||||
u.keyboard.mod = KMOD_NONE;
|
||||
}
|
||||
KeyBinding(SDL_Keycode key, SDL_Keymod mod = KMOD_NONE) :
|
||||
type(KEYBOARD_KEY)
|
||||
{
|
||||
u.keyboard.key = key;
|
||||
u.keyboard.mod = mod;
|
||||
}
|
||||
|
||||
std::string ToString() const; // for serialisation
|
||||
std::string Description() const; // for display to the user
|
||||
std::string ToString() const; // for serialisation
|
||||
std::string Description() const; // for display to the user
|
||||
|
||||
bool IsActive() const;
|
||||
bool Matches(const SDL_Keysym *sym) const;
|
||||
bool Matches(const SDL_JoyButtonEvent *joy) const;
|
||||
bool Matches(const SDL_JoyHatEvent *joy) const;
|
||||
bool IsActive() const;
|
||||
bool Matches(const SDL_Keysym *sym) const;
|
||||
bool Matches(const SDL_JoyButtonEvent *joy) const;
|
||||
bool Matches(const SDL_JoyHatEvent *joy) const;
|
||||
|
||||
void Clear() { memset(this, 0, sizeof(*this)); }
|
||||
void Clear() { memset(this, 0, sizeof(*this)); }
|
||||
|
||||
bool Enabled() const { return (type != BINDING_DISABLED); }
|
||||
bool Enabled() const { return (type != BINDING_DISABLED); }
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &oss, const KeyBinding &kb);
|
||||
friend std::ostream &operator<<(std::ostream &oss, const KeyBinding &kb);
|
||||
|
||||
private:
|
||||
Type type;
|
||||
union {
|
||||
struct {
|
||||
SDL_Keycode key;
|
||||
SDL_Keymod mod;
|
||||
} keyboard;
|
||||
private:
|
||||
Type type;
|
||||
union {
|
||||
struct {
|
||||
SDL_Keycode key;
|
||||
SDL_Keymod mod;
|
||||
} keyboard;
|
||||
|
||||
struct {
|
||||
Uint8 joystick;
|
||||
Uint8 button;
|
||||
} joystickButton;
|
||||
struct {
|
||||
Uint8 joystick;
|
||||
Uint8 button;
|
||||
} joystickButton;
|
||||
|
||||
struct {
|
||||
Uint8 joystick;
|
||||
Uint8 hat;
|
||||
Uint8 direction;
|
||||
} joystickHat;
|
||||
struct {
|
||||
Uint8 joystick;
|
||||
Uint8 hat;
|
||||
Uint8 direction;
|
||||
} joystickHat;
|
||||
|
||||
/* TODO: implement binding mouse buttons.
|
||||
/* TODO: implement binding mouse buttons.
|
||||
struct {
|
||||
Uint8 button;
|
||||
// TODO: implement binding multiple clicks as their own action.
|
||||
Uint8 clicks;
|
||||
} mouseButton;
|
||||
*/
|
||||
} u;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct ActionBinding {
|
||||
|
@ -84,14 +88,15 @@ namespace KeyBindings {
|
|||
sigc::signal<void> onPress;
|
||||
sigc::signal<void> onRelease;
|
||||
|
||||
ActionBinding() { }
|
||||
ActionBinding(KeyBinding b1, KeyBinding b2 = KeyBinding())
|
||||
: binding1(b1), binding2(b2) { }
|
||||
ActionBinding() {}
|
||||
ActionBinding(KeyBinding b1, KeyBinding b2 = KeyBinding()) :
|
||||
binding1(b1),
|
||||
binding2(b2) {}
|
||||
// This constructor is just a programmer shortcut.
|
||||
ActionBinding(SDL_Keycode k1, SDL_Keycode k2 = SDLK_UNKNOWN)
|
||||
{
|
||||
binding1 = KeyBinding(k1);
|
||||
if(k2 != SDLK_UNKNOWN) binding2 = KeyBinding(k2);
|
||||
if (k2 != SDLK_UNKNOWN) binding2 = KeyBinding(k2);
|
||||
}
|
||||
|
||||
void SetFromString(const char *str);
|
||||
|
@ -110,47 +115,58 @@ namespace KeyBindings {
|
|||
};
|
||||
|
||||
struct JoyAxisBinding {
|
||||
public:
|
||||
JoyAxisBinding() : joystick(JOYSTICK_DISABLED), axis(0), direction(POSITIVE), deadzone(0.0f), sensitivity(1.0f) { }
|
||||
JoyAxisBinding(Uint8 joystick_, Uint8 axis_, AxisDirection direction_, float deadzone_ = 0.0f, float sensitivity_ = 1.0f)
|
||||
: joystick(joystick_), axis(axis_), direction(direction_), deadzone(deadzone_), sensitivity(sensitivity_) { }
|
||||
public:
|
||||
JoyAxisBinding() :
|
||||
joystick(JOYSTICK_DISABLED),
|
||||
axis(0),
|
||||
direction(POSITIVE),
|
||||
deadzone(0.0f),
|
||||
sensitivity(1.0f) {}
|
||||
JoyAxisBinding(Uint8 joystick_, Uint8 axis_, AxisDirection direction_, float deadzone_ = 0.0f, float sensitivity_ = 1.0f) :
|
||||
joystick(joystick_),
|
||||
axis(axis_),
|
||||
direction(direction_),
|
||||
deadzone(deadzone_),
|
||||
sensitivity(sensitivity_) {}
|
||||
|
||||
float GetValue() const;
|
||||
std::string Description() const;
|
||||
float GetValue() const;
|
||||
std::string Description() const;
|
||||
|
||||
void Clear() {
|
||||
joystick = JOYSTICK_DISABLED;
|
||||
axis = 0;
|
||||
direction = POSITIVE;
|
||||
deadzone = 0.0f;
|
||||
sensitivity = 1.0f;
|
||||
}
|
||||
void Clear()
|
||||
{
|
||||
joystick = JOYSTICK_DISABLED;
|
||||
axis = 0;
|
||||
direction = POSITIVE;
|
||||
deadzone = 0.0f;
|
||||
sensitivity = 1.0f;
|
||||
}
|
||||
|
||||
bool Enabled() const { return (joystick != JOYSTICK_DISABLED); }
|
||||
bool Enabled() const { return (joystick != JOYSTICK_DISABLED); }
|
||||
|
||||
static bool FromString(const char *str, JoyAxisBinding &binding);
|
||||
static JoyAxisBinding FromString(const char *str);
|
||||
std::string ToString() const;
|
||||
static bool FromString(const char *str, JoyAxisBinding &binding);
|
||||
static JoyAxisBinding FromString(const char *str);
|
||||
std::string ToString() const;
|
||||
|
||||
bool Matches(const SDL_Event *event) const;
|
||||
bool IsActive() const;
|
||||
bool Matches(const SDL_Event *event) const;
|
||||
bool IsActive() const;
|
||||
|
||||
bool IsInverted() { return direction == NEGATIVE; }
|
||||
AxisDirection GetDirection() { return direction; }
|
||||
void SetDirection(AxisDirection dir) { direction = dir; }
|
||||
bool IsInverted() { return direction == NEGATIVE; }
|
||||
AxisDirection GetDirection() { return direction; }
|
||||
void SetDirection(AxisDirection dir) { direction = dir; }
|
||||
|
||||
float GetDeadzone() { return deadzone; }
|
||||
void SetDeadzone(float dz) { deadzone = dz; }
|
||||
float GetDeadzone() { return deadzone; }
|
||||
void SetDeadzone(float dz) { deadzone = dz; }
|
||||
|
||||
float GetSensitivity() { return sensitivity; }
|
||||
void SetSensitivity(float sens) { sensitivity = sens; }
|
||||
private:
|
||||
enum { JOYSTICK_DISABLED = Uint8(-1) };
|
||||
Uint8 joystick;
|
||||
Uint8 axis;
|
||||
AxisDirection direction;
|
||||
float deadzone;
|
||||
float sensitivity;
|
||||
float GetSensitivity() { return sensitivity; }
|
||||
void SetSensitivity(float sens) { sensitivity = sens; }
|
||||
|
||||
private:
|
||||
enum { JOYSTICK_DISABLED = Uint8(-1) };
|
||||
Uint8 joystick;
|
||||
Uint8 axis;
|
||||
AxisDirection direction;
|
||||
float deadzone;
|
||||
float sensitivity;
|
||||
};
|
||||
|
||||
struct AxisBinding {
|
||||
|
@ -158,12 +174,15 @@ namespace KeyBindings {
|
|||
KeyBinding positive;
|
||||
KeyBinding negative;
|
||||
|
||||
AxisBinding() { }
|
||||
AxisBinding(JoyAxisBinding ax, KeyBinding pos = KeyBinding(), KeyBinding neg = KeyBinding())
|
||||
: axis(ax), positive(pos), negative(neg) { }
|
||||
AxisBinding() {}
|
||||
AxisBinding(JoyAxisBinding ax, KeyBinding pos = KeyBinding(), KeyBinding neg = KeyBinding()) :
|
||||
axis(ax),
|
||||
positive(pos),
|
||||
negative(neg) {}
|
||||
// This constructor is just a programmer shortcut.
|
||||
AxisBinding(SDL_Keycode k1, SDL_Keycode k2)
|
||||
: positive(KeyBinding(k1)), negative(KeyBinding(k2)) { }
|
||||
AxisBinding(SDL_Keycode k1, SDL_Keycode k2) :
|
||||
positive(KeyBinding(k1)),
|
||||
negative(KeyBinding(k2)) {}
|
||||
|
||||
sigc::signal<void, float> onAxis;
|
||||
|
||||
|
@ -189,11 +208,11 @@ namespace KeyBindings {
|
|||
|
||||
void DispatchSDLEvent(const SDL_Event *event);
|
||||
|
||||
#define KEY_BINDING(name,a,b,c,d) extern ActionBinding name;
|
||||
#define AXIS_BINDING(name,a,b,c) extern JoyAxisBinding name;
|
||||
#define KEY_BINDING(name, a, b, c, d) extern ActionBinding name;
|
||||
#define AXIS_BINDING(name, a, b, c) extern JoyAxisBinding name;
|
||||
#include "KeyBindings.inc.h"
|
||||
|
||||
#define BINDING_PAGE(name) extern const BindingPrototype BINDING_PROTOS_ ## name[];
|
||||
#define BINDING_PAGE(name) extern const BindingPrototype BINDING_PROTOS_##name[];
|
||||
#include "KeyBindings.inc.h"
|
||||
|
||||
} // namespace KeyBindings
|
||||
|
|
362
src/Lang.cpp
362
src/Lang.cpp
|
@ -1,231 +1,231 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "libs.h"
|
||||
#include "Lang.h"
|
||||
#include "FileSystem.h"
|
||||
#include "StringRange.h"
|
||||
#include "utils.h"
|
||||
#include "text/TextSupport.h"
|
||||
#include "JsonUtils.h"
|
||||
#include "StringRange.h"
|
||||
#include "libs.h"
|
||||
#include "text/TextSupport.h"
|
||||
#include "utils.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace Lang {
|
||||
|
||||
static bool ident_head(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_');
|
||||
}
|
||||
static bool ident_head(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_');
|
||||
}
|
||||
|
||||
static bool ident_tail(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_');
|
||||
}
|
||||
static bool ident_tail(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_');
|
||||
}
|
||||
|
||||
static bool valid_token(const std::string &token)
|
||||
{
|
||||
if (token.empty()) return false;
|
||||
if (!ident_head(token[0])) return false;
|
||||
for (unsigned int i = 1; i < token.size(); i++)
|
||||
if (!ident_tail(token[i])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Resource::Load()
|
||||
{
|
||||
if (m_loaded)
|
||||
static bool valid_token(const std::string &token)
|
||||
{
|
||||
if (token.empty()) return false;
|
||||
if (!ident_head(token[0])) return false;
|
||||
for (unsigned int i = 1; i < token.size(); i++)
|
||||
if (!ident_tail(token[i])) return false;
|
||||
return true;
|
||||
|
||||
std::string filename = "lang/" + m_name + "/" + m_langCode + ".json";
|
||||
Json data = JsonUtils::LoadJsonDataFile(filename);
|
||||
if (data.is_null()) {
|
||||
Output("couldn't read language file '%s'\n", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Json::iterator i = data.begin(); i != data.end(); ++i) {
|
||||
const std::string token = i.key();
|
||||
if (token.empty()) {
|
||||
Output("%s: found empty token, skipping it\n", filename.c_str());
|
||||
continue;
|
||||
}
|
||||
if (!valid_token(token)) {
|
||||
Output("%s: invalid token '%s', skipping it\n", filename.c_str(), token.c_str());
|
||||
continue;
|
||||
bool Resource::Load()
|
||||
{
|
||||
if (m_loaded)
|
||||
return true;
|
||||
|
||||
std::string filename = "lang/" + m_name + "/" + m_langCode + ".json";
|
||||
Json data = JsonUtils::LoadJsonDataFile(filename);
|
||||
if (data.is_null()) {
|
||||
Output("couldn't read language file '%s'\n", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Json message = i.value()["message"];
|
||||
if (message.is_null()) {
|
||||
Output("%s: no 'message' key for token '%s', skipping it\n", filename.c_str(), token.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!message.is_string()) {
|
||||
Output("%s: value for token '%s' is not a string, skipping it\n", filename.c_str(), token.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string text = message;
|
||||
if (text.empty()) {
|
||||
Output("%s: empty value for token '%s', skipping it\n", filename.c_str(), token.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// extracted quoted string
|
||||
if (text[0] == '"' && text[text.size()-1] == '"')
|
||||
text = text.substr(1, text.size()-2);
|
||||
|
||||
// adjust for escaped newlines
|
||||
{
|
||||
std::string adjustedText;
|
||||
adjustedText.reserve(text.size());
|
||||
|
||||
unsigned int ii;
|
||||
for (ii = 0; ii < text.size()-1; ii++) {
|
||||
const char *c = &text[ii];
|
||||
if (c[0] == '\\' && c[1] == 'n') {
|
||||
ii++;
|
||||
adjustedText += '\n';
|
||||
}
|
||||
else
|
||||
adjustedText += *c;
|
||||
for (Json::iterator i = data.begin(); i != data.end(); ++i) {
|
||||
const std::string token = i.key();
|
||||
if (token.empty()) {
|
||||
Output("%s: found empty token, skipping it\n", filename.c_str());
|
||||
continue;
|
||||
}
|
||||
if (ii != text.size())
|
||||
adjustedText += text[ii++];
|
||||
assert(ii == text.size());
|
||||
text = adjustedText;
|
||||
if (!valid_token(token)) {
|
||||
Output("%s: invalid token '%s', skipping it\n", filename.c_str(), token.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
Json message = i.value()["message"];
|
||||
if (message.is_null()) {
|
||||
Output("%s: no 'message' key for token '%s', skipping it\n", filename.c_str(), token.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!message.is_string()) {
|
||||
Output("%s: value for token '%s' is not a string, skipping it\n", filename.c_str(), token.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string text = message;
|
||||
if (text.empty()) {
|
||||
Output("%s: empty value for token '%s', skipping it\n", filename.c_str(), token.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
// extracted quoted string
|
||||
if (text[0] == '"' && text[text.size() - 1] == '"')
|
||||
text = text.substr(1, text.size() - 2);
|
||||
|
||||
// adjust for escaped newlines
|
||||
{
|
||||
std::string adjustedText;
|
||||
adjustedText.reserve(text.size());
|
||||
|
||||
unsigned int ii;
|
||||
for (ii = 0; ii < text.size() - 1; ii++) {
|
||||
const char *c = &text[ii];
|
||||
if (c[0] == '\\' && c[1] == 'n') {
|
||||
ii++;
|
||||
adjustedText += '\n';
|
||||
} else
|
||||
adjustedText += *c;
|
||||
}
|
||||
if (ii != text.size())
|
||||
adjustedText += text[ii++];
|
||||
assert(ii == text.size());
|
||||
text = adjustedText;
|
||||
}
|
||||
|
||||
m_strings[token] = text;
|
||||
}
|
||||
|
||||
m_strings[token] = text;
|
||||
m_loaded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_loaded = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string &Resource::Get(const std::string &token) const
|
||||
{
|
||||
std::map<std::string,std::string>::const_iterator i = m_strings.find(token);
|
||||
if (i == m_strings.end()) {
|
||||
static const std::string empty;
|
||||
return empty;
|
||||
}
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
std::vector<std::string> Resource::GetAvailableLanguages(const std::string &resourceName)
|
||||
{
|
||||
std::vector<std::string> languages;
|
||||
|
||||
for (FileSystem::FileEnumerator files(FileSystem::gameDataFiles, "lang/" + resourceName); !files.Finished(); files.Next()) {
|
||||
assert(files.Current().IsFile());
|
||||
const std::string &path = files.Current().GetPath();
|
||||
if (ends_with_ci(path, ".json")) {
|
||||
const std::string name = files.Current().GetName();
|
||||
languages.push_back(name.substr(0, name.size() - 5));
|
||||
const std::string &Resource::Get(const std::string &token) const
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator i = m_strings.find(token);
|
||||
if (i == m_strings.end()) {
|
||||
static const std::string empty;
|
||||
return empty;
|
||||
}
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
return languages;
|
||||
}
|
||||
std::vector<std::string> Resource::GetAvailableLanguages(const std::string &resourceName)
|
||||
{
|
||||
std::vector<std::string> languages;
|
||||
|
||||
for (FileSystem::FileEnumerator files(FileSystem::gameDataFiles, "lang/" + resourceName); !files.Finished(); files.Next()) {
|
||||
assert(files.Current().IsFile());
|
||||
const std::string &path = files.Current().GetPath();
|
||||
if (ends_with_ci(path, ".json")) {
|
||||
const std::string name = files.Current().GetName();
|
||||
languages.push_back(name.substr(0, name.size() - 5));
|
||||
}
|
||||
}
|
||||
|
||||
// XXX we're allocating a KB for each translatable string
|
||||
// that's... not very nice (though I guess it "doesn't matter" with virtual memory and multi-GB of RAM)
|
||||
static const int STRING_RECORD_SIZE = 1024;
|
||||
return languages;
|
||||
}
|
||||
|
||||
// XXX we're allocating a KB for each translatable string
|
||||
// that's... not very nice (though I guess it "doesn't matter" with virtual memory and multi-GB of RAM)
|
||||
static const int STRING_RECORD_SIZE = 1024;
|
||||
#define DECLARE_STRING(x) char x[STRING_RECORD_SIZE];
|
||||
#include "LangStrings.inc.h"
|
||||
#undef DECLARE_STRING
|
||||
|
||||
//
|
||||
// declaring value type as const char* so that we can give out a const reference to the real
|
||||
// token map without allowing external code to modify token text
|
||||
// unfortunately, this means we don't have write access internally either,
|
||||
// so we have to const_cast<> to initialise the token values.
|
||||
// this could be avoided by using a custom class for the value type
|
||||
// (or std::string, but then we'd be changing the way translated text is stored)
|
||||
typedef std::map<std::string, const char*> token_map;
|
||||
static token_map s_token_map;
|
||||
//
|
||||
// declaring value type as const char* so that we can give out a const reference to the real
|
||||
// token map without allowing external code to modify token text
|
||||
// unfortunately, this means we don't have write access internally either,
|
||||
// so we have to const_cast<> to initialise the token values.
|
||||
// this could be avoided by using a custom class for the value type
|
||||
// (or std::string, but then we'd be changing the way translated text is stored)
|
||||
typedef std::map<std::string, const char *> token_map;
|
||||
static token_map s_token_map;
|
||||
|
||||
static struct init_string_helper_class {
|
||||
init_string_helper_class() {
|
||||
#define DECLARE_STRING(x) s_token_map.insert(std::make_pair(#x, Lang::x)); Lang::x[0] = '\0';
|
||||
static struct init_string_helper_class {
|
||||
init_string_helper_class()
|
||||
{
|
||||
#define DECLARE_STRING(x) \
|
||||
s_token_map.insert(std::make_pair(#x, Lang::x)); \
|
||||
Lang::x[0] = '\0';
|
||||
#include "LangStrings.inc.h"
|
||||
#undef DECLARE_STRING
|
||||
}
|
||||
} init_string_helper;
|
||||
|
||||
|
||||
static void copy_string(char *buf, const char *str, size_t strsize, size_t bufsize)
|
||||
{
|
||||
size_t sz = std::min(strsize, bufsize-1);
|
||||
memcpy(buf, str, sz);
|
||||
buf[sz] = '\0';
|
||||
}
|
||||
|
||||
static Resource s_coreResource("core", "<unknown>");
|
||||
|
||||
void MakeCore(Resource &res)
|
||||
{
|
||||
assert(res.GetName() == "core");
|
||||
|
||||
res.Load();
|
||||
|
||||
for (token_map::iterator i = s_token_map.begin(); i != s_token_map.end(); ++i) {
|
||||
const std::string &token = i->first;
|
||||
std::string text = res.Get(token);
|
||||
|
||||
if (text.empty()) {
|
||||
Output("%s/%s: token '%s' not found\n", res.GetName().c_str(), res.GetLangCode().c_str(), token.c_str());
|
||||
text = token;
|
||||
}
|
||||
} init_string_helper;
|
||||
|
||||
if (text.size() > size_t(STRING_RECORD_SIZE)) {
|
||||
Output("%s/%s: text for token '%s' is too long and will be truncated\n", res.GetName().c_str(), res.GetLangCode().c_str(), token.c_str());
|
||||
text.resize(STRING_RECORD_SIZE);
|
||||
}
|
||||
|
||||
// const_cast so we can set the string, see above
|
||||
char *record = const_cast<char*>(i->second);
|
||||
copy_string(record, text.c_str(), text.size(), STRING_RECORD_SIZE);
|
||||
static void copy_string(char *buf, const char *str, size_t strsize, size_t bufsize)
|
||||
{
|
||||
size_t sz = std::min(strsize, bufsize - 1);
|
||||
memcpy(buf, str, sz);
|
||||
buf[sz] = '\0';
|
||||
}
|
||||
|
||||
s_coreResource = res;
|
||||
}
|
||||
static Resource s_coreResource("core", "<unknown>");
|
||||
|
||||
const Resource &GetCore()
|
||||
{
|
||||
return s_coreResource;
|
||||
}
|
||||
void MakeCore(Resource &res)
|
||||
{
|
||||
assert(res.GetName() == "core");
|
||||
|
||||
static std::map<std::string,Resource> m_cachedResources;
|
||||
res.Load();
|
||||
|
||||
Resource GetResource(const std::string &name, const std::string &langCode)
|
||||
{
|
||||
auto key = name + ":" + langCode;
|
||||
for (token_map::iterator i = s_token_map.begin(); i != s_token_map.end(); ++i) {
|
||||
const std::string &token = i->first;
|
||||
std::string text = res.Get(token);
|
||||
|
||||
auto i = m_cachedResources.find(key);
|
||||
if (i != m_cachedResources.end())
|
||||
return i->second;
|
||||
if (text.empty()) {
|
||||
Output("%s/%s: token '%s' not found\n", res.GetName().c_str(), res.GetLangCode().c_str(), token.c_str());
|
||||
text = token;
|
||||
}
|
||||
|
||||
Lang::Resource res = Lang::Resource(name, langCode);
|
||||
bool loaded = res.Load();
|
||||
if (!loaded) {
|
||||
if (langCode != "en") {
|
||||
Output("couldn't load language resource %s/%s, trying %s/en\n", name.c_str(), langCode.c_str(), name.c_str());
|
||||
res = Lang::Resource(name, "en");
|
||||
loaded = res.Load();
|
||||
key = name + ":" + "en";
|
||||
if (text.size() > size_t(STRING_RECORD_SIZE)) {
|
||||
Output("%s/%s: text for token '%s' is too long and will be truncated\n", res.GetName().c_str(), res.GetLangCode().c_str(), token.c_str());
|
||||
text.resize(STRING_RECORD_SIZE);
|
||||
}
|
||||
|
||||
// const_cast so we can set the string, see above
|
||||
char *record = const_cast<char *>(i->second);
|
||||
copy_string(record, text.c_str(), text.size(), STRING_RECORD_SIZE);
|
||||
}
|
||||
if (!loaded)
|
||||
Output("couldn't load language resource %s/en\n", name.c_str());
|
||||
|
||||
s_coreResource = res;
|
||||
}
|
||||
|
||||
if (loaded)
|
||||
m_cachedResources.insert(std::make_pair(key, res));
|
||||
const Resource &GetCore()
|
||||
{
|
||||
return s_coreResource;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
static std::map<std::string, Resource> m_cachedResources;
|
||||
|
||||
Resource GetResource(const std::string &name, const std::string &langCode)
|
||||
{
|
||||
auto key = name + ":" + langCode;
|
||||
|
||||
auto i = m_cachedResources.find(key);
|
||||
if (i != m_cachedResources.end())
|
||||
return i->second;
|
||||
|
||||
Lang::Resource res = Lang::Resource(name, langCode);
|
||||
bool loaded = res.Load();
|
||||
if (!loaded) {
|
||||
if (langCode != "en") {
|
||||
Output("couldn't load language resource %s/%s, trying %s/en\n", name.c_str(), langCode.c_str(), name.c_str());
|
||||
res = Lang::Resource(name, "en");
|
||||
loaded = res.Load();
|
||||
key = name + ":" + "en";
|
||||
}
|
||||
if (!loaded)
|
||||
Output("couldn't load language resource %s/en\n", name.c_str());
|
||||
}
|
||||
|
||||
if (loaded)
|
||||
m_cachedResources.insert(std::make_pair(key, res));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace Lang
|
||||
|
|
54
src/Lang.h
54
src/Lang.h
|
@ -4,52 +4,54 @@
|
|||
#ifndef _LANG_H
|
||||
#define _LANG_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <SDL_stdinc.h>
|
||||
#include "IterationProxy.h"
|
||||
#include <SDL_stdinc.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Lang {
|
||||
|
||||
class Resource {
|
||||
public:
|
||||
Resource(const std::string &name, const std::string &langCode) :
|
||||
m_name(name), m_langCode(langCode), m_loaded(false) {}
|
||||
class Resource {
|
||||
public:
|
||||
Resource(const std::string &name, const std::string &langCode) :
|
||||
m_name(name),
|
||||
m_langCode(langCode),
|
||||
m_loaded(false) {}
|
||||
|
||||
const std::string &GetName() const { return m_name; }
|
||||
const std::string &GetLangCode() const { return m_langCode; }
|
||||
const std::string &GetName() const { return m_name; }
|
||||
const std::string &GetLangCode() const { return m_langCode; }
|
||||
|
||||
bool Load();
|
||||
bool Load();
|
||||
|
||||
Uint32 GetNumStrings() const { return static_cast<Uint32>(m_strings.size()); }
|
||||
Uint32 GetNumStrings() const { return static_cast<Uint32>(m_strings.size()); }
|
||||
|
||||
const std::string &Get(const std::string &token) const;
|
||||
const std::string &Get(const std::string &token) const;
|
||||
|
||||
static std::vector<std::string> GetAvailableLanguages(const std::string &resourceName);
|
||||
static std::vector<std::string> GetAvailableLanguages(const std::string &resourceName);
|
||||
|
||||
IterationProxy<std::map<std::string,std::string> > GetStrings() { return MakeIterationProxy(m_strings); }
|
||||
const IterationProxy<const std::map<std::string,std::string> > GetStrings() const { return MakeIterationProxy(m_strings); }
|
||||
IterationProxy<std::map<std::string, std::string>> GetStrings() { return MakeIterationProxy(m_strings); }
|
||||
const IterationProxy<const std::map<std::string, std::string>> GetStrings() const { return MakeIterationProxy(m_strings); }
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
std::string m_langCode;
|
||||
private:
|
||||
std::string m_name;
|
||||
std::string m_langCode;
|
||||
|
||||
bool m_loaded;
|
||||
bool m_loaded;
|
||||
|
||||
std::map<std::string,std::string> m_strings;
|
||||
};
|
||||
std::map<std::string, std::string> m_strings;
|
||||
};
|
||||
|
||||
// declare all strings
|
||||
#define DECLARE_STRING(x) extern char x[];
|
||||
#include "LangStrings.inc.h"
|
||||
#undef DECLARE_STRING
|
||||
|
||||
void MakeCore(Resource &res);
|
||||
const Resource &GetCore();
|
||||
void MakeCore(Resource &res);
|
||||
const Resource &GetCore();
|
||||
|
||||
Resource GetResource(const std::string &name, const std::string &langCode);
|
||||
Resource GetResource(const std::string &name, const std::string &langCode);
|
||||
|
||||
}
|
||||
} // namespace Lang
|
||||
|
||||
#endif
|
||||
|
|
22
src/Lua.cpp
22
src/Lua.cpp
|
@ -5,17 +5,17 @@
|
|||
|
||||
namespace Lua {
|
||||
|
||||
LuaManager *manager = 0;
|
||||
LuaManager *manager = 0;
|
||||
|
||||
void Init()
|
||||
{
|
||||
manager = new LuaManager();
|
||||
}
|
||||
void Init()
|
||||
{
|
||||
manager = new LuaManager();
|
||||
}
|
||||
|
||||
void Uninit()
|
||||
{
|
||||
delete manager;
|
||||
manager = 0;
|
||||
}
|
||||
void Uninit()
|
||||
{
|
||||
delete manager;
|
||||
manager = 0;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Lua
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
// modelviewer. probably sucks in the long term
|
||||
namespace Lua {
|
||||
|
||||
extern LuaManager *manager;
|
||||
extern LuaManager *manager;
|
||||
|
||||
void Init();
|
||||
void Uninit();
|
||||
void Init();
|
||||
void Uninit();
|
||||
|
||||
}
|
||||
} // namespace Lua
|
||||
|
||||
#endif
|
||||
|
|
305
src/LuaBody.cpp
305
src/LuaBody.cpp
|
@ -1,26 +1,26 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "LuaObject.h"
|
||||
#include "LuaUtils.h"
|
||||
#include "LuaConstants.h"
|
||||
#include "EnumStrings.h"
|
||||
#include "Body.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
#include "EnumStrings.h"
|
||||
#include "Frame.h"
|
||||
#include "TerrainBody.h"
|
||||
#include "Pi.h"
|
||||
#include "Game.h"
|
||||
#include "LuaConstants.h"
|
||||
#include "LuaObject.h"
|
||||
#include "LuaPiGui.h"
|
||||
#include "LuaUtils.h"
|
||||
#include "Pi.h"
|
||||
#include "TerrainBody.h"
|
||||
#include "galaxy/StarSystem.h"
|
||||
|
||||
#include "ModelBody.h"
|
||||
#include "Ship.h"
|
||||
#include "Player.h"
|
||||
#include "SpaceStation.h"
|
||||
#include "Planet.h"
|
||||
#include "Star.h"
|
||||
#include "CargoBody.h"
|
||||
#include "Missile.h"
|
||||
#include "ModelBody.h"
|
||||
#include "Planet.h"
|
||||
#include "Player.h"
|
||||
#include "Ship.h"
|
||||
#include "SpaceStation.h"
|
||||
#include "Star.h"
|
||||
|
||||
/*
|
||||
* Class: Body
|
||||
|
@ -139,89 +139,89 @@ static int l_body_get_velocity_rel_to(lua_State *l)
|
|||
|
||||
static int l_body_is_moon(lua_State *l)
|
||||
{
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
const SystemBody *sb = body->GetSystemBody();
|
||||
if(!sb) {
|
||||
LuaPush<bool>(l, false);
|
||||
} else {
|
||||
LuaPush<bool>(l, sb->IsMoon());
|
||||
}
|
||||
return 1;
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
const SystemBody *sb = body->GetSystemBody();
|
||||
if (!sb) {
|
||||
LuaPush<bool>(l, false);
|
||||
} else {
|
||||
LuaPush<bool>(l, sb->IsMoon());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_body_is_missile(lua_State *l)
|
||||
{
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
LuaPush<bool>(l, body->GetType() == Object::Type::MISSILE);
|
||||
return 1;
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
LuaPush<bool>(l, body->GetType() == Object::Type::MISSILE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_body_is_station(lua_State *l)
|
||||
{
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
LuaPush<bool>(l, body->GetType() == Object::Type::SPACESTATION);
|
||||
return 1;
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
LuaPush<bool>(l, body->GetType() == Object::Type::SPACESTATION);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_body_is_space_station(lua_State *l)
|
||||
{
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
const SystemBody *sb = body->GetSystemBody();
|
||||
LuaPush<bool>(l, sb ? sb->GetType() == SystemBody::BodyType::TYPE_STARPORT_ORBITAL : false);
|
||||
return 1;
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
const SystemBody *sb = body->GetSystemBody();
|
||||
LuaPush<bool>(l, sb ? sb->GetType() == SystemBody::BodyType::TYPE_STARPORT_ORBITAL : false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_body_is_ground_station(lua_State *l)
|
||||
{
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
const SystemBody *sb = body->GetSystemBody();
|
||||
LuaPush<bool>(l, sb ? sb->GetType() == SystemBody::BodyType::TYPE_STARPORT_SURFACE : false);
|
||||
return 1;
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
const SystemBody *sb = body->GetSystemBody();
|
||||
LuaPush<bool>(l, sb ? sb->GetType() == SystemBody::BodyType::TYPE_STARPORT_SURFACE : false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_body_is_cargo_container(lua_State *l)
|
||||
{
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
LuaPush<bool>(l, body->GetType() == Object::Type::CARGOBODY);
|
||||
return 1;
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
LuaPush<bool>(l, body->GetType() == Object::Type::CARGOBODY);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_body_is_ship(lua_State *l)
|
||||
{
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
LuaPush<bool>(l, body->GetType() == Object::Type::SHIP);
|
||||
return 1;
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
LuaPush<bool>(l, body->GetType() == Object::Type::SHIP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_body_is_hyperspace_cloud(lua_State *l)
|
||||
{
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
LuaPush<bool>(l, body->GetType() == Object::Type::HYPERSPACECLOUD);
|
||||
return 1;
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
LuaPush<bool>(l, body->GetType() == Object::Type::HYPERSPACECLOUD);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_body_is_planet(lua_State *l)
|
||||
{
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
const SystemBody *sb = body->GetSystemBody();
|
||||
if(!sb) {
|
||||
LuaPush<bool>(l, false);
|
||||
} else {
|
||||
LuaPush<bool>(l, sb->IsPlanet());
|
||||
}
|
||||
return 1;
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
const SystemBody *sb = body->GetSystemBody();
|
||||
if (!sb) {
|
||||
LuaPush<bool>(l, false);
|
||||
} else {
|
||||
LuaPush<bool>(l, sb->IsPlanet());
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_body_get_system_body(lua_State *l)
|
||||
{
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
SystemBody *sb = const_cast<SystemBody*>(body->GetSystemBody()); // TODO: ugly, change this...
|
||||
if(!sb) {
|
||||
lua_pushnil(l);
|
||||
} else {
|
||||
LuaObject<SystemBody>::PushToLua(sb);
|
||||
}
|
||||
return 1;
|
||||
Body *body = LuaObject<Body>::CheckFromLua(1);
|
||||
SystemBody *sb = const_cast<SystemBody *>(body->GetSystemBody()); // TODO: ugly, change this...
|
||||
if (!sb) {
|
||||
lua_pushnil(l);
|
||||
} else {
|
||||
LuaObject<SystemBody>::PushToLua(sb);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_body_is_more_important_than(lua_State *l)
|
||||
|
@ -234,8 +234,7 @@ static int l_body_is_more_important_than(lua_State *l)
|
|||
// the most important body is shown on the hud and
|
||||
// bodies are sorted by importance in menus
|
||||
|
||||
if(body == other)
|
||||
{
|
||||
if (body == other) {
|
||||
LuaPush<bool>(l, false);
|
||||
return 1;
|
||||
}
|
||||
|
@ -257,44 +256,69 @@ static int l_body_is_more_important_than(lua_State *l)
|
|||
// if type is the same, just sort alphabetically
|
||||
// planets are different, because moons are
|
||||
// less important (but don't have their own type)
|
||||
if(a == b && a != Object::Type::PLANET) result = body->GetLabel() < other->GetLabel();
|
||||
if (a == b && a != Object::Type::PLANET) result = body->GetLabel() < other->GetLabel();
|
||||
// a star is larger than any other object
|
||||
else if(a == Object::Type::STAR) result = true;
|
||||
else if (a == Object::Type::STAR)
|
||||
result = true;
|
||||
// any (non-star) object is smaller than a star
|
||||
else if(b == Object::Type::STAR) result = false;
|
||||
else if (b == Object::Type::STAR)
|
||||
result = false;
|
||||
// a gas giant is larger than anything but a star,
|
||||
// but remember to keep total order in mind: if both are
|
||||
// gas giants, order alphabetically
|
||||
else if(a_gas_giant) result = !b_gas_giant || body->GetLabel() < other->GetLabel();
|
||||
else if (a_gas_giant)
|
||||
result = !b_gas_giant || body->GetLabel() < other->GetLabel();
|
||||
// any (non-star, non-gas giant) object is smaller than a gas giant
|
||||
else if(b_gas_giant) result = false;
|
||||
else if (b_gas_giant)
|
||||
result = false;
|
||||
// between two planets or moons, alphabetic
|
||||
else if(a_planet && b_planet) result = body->GetLabel() < other->GetLabel();
|
||||
else if(a_moon && b_moon) result = body->GetLabel() < other->GetLabel();
|
||||
else if (a_planet && b_planet)
|
||||
result = body->GetLabel() < other->GetLabel();
|
||||
else if (a_moon && b_moon)
|
||||
result = body->GetLabel() < other->GetLabel();
|
||||
// a planet is larger than any non-planet
|
||||
else if(a_planet) result = true;
|
||||
else if (a_planet)
|
||||
result = true;
|
||||
// a non-planet is smaller than any planet
|
||||
else if(b_planet) result = false;
|
||||
else if (b_planet)
|
||||
result = false;
|
||||
// a moon is larger than any non-moon
|
||||
else if(a_moon) result = true;
|
||||
else if (a_moon)
|
||||
result = true;
|
||||
// a non-moon is smaller than any moon
|
||||
else if(b_moon) result = false;
|
||||
else if (b_moon)
|
||||
result = false;
|
||||
// spacestation > city > ship > hyperspace cloud > cargo body > missile > projectile
|
||||
else if(a == Object::Type::SPACESTATION) result = true;
|
||||
else if(b == Object::Type::SPACESTATION) result = false;
|
||||
else if(a == Object::Type::CITYONPLANET) result = true;
|
||||
else if(b == Object::Type::CITYONPLANET) result = false;
|
||||
else if(a == Object::Type::SHIP) result = true;
|
||||
else if(b == Object::Type::SHIP) result = false;
|
||||
else if(a == Object::Type::HYPERSPACECLOUD) result = true;
|
||||
else if(b == Object::Type::HYPERSPACECLOUD) result = false;
|
||||
else if(a == Object::Type::CARGOBODY) result = true;
|
||||
else if(b == Object::Type::CARGOBODY) result = false;
|
||||
else if(a == Object::Type::MISSILE) result = true;
|
||||
else if(b == Object::Type::MISSILE) result = false;
|
||||
else if(a == Object::Type::PROJECTILE) result = true;
|
||||
else if(b == Object::Type::PROJECTILE) result = false;
|
||||
else Error("don't know how to compare %i and %i\n", a, b);
|
||||
else if (a == Object::Type::SPACESTATION)
|
||||
result = true;
|
||||
else if (b == Object::Type::SPACESTATION)
|
||||
result = false;
|
||||
else if (a == Object::Type::CITYONPLANET)
|
||||
result = true;
|
||||
else if (b == Object::Type::CITYONPLANET)
|
||||
result = false;
|
||||
else if (a == Object::Type::SHIP)
|
||||
result = true;
|
||||
else if (b == Object::Type::SHIP)
|
||||
result = false;
|
||||
else if (a == Object::Type::HYPERSPACECLOUD)
|
||||
result = true;
|
||||
else if (b == Object::Type::HYPERSPACECLOUD)
|
||||
result = false;
|
||||
else if (a == Object::Type::CARGOBODY)
|
||||
result = true;
|
||||
else if (b == Object::Type::CARGOBODY)
|
||||
result = false;
|
||||
else if (a == Object::Type::MISSILE)
|
||||
result = true;
|
||||
else if (b == Object::Type::MISSILE)
|
||||
result = false;
|
||||
else if (a == Object::Type::PROJECTILE)
|
||||
result = true;
|
||||
else if (b == Object::Type::PROJECTILE)
|
||||
result = false;
|
||||
else
|
||||
Error("don't know how to compare %i and %i\n", a, b);
|
||||
|
||||
LuaPush<bool>(l, result);
|
||||
return 1;
|
||||
|
@ -353,8 +377,8 @@ static int l_body_get_altitude_rel_to(lua_State *l)
|
|||
const Body *other = LuaObject<Body>::CheckFromLua(2);
|
||||
vector3d pos = Pi::player->GetPositionRelTo(other);
|
||||
double center_dist = pos.Length();
|
||||
if(other && other->IsType(Object::TERRAINBODY)) {
|
||||
const TerrainBody* terrain = static_cast<const TerrainBody*>(other);
|
||||
if (other && other->IsType(Object::TERRAINBODY)) {
|
||||
const TerrainBody *terrain = static_cast<const TerrainBody *>(other);
|
||||
vector3d surface_pos = pos.Normalized();
|
||||
double radius = 0.0;
|
||||
if (center_dist <= 3.0 * terrain->GetMaxFeatureRadius()) {
|
||||
|
@ -369,7 +393,6 @@ static int l_body_get_altitude_rel_to(lua_State *l)
|
|||
LuaPush(l, center_dist);
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -604,13 +627,13 @@ static int l_body_get_ground_position(lua_State *l)
|
|||
return 0;
|
||||
|
||||
vector3d pos = b->GetPosition();
|
||||
double latitude = atan2(pos.y, sqrt(pos.x*pos.x + pos.z * pos.z));
|
||||
double latitude = atan2(pos.y, sqrt(pos.x * pos.x + pos.z * pos.z));
|
||||
double longitude = atan2(pos.x, pos.z);
|
||||
lua_pushnumber(l, latitude);
|
||||
lua_pushnumber(l, longitude);
|
||||
Body *astro = f->GetBody();
|
||||
if (astro->IsType(Object::TERRAINBODY)) {
|
||||
double radius = static_cast<TerrainBody*>(astro)->GetTerrainHeight(pos.Normalized());
|
||||
double radius = static_cast<TerrainBody *>(astro)->GetTerrainHeight(pos.Normalized());
|
||||
double altitude = pos.Length() - radius;
|
||||
lua_pushnumber(l, altitude);
|
||||
} else {
|
||||
|
@ -707,14 +730,15 @@ static int l_body_get_projected_screen_position(lua_State *l)
|
|||
return pushOnScreenPositionDirection(l, p);
|
||||
}
|
||||
|
||||
static int l_body_get_atmospheric_state(lua_State *l) {
|
||||
static int l_body_get_atmospheric_state(lua_State *l)
|
||||
{
|
||||
Body *b = LuaObject<Body>::CheckFromLua(1);
|
||||
// const SystemBody *sb = b->GetSystemBody();
|
||||
vector3d pos = Pi::player->GetPosition();
|
||||
double center_dist = pos.Length();
|
||||
if (b->IsType(Object::PLANET)) {
|
||||
double pressure, density;
|
||||
static_cast<Planet*>(b)->GetAtmosphericState(center_dist, &pressure, &density);
|
||||
static_cast<Planet *>(b)->GetAtmosphericState(center_dist, &pressure, &density);
|
||||
lua_pushnumber(l, pressure);
|
||||
lua_pushnumber(l, density);
|
||||
return 2;
|
||||
|
@ -738,38 +762,39 @@ static int l_body_get_target_indicator_screen_position(lua_State *l)
|
|||
return pushOnScreenPositionDirection(l, p);
|
||||
}
|
||||
|
||||
static bool push_body_to_lua(Body *body) {
|
||||
static bool push_body_to_lua(Body *body)
|
||||
{
|
||||
assert(body);
|
||||
switch (body->GetType()) {
|
||||
case Object::BODY:
|
||||
LuaObject<Body>::PushToLua(body);
|
||||
break;
|
||||
case Object::MODELBODY:
|
||||
LuaObject<Body>::PushToLua(dynamic_cast<ModelBody*>(body));
|
||||
LuaObject<Body>::PushToLua(dynamic_cast<ModelBody *>(body));
|
||||
break;
|
||||
case Object::SHIP:
|
||||
LuaObject<Ship>::PushToLua(dynamic_cast<Ship*>(body));
|
||||
LuaObject<Ship>::PushToLua(dynamic_cast<Ship *>(body));
|
||||
break;
|
||||
case Object::PLAYER:
|
||||
LuaObject<Player>::PushToLua(dynamic_cast<Player*>(body));
|
||||
LuaObject<Player>::PushToLua(dynamic_cast<Player *>(body));
|
||||
break;
|
||||
case Object::SPACESTATION:
|
||||
LuaObject<SpaceStation>::PushToLua(dynamic_cast<SpaceStation*>(body));
|
||||
LuaObject<SpaceStation>::PushToLua(dynamic_cast<SpaceStation *>(body));
|
||||
break;
|
||||
case Object::PLANET:
|
||||
LuaObject<Planet>::PushToLua(dynamic_cast<Planet*>(body));
|
||||
LuaObject<Planet>::PushToLua(dynamic_cast<Planet *>(body));
|
||||
break;
|
||||
case Object::STAR:
|
||||
LuaObject<Star>::PushToLua(dynamic_cast<Star*>(body));
|
||||
LuaObject<Star>::PushToLua(dynamic_cast<Star *>(body));
|
||||
break;
|
||||
case Object::CARGOBODY:
|
||||
LuaObject<Star>::PushToLua(dynamic_cast<CargoBody*>(body));
|
||||
LuaObject<Star>::PushToLua(dynamic_cast<CargoBody *>(body));
|
||||
break;
|
||||
case Object::MISSILE:
|
||||
LuaObject<Missile>::PushToLua(dynamic_cast<Missile*>(body));
|
||||
LuaObject<Missile>::PushToLua(dynamic_cast<Missile *>(body));
|
||||
break;
|
||||
case Object::HYPERSPACECLOUD:
|
||||
LuaObject<HyperspaceCloud>::PushToLua(dynamic_cast<HyperspaceCloud*>(body));
|
||||
LuaObject<HyperspaceCloud>::PushToLua(dynamic_cast<HyperspaceCloud *>(body));
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
@ -780,14 +805,14 @@ static bool push_body_to_lua(Body *body) {
|
|||
static std::string _body_serializer(LuaWrappable *o)
|
||||
{
|
||||
static char buf[256];
|
||||
Body *b = static_cast<Body*>(o);
|
||||
Body *b = static_cast<Body *>(o);
|
||||
snprintf(buf, sizeof(buf), "%u\n", Pi::game->GetSpace()->GetIndexForBody(b));
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
static bool _body_deserializer(const char *pos, const char **next)
|
||||
{
|
||||
Uint32 n = strtoul(pos, const_cast<char**>(next), 0);
|
||||
Uint32 n = strtoul(pos, const_cast<char **>(next), 0);
|
||||
if (pos == *next) return false;
|
||||
(*next)++; // skip newline
|
||||
|
||||
|
@ -797,7 +822,7 @@ static bool _body_deserializer(const char *pos, const char **next)
|
|||
|
||||
static void _body_to_json(Json &out, LuaWrappable *o)
|
||||
{
|
||||
Body *b = static_cast<Body*>(o);
|
||||
Body *b = static_cast<Body *>(o);
|
||||
out = Json(Pi::game->GetSpace()->GetIndexForBody(b));
|
||||
}
|
||||
|
||||
|
@ -808,45 +833,47 @@ static bool _body_from_json(const Json &obj)
|
|||
return push_body_to_lua(body);
|
||||
}
|
||||
|
||||
template <> const char *LuaObject<Body>::s_type = "Body";
|
||||
template <>
|
||||
const char *LuaObject<Body>::s_type = "Body";
|
||||
|
||||
template <> void LuaObject<Body>::RegisterClass()
|
||||
template <>
|
||||
void LuaObject<Body>::RegisterClass()
|
||||
{
|
||||
const char *l_parent = "PropertiedObject";
|
||||
|
||||
static luaL_Reg l_methods[] = {
|
||||
{ "IsDynamic", l_body_is_dynamic },
|
||||
{ "IsDynamic", l_body_is_dynamic },
|
||||
{ "DistanceTo", l_body_distance_to },
|
||||
{ "GetGroundPosition", l_body_get_ground_position },
|
||||
{ "FindNearestTo", l_body_find_nearest_to },
|
||||
{ "GetVelocityRelTo", l_body_get_velocity_rel_to },
|
||||
{ "GetPositionRelTo", l_body_get_position_rel_to },
|
||||
{ "GetAltitudeRelTo", l_body_get_altitude_rel_to },
|
||||
{ "GetVelocityRelTo", l_body_get_velocity_rel_to },
|
||||
{ "GetPositionRelTo", l_body_get_position_rel_to },
|
||||
{ "GetAltitudeRelTo", l_body_get_altitude_rel_to },
|
||||
{ "GetProjectedScreenPosition", l_body_get_projected_screen_position },
|
||||
{ "GetTargetIndicatorScreenPosition", l_body_get_target_indicator_screen_position },
|
||||
{ "GetPhysicalRadius", l_body_get_phys_radius },
|
||||
{ "GetPhysicalRadius", l_body_get_phys_radius },
|
||||
{ "GetAtmosphericState", l_body_get_atmospheric_state },
|
||||
{ "GetLabel", l_body_get_label },
|
||||
{ "GetLabel", l_body_get_label },
|
||||
{ "IsMoreImportantThan", l_body_is_more_important_than },
|
||||
{ "IsMoon", l_body_is_moon },
|
||||
{ "IsPlanet", l_body_is_planet },
|
||||
{ "IsShip", l_body_is_ship },
|
||||
{ "IsHyperspaceCloud", l_body_is_hyperspace_cloud },
|
||||
{ "IsMissile", l_body_is_missile },
|
||||
{ "IsStation", l_body_is_station },
|
||||
{ "IsSpaceStation", l_body_is_space_station },
|
||||
{ "IsGroundStation", l_body_is_ground_station },
|
||||
{ "IsCargoContainer", l_body_is_cargo_container },
|
||||
{ "GetSystemBody", l_body_get_system_body },
|
||||
{ "IsMoon", l_body_is_moon },
|
||||
{ "IsPlanet", l_body_is_planet },
|
||||
{ "IsShip", l_body_is_ship },
|
||||
{ "IsHyperspaceCloud", l_body_is_hyperspace_cloud },
|
||||
{ "IsMissile", l_body_is_missile },
|
||||
{ "IsStation", l_body_is_station },
|
||||
{ "IsSpaceStation", l_body_is_space_station },
|
||||
{ "IsGroundStation", l_body_is_ground_station },
|
||||
{ "IsCargoContainer", l_body_is_cargo_container },
|
||||
{ "GetSystemBody", l_body_get_system_body },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static luaL_Reg l_attrs[] = {
|
||||
{ "seed", l_body_attr_seed },
|
||||
{ "path", l_body_attr_path },
|
||||
{ "type", l_body_attr_type },
|
||||
{ "superType", l_body_attr_super_type },
|
||||
{ "frameBody", l_body_attr_frame_body },
|
||||
{ "seed", l_body_attr_seed },
|
||||
{ "path", l_body_attr_path },
|
||||
{ "type", l_body_attr_type },
|
||||
{ "superType", l_body_attr_super_type },
|
||||
{ "frameBody", l_body_attr_frame_body },
|
||||
{ "frameRotating", l_body_attr_frame_rotating },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
@ -858,13 +885,13 @@ template <> void LuaObject<Body>::RegisterClass()
|
|||
LuaObjectBase::RegisterSerializer(s_type, body_serializers);
|
||||
|
||||
// we're also the serializer for our subclasses
|
||||
LuaObjectBase::RegisterSerializer("ModelBody", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("Ship", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("Player", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("SpaceStation", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("Planet", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("Star", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("CargoBody", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("Missile", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("ModelBody", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("Ship", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("Player", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("SpaceStation", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("Planet", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("Star", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("CargoBody", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("Missile", body_serializers);
|
||||
LuaObjectBase::RegisterSerializer("HyperspaceCloud", body_serializers);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright © 2008-2019 Pioneer Developers. See AUTHORS.txt for details
|
||||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "CargoBody.h"
|
||||
#include "LuaObject.h"
|
||||
#include "LuaUtils.h"
|
||||
#include "CargoBody.h"
|
||||
|
||||
/*
|
||||
* Class: CargoBody
|
||||
|
@ -27,9 +27,11 @@
|
|||
* experimental
|
||||
*/
|
||||
|
||||
template <> const char *LuaObject<CargoBody>::s_type = "CargoBody";
|
||||
template <>
|
||||
const char *LuaObject<CargoBody>::s_type = "CargoBody";
|
||||
|
||||
template <> void LuaObject<CargoBody>::RegisterClass()
|
||||
template <>
|
||||
void LuaObject<CargoBody>::RegisterClass()
|
||||
{
|
||||
const char *l_parent = "ModelBody";
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "LuaComms.h"
|
||||
#include "GameLog.h"
|
||||
#include "LuaObject.h"
|
||||
#include "LuaUtils.h"
|
||||
#include "Pi.h"
|
||||
#include "ShipCpanel.h"
|
||||
#include "GameLog.h"
|
||||
|
||||
/*
|
||||
* Interface: Comms
|
||||
|
@ -104,7 +104,7 @@ void LuaComms::Register()
|
|||
LUA_DEBUG_START(l);
|
||||
|
||||
static const luaL_Reg l_methods[] = {
|
||||
{ "Message", l_comms_message },
|
||||
{ "Message", l_comms_message },
|
||||
{ "ImportantMessage", l_comms_important_message },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
|
|
@ -2,30 +2,30 @@
|
|||
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
||||
|
||||
#include "LuaConsole.h"
|
||||
#include "FileSystem.h"
|
||||
#include "KeyBindings.h"
|
||||
#include "LuaManager.h"
|
||||
#include "LuaUtils.h"
|
||||
#include "Pi.h"
|
||||
#include "text/TextSupport.h"
|
||||
#include "text/TextureFont.h"
|
||||
#include "ui/Context.h"
|
||||
#include "ui/Margin.h"
|
||||
#include "text/TextureFont.h"
|
||||
#include "text/TextSupport.h"
|
||||
#include "KeyBindings.h"
|
||||
#include "FileSystem.h"
|
||||
#include "LuaUtils.h"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef REMOTE_LUA_REPL
|
||||
// for networking
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
// end networking
|
||||
#endif
|
||||
|
||||
|
@ -37,12 +37,13 @@ static const char CONSOLE_CHUNK_NAME[] = "[T] console";
|
|||
static const char CONSOLE_CHUNK_NAME[] = "console";
|
||||
#endif
|
||||
|
||||
LuaConsole::LuaConsole():
|
||||
LuaConsole::LuaConsole() :
|
||||
m_active(false),
|
||||
m_precompletionStatement(),
|
||||
m_completionList()
|
||||
#ifdef REMOTE_LUA_REPL
|
||||
, m_debugSocket(0)
|
||||
,
|
||||
m_debugSocket(0)
|
||||
#endif
|
||||
{
|
||||
|
||||
|
@ -52,17 +53,7 @@ LuaConsole::LuaConsole():
|
|||
m_scroller = Pi::ui->Scroller()->SetInnerWidget(m_output);
|
||||
|
||||
// temporary until LuaConsole is moved to lua: move up to clear imgui time window
|
||||
m_container.Reset(Pi::ui->Margin(80, UI::Margin::Direction::BOTTOM)->SetInnerWidget(
|
||||
Pi::ui->Margin(10)->SetInnerWidget(
|
||||
Pi::ui->ColorBackground(Color(0,0,0,0xc0))->SetInnerWidget(
|
||||
Pi::ui->VBox()->PackEnd(UI::WidgetSet(
|
||||
Pi::ui->Expand()->SetInnerWidget(
|
||||
m_scroller
|
||||
),
|
||||
m_entry
|
||||
))
|
||||
)
|
||||
)));
|
||||
m_container.Reset(Pi::ui->Margin(80, UI::Margin::Direction::BOTTOM)->SetInnerWidget(Pi::ui->Margin(10)->SetInnerWidget(Pi::ui->ColorBackground(Color(0, 0, 0, 0xc0))->SetInnerWidget(Pi::ui->VBox()->PackEnd(UI::WidgetSet(Pi::ui->Expand()->SetInnerWidget(m_scroller), m_entry))))));
|
||||
|
||||
m_container->SetFont(UI::Widget::FONT_MONO_NORMAL);
|
||||
|
||||
|
@ -86,7 +77,8 @@ void LuaConsole::Toggle()
|
|||
m_active = !m_active;
|
||||
}
|
||||
|
||||
static int capture_traceback(lua_State *L) {
|
||||
static int capture_traceback(lua_State *L)
|
||||
{
|
||||
lua_pushstring(L, "\n");
|
||||
luaL_traceback(L, L, nullptr, 0);
|
||||
lua_concat(L, 3);
|
||||
|
@ -94,7 +86,8 @@ static int capture_traceback(lua_State *L) {
|
|||
}
|
||||
|
||||
// Create the table and leave a copy on the stack for further use
|
||||
static void init_global_table(lua_State *l) {
|
||||
static void init_global_table(lua_State *l)
|
||||
{
|
||||
LUA_DEBUG_START(l);
|
||||
|
||||
lua_newtable(l);
|
||||
|
@ -109,7 +102,8 @@ static void init_global_table(lua_State *l) {
|
|||
LUA_DEBUG_END(l, 1);
|
||||
}
|
||||
|
||||
static int console_autoexec(lua_State* l) {
|
||||
static int console_autoexec(lua_State *l)
|
||||
{
|
||||
LUA_DEBUG_START(l);
|
||||
|
||||
init_global_table(l); // _ENV
|
||||
|
@ -155,10 +149,10 @@ static int console_autoexec(lua_State* l) {
|
|||
LUA_DEBUG_END(l, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void LuaConsole::RegisterAutoexec() {
|
||||
void LuaConsole::RegisterAutoexec()
|
||||
{
|
||||
lua_State *L = Lua::manager->GetLuaState();
|
||||
LUA_DEBUG_START(L);
|
||||
if (!pi_lua_import(L, "Event")) {
|
||||
|
@ -177,89 +171,92 @@ void LuaConsole::RegisterAutoexec() {
|
|||
|
||||
LuaConsole::~LuaConsole() {}
|
||||
|
||||
bool LuaConsole::OnKeyDown(const UI::KeyboardEvent &event) {
|
||||
bool LuaConsole::OnKeyDown(const UI::KeyboardEvent &event)
|
||||
{
|
||||
|
||||
switch (event.keysym.sym) {
|
||||
case SDLK_ESCAPE: {
|
||||
// pressing the ESC key will drop our layer, but we still have to make sure we are marked as not active anymore
|
||||
m_active = false;
|
||||
break;
|
||||
}
|
||||
case SDLK_UP:
|
||||
case SDLK_DOWN: {
|
||||
if (m_historyPosition == -1) {
|
||||
if (event.keysym.sym == SDLK_UP) {
|
||||
m_historyPosition = (m_statementHistory.size() - 1);
|
||||
if (m_historyPosition != -1) {
|
||||
m_stashedStatement = m_entry->GetText();
|
||||
m_entry->SetText(m_statementHistory[m_historyPosition]);
|
||||
}
|
||||
case SDLK_ESCAPE: {
|
||||
// pressing the ESC key will drop our layer, but we still have to make sure we are marked as not active anymore
|
||||
m_active = false;
|
||||
break;
|
||||
}
|
||||
case SDLK_UP:
|
||||
case SDLK_DOWN: {
|
||||
if (m_historyPosition == -1) {
|
||||
if (event.keysym.sym == SDLK_UP) {
|
||||
m_historyPosition = (m_statementHistory.size() - 1);
|
||||
if (m_historyPosition != -1) {
|
||||
m_stashedStatement = m_entry->GetText();
|
||||
m_entry->SetText(m_statementHistory[m_historyPosition]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (event.keysym.sym == SDLK_DOWN) {
|
||||
++m_historyPosition;
|
||||
if (m_historyPosition >= int(m_statementHistory.size())) {
|
||||
m_historyPosition = -1;
|
||||
m_entry->SetText(m_stashedStatement);
|
||||
m_stashedStatement.clear();
|
||||
} else {
|
||||
m_entry->SetText(m_statementHistory[m_historyPosition]);
|
||||
}
|
||||
} else {
|
||||
if (event.keysym.sym == SDLK_DOWN) {
|
||||
++m_historyPosition;
|
||||
if (m_historyPosition >= int(m_statementHistory.size())) {
|
||||
m_historyPosition = -1;
|
||||
m_entry->SetText(m_stashedStatement);
|
||||
m_stashedStatement.clear();
|
||||
} else {
|
||||
m_entry->SetText(m_statementHistory[m_historyPosition]);
|
||||
}
|
||||
} else {
|
||||
if (m_historyPosition > 0) {
|
||||
--m_historyPosition;
|
||||
m_entry->SetText(m_statementHistory[m_historyPosition]);
|
||||
}
|
||||
if (m_historyPosition > 0) {
|
||||
--m_historyPosition;
|
||||
m_entry->SetText(m_statementHistory[m_historyPosition]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case SDLK_u:
|
||||
case SDLK_w:
|
||||
if (event.keysym.mod & KMOD_CTRL) {
|
||||
// TextEntry already cleared the input, we must cleanup the history
|
||||
m_stashedStatement.clear();
|
||||
m_historyPosition = -1;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
|
||||
case SDLK_l:
|
||||
if (event.keysym.mod & KMOD_CTRL) {
|
||||
m_output->SetText("");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_TAB:
|
||||
if (m_completionList.empty()) {
|
||||
UpdateCompletion(m_entry->GetText());
|
||||
}
|
||||
if (!m_completionList.empty()) { // We still need to test whether it failed or not.
|
||||
if (event.keysym.mod & KMOD_SHIFT) {
|
||||
if (m_currentCompletion == 0)
|
||||
m_currentCompletion = m_completionList.size();
|
||||
m_currentCompletion--;
|
||||
} else {
|
||||
m_currentCompletion++;
|
||||
if (m_currentCompletion == m_completionList.size())
|
||||
m_currentCompletion = 0;
|
||||
}
|
||||
m_entry->SetText(m_precompletionStatement + m_completionList[m_currentCompletion]);
|
||||
}
|
||||
case SDLK_u:
|
||||
case SDLK_w:
|
||||
if (event.keysym.mod & KMOD_CTRL) {
|
||||
// TextEntry already cleared the input, we must cleanup the history
|
||||
m_stashedStatement.clear();
|
||||
m_historyPosition = -1;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_l:
|
||||
if (event.keysym.mod & KMOD_CTRL) {
|
||||
m_output->SetText("");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_TAB:
|
||||
if (m_completionList.empty()) {
|
||||
UpdateCompletion(m_entry->GetText());
|
||||
}
|
||||
if (!m_completionList.empty()) { // We still need to test whether it failed or not.
|
||||
if (event.keysym.mod & KMOD_SHIFT) {
|
||||
if (m_currentCompletion == 0)
|
||||
m_currentCompletion = m_completionList.size();
|
||||
m_currentCompletion--;
|
||||
} else {
|
||||
m_currentCompletion++;
|
||||
if (m_currentCompletion == m_completionList.size())
|
||||
m_currentCompletion = 0;
|
||||
}
|
||||
m_entry->SetText(m_precompletionStatement + m_completionList[m_currentCompletion]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LuaConsole::OnChange(const std::string &text) {
|
||||
void LuaConsole::OnChange(const std::string &text)
|
||||
{
|
||||
m_completionList.clear();
|
||||
}
|
||||
|
||||
void LuaConsole::OnEnter(const std::string &text) {
|
||||
void LuaConsole::OnEnter(const std::string &text)
|
||||
{
|
||||
if (!text.empty())
|
||||
ExecOrContinue(text);
|
||||
m_completionList.clear();
|
||||
|
@ -267,7 +264,8 @@ void LuaConsole::OnEnter(const std::string &text) {
|
|||
m_scroller->SetScrollPosition(1.0f);
|
||||
}
|
||||
|
||||
void LuaConsole::UpdateCompletion(const std::string & statement) {
|
||||
void LuaConsole::UpdateCompletion(const std::string &statement)
|
||||
{
|
||||
// First, split the statement into chunks.
|
||||
m_completionList.clear();
|
||||
std::stack<std::string> chunks;
|
||||
|
@ -276,13 +274,13 @@ void LuaConsole::UpdateCompletion(const std::string & statement) {
|
|||
std::string::const_iterator current_end = statement.end();
|
||||
std::string::const_iterator current_begin = statement.begin(); // To keep record when breaking off the loop.
|
||||
for (std::string::const_reverse_iterator r_str_it = statement.rbegin();
|
||||
r_str_it != statement.rend(); ++r_str_it) {
|
||||
if(Text::is_alphanumunderscore(*r_str_it)) {
|
||||
r_str_it != statement.rend(); ++r_str_it) {
|
||||
if (Text::is_alphanumunderscore(*r_str_it)) {
|
||||
expect_symbolname = false;
|
||||
continue;
|
||||
} else if (expect_symbolname) // Wrong syntax.
|
||||
return;
|
||||
if(*r_str_it != '.' && (!chunks.empty() || *r_str_it != ':')) { // We are out of the expression.
|
||||
if (*r_str_it != '.' && (!chunks.empty() || *r_str_it != ':')) { // We are out of the expression.
|
||||
current_begin = r_str_it.base(); // Flag the symbol marking the beginning of the expression.
|
||||
break;
|
||||
}
|
||||
|
@ -290,8 +288,8 @@ void LuaConsole::UpdateCompletion(const std::string & statement) {
|
|||
expect_symbolname = true; // We hit a separator, there should be a symbol name before it.
|
||||
chunks.push(std::string(r_str_it.base(), current_end));
|
||||
if (*r_str_it == ':') // If it is a colon, we know chunks is empty so it is incomplete.
|
||||
method = true; // it must mean that we want to call a method.
|
||||
current_end = (r_str_it+1).base(); // +1 in order to point on the CURRENT character.
|
||||
method = true; // it must mean that we want to call a method.
|
||||
current_end = (r_str_it + 1).base(); // +1 in order to point on the CURRENT character.
|
||||
}
|
||||
if (expect_symbolname) // Again, a symbol was expected when we broke out of the loop.
|
||||
return;
|
||||
|
@ -303,7 +301,7 @@ void LuaConsole::UpdateCompletion(const std::string & statement) {
|
|||
return;
|
||||
}
|
||||
|
||||
lua_State * l = Lua::manager->GetLuaState();
|
||||
lua_State *l = Lua::manager->GetLuaState();
|
||||
int stackheight = lua_gettop(l);
|
||||
lua_getfield(l, LUA_REGISTRYINDEX, "ConsoleGlobal");
|
||||
// Loading the tables in which to do the name lookup
|
||||
|
@ -315,7 +313,7 @@ void LuaConsole::UpdateCompletion(const std::string & statement) {
|
|||
chunks.pop();
|
||||
}
|
||||
LuaObjectBase::GetNames(m_completionList, chunks.top(), method);
|
||||
if(!m_completionList.empty()) {
|
||||
if (!m_completionList.empty()) {
|
||||
std::sort(m_completionList.begin(), m_completionList.end());
|
||||
m_completionList.erase(std::unique(m_completionList.begin(), m_completionList.end()), m_completionList.end());
|
||||
// Add blank completion at the end of the list and point to it.
|
||||
|
@ -324,10 +322,11 @@ void LuaConsole::UpdateCompletion(const std::string & statement) {
|
|||
|
||||
m_precompletionStatement = statement;
|
||||
}
|
||||
lua_pop(l, lua_gettop(l)-stackheight); // Clean the whole stack.
|
||||
lua_pop(l, lua_gettop(l) - stackheight); // Clean the whole stack.
|
||||
}
|
||||
|
||||
void LuaConsole::AddOutput(const std::string &line) {
|
||||
void LuaConsole::AddOutput(const std::string &line)
|
||||
{
|
||||
std::string actualLine = line + "\n";
|
||||
m_output->AppendText(actualLine);
|
||||
#ifdef REMOTE_LUA_REPL
|
||||
|
@ -335,12 +334,13 @@ void LuaConsole::AddOutput(const std::string &line) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void LuaConsole::ExecOrContinue(const std::string &stmt, bool repeatStatement) {
|
||||
void LuaConsole::ExecOrContinue(const std::string &stmt, bool repeatStatement)
|
||||
{
|
||||
int result;
|
||||
lua_State *L = Lua::manager->GetLuaState();
|
||||
|
||||
// If the statement is an expression, print its final value.
|
||||
result = luaL_loadbuffer(L, ("return " + stmt).c_str(), stmt.size()+7, CONSOLE_CHUNK_NAME);
|
||||
result = luaL_loadbuffer(L, ("return " + stmt).c_str(), stmt.size() + 7, CONSOLE_CHUNK_NAME);
|
||||
if (result == LUA_ERRSYNTAX)
|
||||
result = luaL_loadbuffer(L, stmt.c_str(), stmt.size(), CONSOLE_CHUNK_NAME);
|
||||
|
||||
|
@ -387,7 +387,7 @@ void LuaConsole::ExecOrContinue(const std::string &stmt, bool repeatStatement) {
|
|||
std::getline(stmt_stream, string_buffer);
|
||||
AddOutput("> " + string_buffer);
|
||||
|
||||
while(!stmt_stream.eof()) {
|
||||
while (!stmt_stream.eof()) {
|
||||
std::getline(stmt_stream, string_buffer);
|
||||
AddOutput(" " + string_buffer);
|
||||
}
|
||||
|
@ -422,7 +422,7 @@ void LuaConsole::ExecOrContinue(const std::string &stmt, bool repeatStatement) {
|
|||
|
||||
// duplicate the tostring function for the call
|
||||
lua_pushvalue(L, -1);
|
||||
lua_pushvalue(L, top+i);
|
||||
lua_pushvalue(L, top + i);
|
||||
|
||||
result = lua_pcall(L, 1, 1, 0);
|
||||
size_t len = 0;
|
||||
|
@ -444,7 +444,7 @@ void LuaConsole::ExecOrContinue(const std::string &stmt, bool repeatStatement) {
|
|||
|
||||
// update the history list
|
||||
|
||||
if (! result) {
|
||||
if (!result) {
|
||||
// command succeeded... add it to the history unless it's just
|
||||
// an exact repeat of the immediate last command
|
||||
if (m_statementHistory.empty() || (stmt != m_statementHistory.back()))
|
||||
|
@ -484,7 +484,8 @@ void LuaConsole::ExecOrContinue(const std::string &stmt, bool repeatStatement) {
|
|||
*
|
||||
* stable
|
||||
*/
|
||||
static int l_console_addline(lua_State *L) {
|
||||
static int l_console_addline(lua_State *L)
|
||||
{
|
||||
if (Pi::luaConsole) {
|
||||
size_t len;
|
||||
const char *s = luaL_checklstring(L, 1, &len);
|
||||
|
@ -493,7 +494,8 @@ static int l_console_addline(lua_State *L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int l_console_print(lua_State *L) {
|
||||
static int l_console_print(lua_State *L)
|
||||
{
|
||||
int nargs = lua_gettop(L);
|
||||
LUA_DEBUG_START(L);
|
||||
std::string line;
|
||||
|
@ -504,8 +506,12 @@ static int l_console_print(lua_State *L) {
|
|||
lua_call(L, 1, 1);
|
||||
size_t len;
|
||||
const char *str = lua_tolstring(L, -1, &len);
|
||||
if (!str) { return luaL_error(L, "'tostring' must return a string to 'print'"); }
|
||||
if (i > 1) { line += '\t'; }
|
||||
if (!str) {
|
||||
return luaL_error(L, "'tostring' must return a string to 'print'");
|
||||
}
|
||||
if (i > 1) {
|
||||
line += '\t';
|
||||
}
|
||||
line.append(str, len);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
@ -539,7 +545,8 @@ void LuaConsole::Register()
|
|||
}
|
||||
|
||||
#ifdef REMOTE_LUA_REPL
|
||||
void LuaConsole::OpenTCPDebugConnection(int portnumber) {
|
||||
void LuaConsole::OpenTCPDebugConnection(int portnumber)
|
||||
{
|
||||
m_debugSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (m_debugSocket < 0) {
|
||||
Output("Error opening socket");
|
||||
|
@ -549,9 +556,9 @@ void LuaConsole::OpenTCPDebugConnection(int portnumber) {
|
|||
destination.sin_family = AF_INET;
|
||||
destination.sin_port = htons(portnumber);
|
||||
destination.sin_addr.s_addr = INADDR_ANY; // this should be localhost only!
|
||||
if (bind(m_debugSocket, reinterpret_cast<struct sockaddr*>(&destination), sizeof(destination)) < 0) {
|
||||
if (bind(m_debugSocket, reinterpret_cast<struct sockaddr *>(&destination), sizeof(destination)) < 0) {
|
||||
Output("Binding socket failed.\n");
|
||||
if(m_debugSocket) {
|
||||
if (m_debugSocket) {
|
||||
close(m_debugSocket);
|
||||
m_debugSocket = 0;
|
||||
return;
|
||||
|
@ -568,12 +575,13 @@ void LuaConsole::OpenTCPDebugConnection(int portnumber) {
|
|||
}
|
||||
}
|
||||
|
||||
void LuaConsole::HandleTCPDebugConnections() {
|
||||
void LuaConsole::HandleTCPDebugConnections()
|
||||
{
|
||||
if (m_debugSocket) {
|
||||
fd_set read_fds;
|
||||
FD_ZERO(&read_fds);
|
||||
FD_SET(m_debugSocket, &read_fds);
|
||||
struct timespec timeout = {0,0};
|
||||
struct timespec timeout = { 0, 0 };
|
||||
|
||||
int res = pselect(m_debugSocket + 1, &read_fds, NULL, NULL, &timeout, NULL);
|
||||
if (res < 0 && errno != EINTR) {
|
||||
|
@ -583,12 +591,13 @@ void LuaConsole::HandleTCPDebugConnections() {
|
|||
HandleNewDebugTCPConnection(m_debugSocket);
|
||||
}
|
||||
}
|
||||
for(int sock : m_debugConnections) {
|
||||
for (int sock : m_debugConnections) {
|
||||
HandleDebugTCPConnection(sock);
|
||||
}
|
||||
}
|
||||
|
||||
void LuaConsole::HandleNewDebugTCPConnection(int socket) {
|
||||
void LuaConsole::HandleNewDebugTCPConnection(int socket)
|
||||
{
|
||||
int sock = accept(socket, NULL, 0);
|
||||
if (sock < 0) {
|
||||
Output("Error accepting on socket.\n");
|
||||
|
@ -610,25 +619,27 @@ void LuaConsole::HandleNewDebugTCPConnection(int socket) {
|
|||
}
|
||||
|
||||
// TODO: these should not be here, do we need them generally? Maybe in utils.cpp?
|
||||
static std::string <rim(std::string & str)
|
||||
static std::string <rim(std::string &str)
|
||||
{
|
||||
auto it2 = std::find_if( str.begin() , str.end() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
|
||||
str.erase( str.begin() , it2);
|
||||
auto it2 = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
|
||||
str.erase(str.begin(), it2);
|
||||
return str;
|
||||
}
|
||||
|
||||
static std::string &rtrim(std::string & str)
|
||||
static std::string &rtrim(std::string &str)
|
||||
{
|
||||
auto it1 = std::find_if( str.rbegin() , str.rend() , [](char ch){ return !std::isspace<char>(ch , std::locale::classic() ) ; } );
|
||||
str.erase( it1.base() , str.end() );
|
||||
auto it1 = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace<char>(ch, std::locale::classic()); });
|
||||
str.erase(it1.base(), str.end());
|
||||
return str;
|
||||
}
|
||||
|
||||
static std::string &trim(std::string &str) {
|
||||
static std::string &trim(std::string &str)
|
||||
{
|
||||
return ltrim(rtrim(str));
|
||||
}
|
||||
|
||||
void LuaConsole::HandleDebugTCPConnection(int sock) {
|
||||
void LuaConsole::HandleDebugTCPConnection(int sock)
|
||||
{
|
||||
char buffer[4097];
|
||||
int count = read(sock, buffer, 4096);
|
||||
if (count < 0 && errno != EAGAIN) {
|
||||
|
@ -644,13 +655,14 @@ void LuaConsole::HandleDebugTCPConnection(int sock) {
|
|||
}
|
||||
}
|
||||
|
||||
void LuaConsole::BroadcastToDebuggers(const std::string &message) {
|
||||
for(int sock : m_debugConnections) {
|
||||
if(send(sock, message.c_str(), message.size(), MSG_NOSIGNAL) < 0) {
|
||||
Output("Closing debug socket, error %d.\n", errno);
|
||||
close(sock);
|
||||
m_debugConnections.erase(std::remove(m_debugConnections.begin(), m_debugConnections.end(), sock), m_debugConnections.end());
|
||||
};
|
||||
}
|
||||
void LuaConsole::BroadcastToDebuggers(const std::string &message)
|
||||
{
|
||||
for (int sock : m_debugConnections) {
|
||||
if (send(sock, message.c_str(), message.size(), MSG_NOSIGNAL) < 0) {
|
||||
Output("Closing debug socket, error %d.\n", errno);
|
||||
close(sock);
|
||||
m_debugConnections.erase(std::remove(m_debugConnections.begin(), m_debugConnections.end(), sock), m_debugConnections.end());
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
#define _LUACONSOLE_H
|
||||
|
||||
#include "LuaManager.h"
|
||||
#include "ui/Widget.h"
|
||||
#include "RefCounted.h"
|
||||
#include "ui/Widget.h"
|
||||
#include <deque>
|
||||
|
||||
namespace UI {
|
||||
class TextEntry;
|
||||
class MultiLineText;
|
||||
class Scroller;
|
||||
}
|
||||
} // namespace UI
|
||||
|
||||
class LuaConsole {
|
||||
public:
|
||||
|
@ -31,16 +31,17 @@ public:
|
|||
#endif
|
||||
|
||||
static void Register();
|
||||
|
||||
private:
|
||||
bool OnKeyDown(const UI::KeyboardEvent &event);
|
||||
void OnChange(const std::string &text);
|
||||
void OnEnter(const std::string &text);
|
||||
|
||||
void ExecOrContinue(const std::string &stmt, bool repeatStatement=true);
|
||||
void ExecOrContinue(const std::string &stmt, bool repeatStatement = true);
|
||||
|
||||
void OnKeyPressed(const SDL_Keysym*);
|
||||
void OnKeyPressed(const SDL_Keysym *);
|
||||
void OnTextChanged();
|
||||
void UpdateCompletion(const std::string & statement);
|
||||
void UpdateCompletion(const std::string &statement);
|
||||
void RegisterAutoexec();
|
||||
|
||||
#ifdef REMOTE_LUA_REPL
|
||||
|
|
|
@ -13,6 +13,6 @@ namespace LuaConstants {
|
|||
int GetConstant(lua_State *l, const char *ns, const char *name);
|
||||
bool CheckConstant(lua_State *l, const char *ns, const char *name, int *out);
|
||||
bool CheckConstantFromArg(lua_State *m, const char *ns, int idx, int *out);
|
||||
}
|
||||
} // namespace LuaConstants
|
||||
|
||||
#endif
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue