Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add interior lighting to stations #5823

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@ mesh station_ring_2-10k.dae


collision station_hub_A_coll.dae
collision station_ring_2-10k_coll.dae
collision station_ring_2-10k_coll.dae

bound capsule interior tag_interior0 tag_interior1 70
bound capsule interior tag_interior1 tag_interior2 110
bound capsule interior tag_interior2 tag_interior3 70
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,8 @@ mesh station_ring_2-2k.dae


collision station_B_coll.dae
#collision station_ring_2-5k_coll.dae
#collision station_ring_2-5k_coll.dae

bound capsule interior tag_interior1 tag_interior2 70
bound capsule interior tag_interior2 tag_interior3 120
bound capsule interior tag_interior3 tag_interior4 70
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@ mesh station_ring_2-5k.dae


collision station_hub_A_coll.dae
collision station_ring_2-5k_coll.dae
collision station_ring_2-5k_coll.dae

bound capsule interior tag_interior0 tag_interior1 70
bound capsule interior tag_interior1 tag_interior2 110
bound capsule interior tag_interior2 tag_interior3 70
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@ mesh station_ring_2-10k.dae


collision station_hub_A_coll.dae
collision station_ring_2-5k10k_coll.dae
collision station_ring_2-5k10k_coll.dae

bound capsule interior tag_interior0 tag_interior1 70
bound capsule interior tag_interior1 tag_interior2 110
bound capsule interior tag_interior2 tag_interior3 70
9,234 changes: 4,791 additions & 4,443 deletions data/models/stations/orbital_station/station_hub_A.dae

Large diffs are not rendered by default.

2,134 changes: 1,136 additions & 998 deletions data/models/stations/orbital_station/station_hub_B.dae

Large diffs are not rendered by default.

84 changes: 67 additions & 17 deletions src/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "graphics/TextureBuilder.h"
#include "graphics/Types.h"
#include "graphics/RenderState.h"
#include "SpaceStation.h"

using namespace Graphics;

Expand Down Expand Up @@ -150,11 +151,13 @@ void Camera::Update()

// evaluate each body and determine if/where/how to draw it
m_sortedBodies.clear();
m_spaceStations.clear();
for (Body *b : Pi::game->GetSpace()->GetBodies()) {
BodyAttrs attrs;
attrs.body = b;
attrs.billboard = false; // false by default
attrs.calcAtmosphereLighting = false; // false by default
attrs.calcInteriorLighting = false;

// If the body wishes to be excluded from the draw, skip it.
if (b->GetFlags() & Body::FLAG_DRAW_EXCLUDE)
Expand Down Expand Up @@ -222,7 +225,15 @@ void Camera::Update()
attrs.calcAtmosphereLighting = true;
}

if(b->IsType(ObjectType::SHIP)) {
attrs.calcInteriorLighting = true;
}

m_sortedBodies.push_back(attrs);

if(b->IsType(ObjectType::SPACESTATION)) {
m_spaceStations.push_back(b);
}
}

// depth sort
Expand Down Expand Up @@ -297,11 +308,12 @@ void Camera::Draw(const Body *excludeBody)
m_renderer->SetLights(rendererLights.size(), &rendererLights[0]);
}

std::vector<float> oldIntensities;
// Save lights for later restoring
oldLightIntensities.clear();
std::vector<float> lightIntensities;
for (size_t i = 0; i < m_lightSources.size(); i++) {
lightIntensities.push_back(1.0);
oldIntensities.push_back(m_renderer->GetLight(i).GetIntensity());
oldLightIntensities.push_back(m_renderer->GetLight(i).GetIntensity());
lightIntensities.push_back(1.0f);
}

Graphics::VertexArray billboards(Graphics::ATTRIB_POSITION | Graphics::ATTRIB_NORMAL);
Expand All @@ -319,23 +331,11 @@ void Camera::Draw(const Body *excludeBody)
continue;
}

