pioneer/src/HyperspaceCloud.cpp

180 lines
4.9 KiB
C++
Raw Normal View History

2012-09-12 04:38:30 -07:00
// Copyright © 2008-2012 Pioneer Developers. See AUTHORS.txt for details
2012-09-15 17:59:15 -07:00
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
2012-09-12 04:38:30 -07:00
#include "HyperspaceCloud.h"
2012-08-04 13:19:46 -07:00
#include "libs.h"
#include "Game.h"
#include "Lang.h"
#include "perlin.h"
#include "Pi.h"
2012-08-04 13:19:46 -07:00
#include "Player.h"
#include "Serializer.h"
2012-08-04 13:19:46 -07:00
#include "Ship.h"
#include "Space.h"
#include "graphics/Graphics.h"
2012-08-04 13:19:46 -07:00
#include "graphics/Material.h"
#include "graphics/Renderer.h"
#include "graphics/VertexArray.h"
using namespace Graphics;
HyperspaceCloud::HyperspaceCloud(Ship *s, double dueDate, bool isArrival)
{
m_flags = Body::FLAG_CAN_MOVE_FRAME |
Body::FLAG_LABEL_HIDDEN;
m_ship = s;
m_pos = vector3d(0,0,0);
2012-11-26 15:40:03 -08:00
SetPhysRadius(0.0);
SetClipRadius(0.0);
m_vel = (s ? s->GetVelocity() : vector3d(0.0));
2011-11-21 13:33:03 -08:00
m_birthdate = Pi::game->GetTime();
m_due = dueDate;
SetIsArrival(isArrival);
InitGraphics();
}
HyperspaceCloud::HyperspaceCloud()
{
m_ship = 0;
m_pos = vector3d(0,0,0);
2012-11-26 15:40:03 -08:00
SetPhysRadius(0.0);
SetClipRadius(0.0);
InitGraphics();
}
void HyperspaceCloud::InitGraphics()
{
m_graphic.vertices.Reset(new Graphics::VertexArray(ATTRIB_POSITION | ATTRIB_DIFFUSE));
Graphics::MaterialDescriptor desc;
desc.vertexColors = true;
m_graphic.material.Reset(Pi::renderer->CreateMaterial(desc));
}
HyperspaceCloud::~HyperspaceCloud()
{
if (m_ship) delete m_ship;
}
void HyperspaceCloud::SetIsArrival(bool isArrival)
{
m_isArrival = isArrival;
SetLabel(isArrival ? Lang::HYPERSPACE_ARRIVAL_CLOUD : Lang::HYPERSPACE_DEPARTURE_CLOUD);
}
vector3d HyperspaceCloud::GetPosition() const
{
return m_pos;
}
void HyperspaceCloud::SetPosition(const vector3d &p)
{
m_pos = p;
}
void HyperspaceCloud::Save(Serializer::Writer &wr, Space *space)
{
Body::Save(wr, space);
wr.Vector3d(m_pos);
wr.Vector3d(m_vel);
wr.Double(m_birthdate);
wr.Double(m_due);
wr.Bool(m_isArrival);
wr.Bool(m_ship != 0);
if (m_ship) m_ship->Serialize(wr, space);
}
void HyperspaceCloud::Load(Serializer::Reader &rd, Space *space)
{
Body::Load(rd, space);
m_pos = rd.Vector3d();
m_vel = rd.Vector3d();
m_birthdate = rd.Double();
m_due = rd.Double();
m_isArrival = rd.Bool();
if (rd.Bool()) {
m_ship = reinterpret_cast<Ship*>(Body::Unserialize(rd, space));
}
}
void HyperspaceCloud::PostLoadFixup(Space *space)
{
2012-12-11 19:18:42 -08:00
Body::PostLoadFixup(space);
if (m_ship) m_ship->PostLoadFixup(space);
}
void HyperspaceCloud::TimeStepUpdate(const float timeStep)
{
m_pos += m_vel * timeStep;
2011-11-21 13:33:03 -08:00
if (m_isArrival && m_ship && (m_due < Pi::game->GetTime())) {
// spawn ship
// XXX some overlap with Space::DoHyperspaceTo(). should probably all
// be moved into EvictShip()
m_ship->SetPosition(m_pos);
m_ship->SetVelocity(m_vel);
2012-11-18 10:13:47 -08:00
m_ship->SetOrient(matrix3x3d::Identity());
m_ship->SetFrame(GetFrame());
Pi::game->GetSpace()->AddBody(m_ship);
if (Pi::player->GetNavTarget() == this && !Pi::player->GetCombatTarget())
Pi::player->SetCombatTarget(m_ship, Pi::player->GetSetSpeedTarget() == this);
m_ship->EnterSystem();
m_ship = 0;
}
}
Ship *HyperspaceCloud::EvictShip()
{
Ship *s = m_ship;
m_ship = 0;
return s;
}
2012-01-20 11:01:24 -08:00
static void make_circle_thing(VertexArray &va, float radius, const Color &colCenter, const Color &colEdge)
{
2012-01-20 11:01:24 -08:00
va.Add(vector3f(0.f, 0.f, 0.f), colCenter);
for (float ang=0; ang<float(M_PI)*2.f; ang+=0.1f) {
2012-01-20 11:01:24 -08:00
va.Add(vector3f(radius*sin(ang), radius*cos(ang), 0.0f), colEdge);
}
2012-01-20 11:01:24 -08:00
va.Add(vector3f(0.f, radius, 0.f), colEdge);
}
2012-11-18 10:13:47 -08:00
void HyperspaceCloud::UpdateInterpTransform(double alpha)
{
2012-11-18 10:13:47 -08:00
m_interpOrient = matrix3x3d::Identity();
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)
{
renderer->SetBlendMode(BLEND_ALPHA_ONE);
glPushMatrix();
2012-02-14 07:16:52 -08:00
matrix4x4d trans = matrix4x4d::Identity();
trans.Translate(float(viewCoords.x), float(viewCoords.y), float(viewCoords.z));
// face the camera dammit
2011-03-06 17:14:46 -08:00
vector3d zaxis = viewCoords.NormalizedSafe();
vector3d xaxis = vector3d(0,1,0).Cross(zaxis).Normalized();
vector3d yaxis = zaxis.Cross(xaxis);
matrix4x4d rot = matrix4x4d::MakeRotMatrix(xaxis, yaxis, zaxis).InverseOf();
2012-02-14 07:16:52 -08:00
renderer->SetTransform(trans * rot);
// precise to the rendered frame (better than PHYSICS_HZ granularity)
2012-08-04 13:19:46 -07:00
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(10.0*preciseTime, 0, 0));
m_graphic.vertices->Clear();
Color4f outerColor = m_isArrival ? Color::BLUE : Color::RED;
outerColor.a = 0.f;
make_circle_thing(*m_graphic.vertices.Get(), radius, Color(1.0,1.0,1.0,1.0), outerColor);
2012-08-04 13:19:46 -07:00
renderer->DrawTriangles(m_graphic.vertices.Get(), m_graphic.material.Get(), TRIANGLE_FAN);
renderer->SetBlendMode(BLEND_SOLID);
glPopMatrix();
}