diff --git a/src/Makefile.am b/src/Makefile.am index 4132250..646a1dc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,7 @@ Lephisto3D_SOURCES = main.cpp gui_button.cpp gui.cpp gui_fixed.cpp gui_screen.cp gui_image_radio_button.cpp gui_multi_state_image_button.cpp ship_cpanel.cpp gui_widget.cpp sector_view.cpp \ mtrand.cpp world_view.cpp system_view.cpp star_system.cpp sector.cpp system_info_view.cpp generic_system_view.cpp \ gui_container.cpp date.cpp space_station.cpp space_station_view.cpp model_body.cpp ship_type.cpp \ - info_view.cpp model_coll_mesh_data.cpp + info_view.cpp model_coll_mesh_data.cpp object_viewer_view.cpp Lephisto3D_LDADD = sbre/libsbre.a include_HEADERS = body.h frame.h generic_system_view.h glfreetype.h gui_button.h gui_container.h gui_events.h gui_fixed.h \ @@ -16,5 +16,5 @@ include_HEADERS = body.h frame.h generic_system_view.h glfreetype.h gui_button.h gui_radio_group.h gui_screen.h gui_toggle_button.h gui_widget.h libs.h matrix4x4.h mtrand.h objimport.h l3d.h \ planet.h player.h dynamic_body.h sector.h sector_view.h ship_cpanel.h ship.h space.h star.h star_system.h system_info_view.h \ system_view.h vector3.h view.h world_view.h date.h space_station.h space_station_view.h model_body.h gui_iselectable.h \ - ship_type.h object.h info_view.h model_coll_mesh_data.h + ship_type.h object.h info_view.h model_coll_mesh_data.h object_viewer_view.h diff --git a/src/body.h b/src/body.h index f46bf40..18c5c45 100644 --- a/src/body.h +++ b/src/body.h @@ -15,25 +15,24 @@ public: virtual Object::Type GetType(void) { return Object::BODY; } virtual void SetPosition(vector3d p) = 0; virtual vector3d GetPosition(void) = 0; /* Within frame. */ - vector3d GetPositionRelTo(const Frame*); virtual void Render(const Frame* camFrame) = 0; - virtual void TransformToModelCoords(const Frame* camFrame) = 0; - virtual void TransformCameraTo(void) = 0; virtual void SetFrame(Frame* f) { m_frame = f; } + /* return true if to we do collision response and apply damage. */ + virtual bool OnCollision(Body* b, Uint32 flags) { return false; } + virtual void TimeStepUpdate(const float timeStep) {} + /* Override to clear any pointers you hold to the dying body. */ + virtual void NotifyDeath(const Body* const dyingBody) {} + + vector3d GetPositionRelTo(const Frame*); Frame* GetFrame(void) { return m_frame; } void SetLabel(const char* label) { m_label = label; } std::string& GetLabel(void) { return m_label; } unsigned int GetFlags(void) { return m_flags; } - /* Return true if we should do collision response and apply damange. */ - virtual bool OnCollision(Body* b, Uint32 flags) { return false; } void SetProjectedPos(const vector3d& projectedPos) { m_projectedPos = projectedPos; } /* Only valid if IsOnScreen() is true. */ const vector3d& GetProjectedPos() const; bool IsOnscreen() const { return m_onscreen; } void SetOnscreen(const bool onscreen) { m_onscreen = onscreen; } - virtual void TimeStepUpdate(const float timeStep) {} - /* Override to clear any pointers you hold to the dying body. */ - virtual void NotifyDeath(const Body* const dyingBody) {} /* Only Space::KillBody() should call this method. */ void MarkDead(void) { m_dead = true; } diff --git a/src/l3d.h b/src/l3d.h index 0ef1e5a..16da893 100644 --- a/src/l3d.h +++ b/src/l3d.h @@ -11,6 +11,7 @@ class Player; class SectorView; class SystemView; class WorldView; +class ObjectViewerView; class SystemInfoView; class ShipCpanel; class StarSystem; @@ -76,6 +77,7 @@ public: static SectorView* sector_view; static SystemInfoView* system_info_view; static WorldView* world_view; + static ObjectViewerView* objectViewerView; static SpaceStationView* spaceStationView; static InfoView* infoView; static ShipCpanel* cpan; diff --git a/src/main.cpp b/src/main.cpp index 3a7432a..597f6b1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,6 +13,7 @@ #include "system_view.h" #include "system_info_view.h" #include "world_view.h" +#include "object_viewer_view.h" #include "star_system.h" #include "space_station.h" #include "space_station_view.h" @@ -35,6 +36,7 @@ enum L3D::MapView L3D::map_view; Player* L3D::player; View* L3D::current_view; WorldView* L3D::world_view; +ObjectViewerView* L3D::objectViewerView; SpaceStationView* L3D::spaceStationView; InfoView* L3D::infoView; SectorView* L3D::sector_view; @@ -152,7 +154,7 @@ void L3D::HandleEvents(void) { case SDL_KEYDOWN: if(event.key.keysym.sym == SDLK_q) L3D::Quit(); if(event.key.keysym.sym == SDLK_F11) SDL_WM_ToggleFullScreen(L3D::scrSurface); - + if(event.key.keysym.sym == SDLK_F12) L3D::SetView(L3D::objectViewerView); L3D::keyState[event.key.keysym.sym] = 1; L3D::onKeyPress.emit(&event.key.keysym); break; @@ -243,6 +245,7 @@ void L3D::MainLoop(void) { system_view = new SystemView(); system_info_view = new SystemInfoView(); world_view = new WorldView(); + objectViewerView = new ObjectViewerView(); spaceStationView = new SpaceStationView(); infoView = new InfoView(); diff --git a/src/model_body.cpp b/src/model_body.cpp index 8519109..ab16388 100644 --- a/src/model_body.cpp +++ b/src/model_body.cpp @@ -81,15 +81,6 @@ void ModelBody::ViewingRotation(void) { glMultMatrixd(&m[0]); } -void ModelBody::TransformCameraTo(void) { - const dReal* p = dGeomGetPosition(geoms[0]); - matrix4x4d m; - GetRotMatrix(m); - m = m.InverseOf(); - glMultMatrixd(&m[0]); - glTranslated(-p[0], -p[1], -p[2]); -} - void ModelBody::TransformToModelCoords(const Frame* camFrame) { vector3d fpos = GetPositionRelTo(camFrame); diff --git a/src/object_viewer_view.cpp b/src/object_viewer_view.cpp new file mode 100644 index 0000000..3e1e909 --- /dev/null +++ b/src/object_viewer_view.cpp @@ -0,0 +1,87 @@ +#include "object_viewer_view.h" +#include "world_view.h" +#include "l3d.h" +#include "frame.h" +#include "player.h" +#include "space.h" + +ObjectViewerView::ObjectViewerView(void) : View() { + SetTransparency(true); + viewingRotation = matrix4x4d::Identity(); + viewingDist = 1000.0f; + + m_infoLabel = new Gui::Label(""); + Add(m_infoLabel, 2, 2); +} + +#if 0 +vector3d Player::GetExternalViewTranslation(void) { + vector3d p = vector3d(0, 0, m_external_view_dist); + p = matrix4x4d::RotateXMatrix(-DEG_2_RAD*m_external_view_rotx) * p; + p = matrix3x4d::RotateYMatrix(-DEG_2_RAD*m_external_view_roty) * p; + matrix4x4d m; + GetRotMatrix(m); + p = m*p; + //printf("%f,%f,%f\n", p.x, p.y, p.z); + return p; +} + +void Player::ApplyExternalViewRotation(void) { + //glTranslatef(0, 0, m_external_view_dist); + glRotatef(-m_external_view_rotx, 1, 0, 0); + glRotatef(-m_external_view_roty, 0, 1, 0); +} +#endif + +#define DEG_2_RAD 0.0174532925 +void ObjectViewerView::Draw3D(void) { + static float rot; + rot += 0.1; + glClearColor(0, 0, 0.1, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + float fracH = L3D::GetScrHeight() / (float)L3D::GetScrWidth(); + glFrustum(-1, 1, -fracH, fracH, 1.0f, 10000.0f); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + vector3d pos = vector3d(0, 0, viewingDist); + //p = matrix4x4d::RotateXMatrix(-DEG_2_RAD*m_external_view_rotx) * p; + pos = matrix4x4d::RotateYMatrix(-DEG_2_RAD*rot) * pos; + pos = matrix4x4d::RotateXMatrix(-DEG_2_RAD*rot) * pos; + + /* + float lightPos[4]; + lightPos[0] = 0; + lightPos[1] = 0; + lightPos[2] = 0; + lightPos[3] = 0; + glLightfv(GL_LIGHT0, GL_POSITION, lightPos); + */ + + /* SBRE rendering (See ModelBody.cpp) uses this.. */ + glRotatef(-rot, 0, 1, 0); + glRotatef(-rot, 1, 0, 0); + //L3D::world_view->viewingRotation = matrix4x4d::Identity(); + glGetDoublev(GL_MODELVIEW_MATRIX, &L3D::world_view->viewingRotation[0]); + + Body* body = L3D::player->GetNavTarget(); + if(body) { + Frame cam_frame(body->GetFrame(), "", Frame::TEMP_VIEWING); + cam_frame.SetPosition(body->GetPosition()+pos); + body->Render(&cam_frame); + body->GetFrame()->RemoveChild(&cam_frame); + } +} + +void ObjectViewerView::Update(void) { + if(L3D::KeyState(SDLK_EQUALS)) viewingDist *= 0.99; + if(L3D::KeyState(SDLK_MINUS)) viewingDist *= 1.01; + viewingDist = CLAMP(viewingDist, 10, 1e10); + + char buf[128]; + snprintf(buf, sizeof(buf), "View dist: %.2f", viewingDist); + m_infoLabel->SetText(buf); +} + diff --git a/src/object_viewer_view.h b/src/object_viewer_view.h new file mode 100644 index 0000000..cad105b --- /dev/null +++ b/src/object_viewer_view.h @@ -0,0 +1,19 @@ +#pragma once +#include "libs.h" +#include "gui.h" +#include "view.h" + +class Body; + +class ObjectViewerView : public View { +public: + ObjectViewerView(void); + virtual void Update(void); + virtual void Draw3D(void); +private: + virtual void OnMouseDown(Gui::MouseButtonEvent* e) { } + matrix4x4d viewingRotation; + float viewingDist; + Gui::Label* m_infoLabel; +}; + diff --git a/src/planet.cpp b/src/planet.cpp index 22e994c..8a4b582 100644 --- a/src/planet.cpp +++ b/src/planet.cpp @@ -25,11 +25,6 @@ void Planet::SetPosition(vector3d p) { dGeomSetPosition(m_geom, p.x, p.y, p.z); } -void Planet::TransformToModelCoords(const Frame* camFrame) { - vector3d fpos = GetPositionRelTo(camFrame); - glTranslatef(m_pos[0]+fpos.x, m_pos[1]+fpos.y, m_pos[2]+fpos.z); -} - void Planet::SetRadius(double radius) { m_radius = radius; dGeomSphereSetRadius(m_geom, radius); @@ -86,10 +81,8 @@ void subdivide(vector3d& v1, vector3d& v2, vector3d& v3, vector3d& v4, int depth } void DrawLovelyRoundCube(double radius) { - const float mdiff[] = { 0.8, 0.8, 0.5, 1.0 }; - const float mambient[] = { 0.02, 0.02, 0.01, 1.0 }; - const float mdiff2[] = { 0.2, 0.2, 0.8, 0.5 }; - const float mambient2[] = { 0.01, 0.01, 0.04, 0.5 }; + const float mdiff[] = { 1.0, 0.8, 0.5, 1.0 }; + const float mambient[] = {0.1, 0.08, 0.05, 1.0 }; glMaterialfv(GL_FRONT, GL_AMBIENT, mambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mdiff); @@ -123,25 +116,199 @@ void DrawLovelyRoundCube(double radius) { //glDisable(GL_CULL_FACE); glEnable(GL_NORMALIZE); - subdivide(p1, p2, p3, p3, 3); - subdivide(p4, p3, p7, p8, 3); - subdivide(p1, p4, p8, p5, 3); - subdivide(p2, p1, p5, p6, 3); - subdivide(p3, p2, p6, p7, 3); - subdivide(p8, p7, p6, p5, 3); - - glEnable(GL_BLEND); - glMaterialfv(GL_FRONT, GL_AMBIENT, mambient2); - glMaterialfv(GL_FRONT, GL_DIFFUSE, mdiff2); - subdivide(p1, p2, p3, p4, 3); - glDisable(GL_BLEND); + subdivide(p1, p2, p3, p3, 4); + subdivide(p4, p3, p7, p8, 4); + subdivide(p1, p4, p8, p5, 4); + subdivide(p2, p1, p5, p6, 4); + subdivide(p3, p2, p6, p7, 4); + subdivide(p8, p7, p6, p5, 4); glDisable(GL_NORMALIZE); } +/* Both arguments in radians. */ +void DrawHoop(float latitude, float width, const float col[4]) { + glPushAttrib(GL_DEPTH_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); + float mambient[4]; + mambient[0] = col[0]*.1; + mambient[1] = col[1]*.1; + mambient[2] = col[2]*.1; + mambient[3] = col[3]; + glMaterialfv(GL_FRONT, GL_AMBIENT, mambient); + glMaterialfv(GL_FRONT, GL_DIFFUSE, col); + glEnable(GL_NORMALIZE); + glEnable(GL_BLEND); + + glBegin(GL_TRIANGLE_STRIP); + for(double longitude=0.0f; longitude < 2*M_PI; longitude += 0.02) { + vector3d v; + double l; + l = latitude+0.5*width; + v.x = sin(longitude)*cos(l); + v.y = sin(l); + v.z = cos(longitude)*cos(l); + v.Normalize(); + glNormal3dv(&v.x); + glVertex3dv(&v.x); + + l = latitude-0.5*width; + v.x = sin(longitude)*cos(l); + v.y = sin(l); + v.z = cos(longitude)*cos(l); + glNormal3dv(&v.x); + glVertex3dv(&v.x); + } + double l = latitude+0.5*width; + vector3d v; + v.x = 0; + v.y = sin(l); + v.z = cos(l); + v.Normalize(); + glNormal3dv(&v.x); + glVertex3dv(&v.x); + + l = latitude-0.5*width; + v.x = 0; + v.y = sin(l); + v.z = cos(l); + glNormal3dv(&v.x); + glVertex3dv(&v.x); + glEnd(); + + glDisable(GL_BLEND); + glDisable(GL_NORMALIZE); + glPopAttrib(); +} + +static void PutPolarPoint(float latitude, float longitude) { + vector3d v; + v.x = sin(longitude)*cos(latitude); + v.y = sin(latitude); + v.z = cos(longitude)*cos(latitude); + v.Normalize(); + glNormal3dv(&v.x); + glVertex3dv(&v.x); +} + +void DrawBlob(float latitude, float longitude, float a, float b, const float col[4]) { + float mambient[4]; + glPushAttrib(GL_DEPTH_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); + mambient[0] = col[0]*.1; + mambient[1] = col[1]*.1; + mambient[2] = col[2]*.1; + mambient[3] = col[3]; + glMaterialfv(GL_FRONT, GL_AMBIENT, mambient); + glMaterialfv(GL_FRONT, GL_DIFFUSE, col); + glEnable(GL_NORMALIZE); + glEnable(GL_BLEND); + + glBegin(GL_TRIANGLE_FAN); + PutPolarPoint(latitude, longitude); + for(double theta = 2*M_PI; theta > 2; theta -= 0.1) { + double _lat = latitude + a * cos(theta); + double _long = longitude + b * sin(theta); + PutPolarPoint(_lat, _long); + } + { + double _lat = latitude + a; + double _long = longitude; + PutPolarPoint(_lat, _long); + } + glEnd(); + + glDisable(GL_BLEND); + glDisable(GL_NORMALIZE); + glPopAttrib(); +} + +static void DrawRing(double inner, double outer, const float color[4]) { + glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | + GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color); + glEnable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + glDisable(GL_CULL_FACE); + + glBegin(GL_TRIANGLE_STRIP); + for(float ang = 0; ang < 2*M_PI; ang+=0.1) { + glVertex3f(inner*sin(ang), 0, inner*cos(ang)); + glVertex3f(outer*sin(ang), 0, outer*cos(ang)); + } + glVertex3f(0, 0, inner); + glVertex3f(0, 0, outer); + glEnd(); + + //gluDisk(L3D::gluQuadric, inner, outer, 40, 20); + glEnable(GL_CULL_FACE); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + glDisable(GL_BLEND); + glDisable(GL_NORMALIZE); + glPopAttrib(); +} + +static void SphereTriSubdivide(vector3d& v1, vector3d &v2, vector3d& v3, int depth) { + if(--depth > 0) { + vector3d v4 = vector3d::Normalize(v1+v2); + vector3d v5 = vector3d::Normalize(v2+v3); + vector3d v6 = vector3d::Normalize(v1+v3); + SphereTriSubdivide(v1, v4, v6, depth); + SphereTriSubdivide(v4, v2, v5, depth); + SphereTriSubdivide(v6, v4, v5, depth); + SphereTriSubdivide(v6, v5, v3, depth); + } else { + glNormal3dv(&v1.x); + glVertex3dv(&v1.x); + glNormal3dv(&v2.x); + glVertex3dv(&v2.x); + glNormal3dv(&v3.x); + glVertex3dv(&v3.x); + } +} + +/* + * yPos should be 1.0 for north pole, -1.0 for south pole. + * size in radians. + */ +static void DrawPole(double yPos, double size, const float col[4]) { + float mambient[4]; + glPushAttrib(GL_DEPTH_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); + mambient[0] = col[0]*.1; + mambient[1] = col[1]*.1; + mambient[2] = col[2]*.1; + mambient[3] = col[3]; + glMaterialfv(GL_FRONT, GL_AMBIENT, mambient); + glMaterialfv(GL_FRONT, GL_DIFFUSE, col); + glEnable(GL_NORMALIZE); + glEnable(GL_BLEND); + + const bool southPole = yPos < 0; + + vector3d center(0, yPos, 0); + glBegin(GL_TRIANGLES); + for(float ang = 2*M_PI; ang > 0; ang -= 0.1) { + vector3d v1(sin(ang), yPos, cos(ang)); + vector3d v2(sin(ang+0.1), yPos, cos(ang+0.1)); + v1.Normalize(); + v2.Normalize(); + if(southPole) + SphereTriSubdivide(center, v2, v1, 4); + else + SphereTriSubdivide(center, v1, v2, 4); + } + glEnd(); + + glDisable(GL_BLEND); + glDisable(GL_NORMALIZE); + glPopAttrib(); +} + void Planet::Render(const Frame* a_camFrame) { glPushMatrix(); - glDisable(GL_DEPTH_TEST); double rad = m_radius; vector3d fpos = GetPositionRelTo(a_camFrame); @@ -149,7 +316,7 @@ void Planet::Render(const Frame* a_camFrame) { double apparent_size = rad / fpos.Length(); double len = fpos.Length(); - while(len > 10000.0f) { + while(len > 5000.0f) { rad *= 0.25; fpos = 0.25*fpos; len *= 0.25; @@ -168,9 +335,30 @@ void Planet::Render(const Frame* a_camFrame) { } else { glScalef(rad, rad, rad); DrawLovelyRoundCube(1.0f); - //gluSphere(L3D::gluQuadric, rad, 100, 100); + const float col1[] = { 1, 1, 0, .7 }; + const float col2[] = { 1, .2, 0, .7 }; + const float col3[] = { .3, 1, 0, .7 }; + const float col4[] = { 1, .6, 0, .7 }; + const float col5[] = { 0, 0, 0.8, .7 }; + const float white[] = { 1, 1, 1, 1 }; + DrawHoop(M_PI/10.0, M_PI/20.0, col1); + DrawHoop(M_PI/12.0, M_PI/20.0, col2); + DrawHoop(0, M_PI/20.0, col2); + DrawHoop(-M_PI/10.0, M_PI/20.0, col3); + DrawHoop(M_PI/2 - M_PI/10.0, M_PI/20.0, col4); + DrawBlob(.2, -0.3, 0.05, 0.2, col5); + DrawBlob(.3, M_PI/2, 0.05, 0.2, col5); + DrawBlob(-.1, -M_PI/2, 0.05, 0.2, col5); + DrawPole(1.0, 0.1, white); + DrawPole(-1.0, 0.1, white); + DrawRing(1.5, 1.8, col1); + DrawRing(1.5, 1.8, col1); + DrawRing(1.9, 2.0, col1); + DrawRing(2.04, 2.3, col1); + //DrawBlob(1.0, 0, 0.02, 0.5, col5); + //DrawBlob(-1.0, 0, 0.02, 05, col5); + glClear(GL_DEPTH_BUFFER_BIT); } - glEnable(GL_DEPTH_TEST); glPopMatrix(); } diff --git a/src/planet.h b/src/planet.h index 1042927..43b28cb 100644 --- a/src/planet.h +++ b/src/planet.h @@ -12,8 +12,6 @@ public: void SetRadius(double radius); double GetRadius(void) { return m_radius; } virtual void Render(const Frame* camFrame); - virtual void TransformToModelCoords(const Frame* camFrame); - virtual void TransformCameraTo(void) {}; virtual void SetFrame(Frame* f); virtual bool OnCollision(Body* b, Uint32 flags) { return true; } private: diff --git a/src/star.cpp b/src/star.cpp index 87fbca2..131fff6 100644 --- a/src/star.cpp +++ b/src/star.cpp @@ -16,11 +16,6 @@ void Star::SetPosition(vector3d p) { m_pos = p; } -void Star::TransformToModelCoords(const Frame* camFrame) { - vector3d fpos = GetPositionRelTo(camFrame); - glTranslatef(m_pos[0]+fpos.x, m_pos[1]+fpos.y, m_pos[2]+fpos.z); -} - void Star::Render(const Frame* a_camFrame) { glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); @@ -39,7 +34,6 @@ void Star::Render(const Frame* a_camFrame) { glTranslatef(fpos.x, fpos.y, fpos.z); - //TransformToModelCoords(a_camFrame); glColor3fv(StarSystem::starColors[m_subtype]); gluSphere(L3D::gluQuadric, rad, 100, 100); glPopMatrix(); diff --git a/src/star.h b/src/star.h index 59f5108..4513ef9 100644 --- a/src/star.h +++ b/src/star.h @@ -13,8 +13,6 @@ public: void SetRadius(double radius) { m_radius = radius; } double GetRadius(void) { return m_radius; } virtual void Render(const Frame* camFrame); - virtual void TransformToModelCoords(const Frame* camFrame); - virtual void TransformCameraTo(void) { }; private: StarSystem::SBody::SubType m_subtype;