double ambient = 0.05, direct = 1.0;
if (attrs->calcAtmosphereLighting)
CalcLighting(attrs->body, ambient, direct);

for (size_t i = 0; i < m_lightSources.size(); i++)
lightIntensities[i] = direct * ShadowedIntensity(i, attrs->body);

// Setup dynamic lighting parameters
m_renderer->SetAmbientColor(Color(ambient * 255, ambient * 255, ambient * 255));
m_renderer->SetLightIntensity(m_lightSources.size(), lightIntensities.data());

PrepareLighting(attrs->body, attrs->calcAtmosphereLighting, attrs->calcInteriorLighting);
attrs->body->Render(m_renderer, this, attrs->viewCoords, attrs->viewTransform);
}

// Restore default ambient color and direct light intensities
m_renderer->SetAmbientColor(Color(255, 255, 255));
m_renderer->SetLightIntensity(m_lightSources.size(), oldIntensities.data());
RestoreLighting();

if (!billboards.IsEmpty()) {
Graphics::Renderer::MatrixTicket mt(m_renderer, matrix4x4f::Identity());
Expand Down Expand Up @@ -555,3 +555,53 @@ void Camera::PrincipalShadows(const Body *b, const int n, std::vector<Shadow> &s
shadowsOut.push_back(*(it++));
}
}
void Camera::CalcInteriorLighting(const Body* b, Color4ub &sLight, double &sFac) const
{
for(const auto& ss : m_spaceStations) {
const SpaceStation* as_ss = static_cast<SpaceStation *>(ss);
const double distance2 = as_ss->GetPositionRelTo(b).LengthSqr();
const double maxClip = b->GetClipRadius() + ss->GetClipRadius();

// This short-circuits for efficient checking. Only one station may actually set
// lighting values in CalcInteriorLighting, which is why we return as soon as that happens
if (distance2 < maxClip * maxClip && as_ss->CalcInteriorLighting(b, sLight, sFac))
return;
}
}

void Camera::PrepareLighting(const Body *b, bool doAtmosphere, bool doInteriors) const
{
std::vector<float> lightIntensities;

double ambient = 0.05, direct = 1.0;
if (doAtmosphere)
CalcLighting(b, ambient, direct);

Color4ub ambientLightColor = Color::WHITE;
Color4ub stationLightColor = Color::WHITE;
double stationFactor = 0.0;

if (doInteriors)
CalcInteriorLighting(b, stationLightColor, stationFactor);

direct = direct * (1.0 - stationFactor);
ambient = ambient * (1.0 - stationFactor) + stationFactor;

for (size_t i = 0; i < m_lightSources.size(); i++)
lightIntensities.push_back(direct * ShadowedIntensity(i, b));

// Setup dynamic lighting parameters
Color4ub ambientMix = (ambientLightColor.Shade((float)stationFactor)
+ stationLightColor.Shade(1.0f - stationFactor)).Shade(1.0 - ambient);
ambientMix.a = 255;

m_renderer->SetAmbientColor(ambientMix);
m_renderer->SetLightIntensity(m_lightSources.size(), lightIntensities.data());

}

void Camera::RestoreLighting() const
{
m_renderer->SetAmbientColor(Color::WHITE);
m_renderer->SetLightIntensity(m_lightSources.size(), oldLightIntensities.data());
}
15 changes: 15 additions & 0 deletions src/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,26 @@ class Camera {
};

void CalcLighting(const Body *b, double &ambient, double &direct) const;
void CalcInteriorLighting(const Body* b, Color4ub &sLight, double &sFac) const;
void CalcShadows(const int lightNum, const Body *b, std::vector<Shadow> &shadowsOut) const;
float ShadowedIntensity(const int lightNum, const Body *b) const;
void PrincipalShadows(const Body *b, const int n, std::vector<Shadow> &shadowsOut) const;

// lights with properties in camera space
const std::vector<LightSource> &GetLightSources() const { return m_lightSources; }
int GetNumLightSources() const { return static_cast<Uint32>(m_lightSources.size()); }
// Used for lighting the cockpit (and other bodies not directly rendered by the camera)
const std::vector<Body*> GetSpaceStations() const { return m_spaceStations; }

// Sets renderer lighting so that the body is renderer appropiately lit
void PrepareLighting(const Body* b, bool doAtmosphere, bool doInteriors) const;
// Restores default lights, use after rendering an object with custom lighting
// to avoid those bleeding into other objects
void RestoreLighting() const;

private:
std::vector<float> oldLightIntensities;

RefCountedPtr<CameraContext> m_context;
Graphics::Renderer *m_renderer;

Expand All @@ -145,6 +156,8 @@ class Camera {

// if true, calculate atmosphere-attenuated light intensity for the body
bool calcAtmosphereLighting;
// if true, calculate interior light intensity for the body
bool calcInteriorLighting;

// if true, draw object as billboard of billboardSize at billboardPos
bool billboard;
Expand All @@ -163,6 +176,8 @@ class Camera {
};

std::list<BodyAttrs> m_sortedBodies;
// For interior check
std::vector<Body*> m_spaceStations;
std::vector<LightSource> m_lightSources;
};

Expand Down
16 changes: 2 additions & 14 deletions src/ShipCockpit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,9 @@ void ShipCockpit::Render(Graphics::Renderer *renderer, const Camera *camera, con
{
PROFILE_SCOPED()

double ambient = 0.0;
double direct = 0.5;

if (static_cast<Ship *>(m_ship)->GetFlightState() != Ship::HYPERSPACE)
camera->CalcLighting(m_ship, ambient, direct);

std::vector<float> lightIntensities;
for (int i = 0; i < camera->GetNumLightSources(); i++)
lightIntensities.push_back(direct * camera->ShadowedIntensity(i, m_ship));

// Setup dynamic lighting parameters
renderer->SetAmbientColor(Color(ambient * 255, ambient * 255, ambient * 255));
renderer->SetLightIntensity(camera->GetNumLightSources(), lightIntensities.data());

camera->PrepareLighting(this, true, true);
RenderModel(renderer, camera, viewCoords, viewTransform);
camera->RestoreLighting();
Comment on lines +43 to +45
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tested this during hyperjump to ensure it doesn't crash / assert (using e.g. an address sanitizer build)?

}

inline void ShipCockpit::resetInternalCameraController()
Expand Down
16 changes: 16 additions & 0 deletions src/SpaceStation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -903,3 +903,19 @@ double SpaceStation::GetUndockAnimStageDuration(int bay, DockStage stage) const
return stageLength / averageVelocity;
}

bool SpaceStation::CalcInteriorLighting(const Body *b, Color4ub &sLight, double& sIntense) const
{
vector3d bPoint = b->GetPositionRelTo(this);
const float dist = GetModel()->DistanceFromPointToBound("interior", vector3f(bPoint));

// This number can be tweaked to make fading more / less gradual,
// it could depend on ship size but this value feels good on all current ships
const float bRadius = 30.0f;
if(dist - bRadius < 0.0f) {
sIntense = std::max(std::min((bRadius - dist) / bRadius, 1.0f), 0.0f);
sLight = Color::GRAY;
return true;
}

return false;
}
5 changes: 5 additions & 0 deletions src/SpaceStation.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ class SpaceStation : public ModelBody {
// need this now because stations rotate in their frame
virtual void UpdateInterpTransform(double alpha) override;

// Return true if any lightning changes were applied, only do so if body is inside
// or near enough to the station
bool CalcInteriorLighting(const Body *b, Color4ub& sLight, double& sIntensity) const;


protected:
virtual void SaveToJson(Json &jsonObj, Space *space) override;

Expand Down
26 changes: 26 additions & 0 deletions src/scenegraph/BinaryConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,22 @@ void BinaryConverter::Save(const std::string &filename, const std::string &savep

SaveAnimations(wr, m);

// save bounds
wr.Int32(m->m_bounds.size());
for(const RunTimeBoundDefinition& bdef : m->m_bounds) {
wr.Int16(bdef.boundDef.type);
wr.String(bdef.boundDef.forBound);
wr.String(bdef.boundDef.startTag);
wr.String(bdef.boundDef.endTag);
wr.Float(static_cast<float>(bdef.boundDef.radius));
}

//save tags
wr.Int32(m->GetNumTags());
for (unsigned int i = 0; i < m->GetNumTags(); i++)
wr.String(m->GetTagByIndex(i)->GetName().c_str());


// compress in memory, write to open file
size_t outSize = 0;
const std::string &data = wr.GetData();
Expand Down Expand Up @@ -252,6 +263,21 @@ Model *BinaryConverter::CreateModel(const std::string &filename, Serializer::Rea

LoadAnimations(rd);

// load bounds
const int num_bounds = rd.Int32();
for(int i = 0; i < num_bounds; i++) {
BoundDefinition bdef;
bdef.type = static_cast<BoundDefinition::Type>(rd.Int16());
bdef.forBound = rd.String();
bdef.startTag = rd.String();
bdef.endTag = rd.String();
bdef.radius = static_cast<double>(rd.Float());
m_model->m_bounds.push_back(RunTimeBoundDefinition(m_model, bdef));
}

// TODO: load tags? They are saved in BinaryConverter::Save, but
// should be loaded with the model itself...

m_model->InitAnimations();
//m_model->CreateCollisionMesh();
if (m_patternsUsed) SetUpPatterns();
Expand Down
3 changes: 2 additions & 1 deletion src/scenegraph/BinaryConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ namespace SceneGraph {
// 6.1: rewrote serialization, use lz4 compression instead of INFLATE/DEFLATE. Still compatible.
// 6.2: ignored StaticGeometry::m_blendMode in files. Still write blank value.
// 7: Added discrete Tag node, tags are registered in the model hierarchy instead of at the root.
constexpr Uint32 SGM_VERSION = 7;
// 8: Save model bound metadata
constexpr Uint32 SGM_VERSION = 8;

class BinaryConverter : public BaseLoader {
public:
Expand Down
5 changes: 5 additions & 0 deletions src/scenegraph/Loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ namespace SceneGraph {

Model *model = new Model(m_renderer, def.name);
m_model = model;

for(const BoundDefinition& bdef : def.boundsDefs) {
m_model->m_bounds.push_back(RunTimeBoundDefinition(m_model, bdef));
}

bool patternsUsed = false;

m_thrustersRoot.Reset(new Group(m_renderer));
Expand Down
30 changes: 30 additions & 0 deletions src/scenegraph/LoaderDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Data strcutrures used by Loader
*/
#include "Color.h"
#include "../vector3.h"

#include <string>
#include <vector>
Expand Down Expand Up @@ -69,12 +70,41 @@ namespace SceneGraph {
bool loop;
};

struct BoundDefinition {
Web-eWorks marked this conversation as resolved.
Show resolved Hide resolved
enum Type {
// Capsule (cylinder with rounded end-caps)
// startTag, endTag define the endpoints of the central line of the cylinder
// radius defines both the radius of the cylinder and the radius of the endcaps
CAPSULE,
};
Type type;
std::string startTag;
std::string endTag;
double radius;

// What boundary does this bound definition refer to?
std::string forBound;

static BoundDefinition create_capsule(const std::string &for_b, const std::string &start,
const std::string &end, const double rad) {
BoundDefinition out;
out.type = CAPSULE;
out.startTag = start;
out.endTag = end;
out.radius = rad;
out.forBound = for_b;
return out;
}

};

struct ModelDefinition {
std::string name;
std::vector<LodDefinition> lodDefs;
std::vector<MaterialDefinition> matDefs;
std::vector<std::string> collisionDefs;
std::vector<AnimDefinition> animDefs;
std::vector<BoundDefinition> boundsDefs;
};

} // namespace SceneGraph
Expand Down
Loading