[Add] Uhm, apparently the new project stuff wasn't added. My bad.

This commit is contained in:
Rtch90 2017-11-12 18:27:48 +00:00
parent 41950a3099
commit caba05d699
151 changed files with 9589 additions and 0 deletions

0
COMPILING Normal file
View File

46
Makefile.am Normal file
View File

@ -0,0 +1,46 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = src/
EXTRA_DIST = icons/button_f10.png \
icons/button_f7.png \
icons/button_f8.png \
icons/button_f9.png \
icons/cam_external.png \
icons/cam_front.png \
icons/cam_rear.png \
icons/cpanel.png \
icons/cpan_f2_map.png \
icons/cpan_f2_normal.png \
icons/object_brown_dwarf.png \
icons/object_planet_dwarf.png \
icons/object_planet_large_gas_giant.png \
icons/object_planet_medium_gas_giant.png \
icons/object_planet_small_gas_giant.png \
icons/object_planet_small.png \
icons/object_planet_life.png \
icons/object_star_a.png \
icons/object_star_b.png \
icons/object_star_f.png \
icons/object_star_g.png \
icons/object_star_k.png \
icons/object_star_m.png \
icons/object_star_o.png \
icons/sectorview_f6_systeminfo.png \
icons/timeaccel0_on.png \
icons/timeaccel0.png \
icons/timeaccel1_on.png \
icons/timeaccel1.png \
icons/timeaccel2_on.png \
icons/timeaccel2.png \
icons/timeaccel3_on.png \
icons/timeaccel3.png \
icons/timeaccel4_on.png \
icons/timeaccel4.png \
icons/zoom_in_f7.png \
icons/zoom_out_f8.png \
icons/hyperspace_f8.png \
icons/comms_f4.png \
icons/sysview_accel_f1_on.png icons/sysview_accel_f1.png icons/sysview_accel_f2_on.png icons/sysview_accel_f2.png icons/sysview_accel_f3_on.png icons/sysview_accel_f3.png icons/sysview_accel_r1_on.png icons/sysview_accel_r1.png icons/sysview_accel_r2_on.png icons/sysview_accel_r2.png icons/sysview_accel_r3_on.png icons/sysview_accel_r3.png \
config.ini

4
bootstrap Executable file
View File

@ -0,0 +1,4 @@
#! /bin/sh
autoreconf -fvi

6
config.ini Normal file
View File

@ -0,0 +1,6 @@
ScrWidth=800
ScrHeight=600
# 16 or 32.
ScrDepth=16
StartFullscreen=0

36
configure.ac Normal file
View File

@ -0,0 +1,36 @@
# Process this file with autoconf to create configure.
AC_PREREQ(2.59)
AC_INIT([Lephisto3D], [0.0.1], [allanis.saracraft.studios@gmail.com])
#AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([1.9 foreign])
AC_PROG_CC
AC_PROG_CXX
AC_C_CONST
AC_PROG_RANLIB
#AC_PROG_LIBTOOL
#AM_PATH_LIB3DS([1.2.0])
#CFLAGS="$CFLAGS $LIB3DS_CFLAGS"
#LIBS="$LIBS $LIB3DS_LIBS"
CFLAGS="-g -O2 -Wall"
CFLAGS="$CFLAGS `pkg-config --cflags sigc++-2.0`"
LIBS="$LIBS `pkg-config --libs sigc++-2.0` -lGL -lGLU"
CFLAGS="$CFLAGS `pkg-config --cflags freetype2`"
LIBS="$LIBS `pkg-config --libs freetype2`"
CFLAGS="$CFLAGS `ode-config --cflags`"
LIBS="$LIBS `ode-config --libs`"
PKG_CHECK_MODULES(SDL, sdl)
CFLAGS="$CFLAGS $SDL_CFLAGS"
LIBS="$LIBS $SDL_LIBS -lSDL_image"
CXXFLAGS="$CFLAGS"
AC_CONFIG_FILES([Makefile src/Makefile src/sbre/Makefile])
AC_OUTPUT

BIN
icons/button_f10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

BIN
icons/button_f7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

BIN
icons/button_f8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

BIN
icons/button_f9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

BIN
icons/cam_external.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

BIN
icons/cam_front.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

BIN
icons/cam_rear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

BIN
icons/comms_f4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

BIN
icons/cpan_f2_map.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

BIN
icons/cpan_f2_normal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

BIN
icons/cpanel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
icons/hyperspace_f8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
icons/object_star_a.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
icons/object_star_b.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
icons/object_star_f.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
icons/object_star_g.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
icons/object_star_k.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
icons/object_star_m.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 798 B

BIN
icons/object_star_o.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

BIN
icons/sysview_accel_f1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

BIN
icons/sysview_accel_f2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 B

BIN
icons/sysview_accel_f3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

BIN
icons/sysview_accel_r1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

BIN
icons/sysview_accel_r2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

BIN
icons/sysview_accel_r3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

BIN
icons/timeaccel0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

BIN
icons/timeaccel0_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

BIN
icons/timeaccel1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

BIN
icons/timeaccel1_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

BIN
icons/timeaccel2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

BIN
icons/timeaccel2_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

BIN
icons/timeaccel3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

BIN
icons/timeaccel3_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

BIN
icons/timeaccel4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

BIN
icons/timeaccel4_on.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

BIN
icons/zoom_in_f7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

BIN
icons/zoom_out_f8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

19
src/Makefile.am Normal file
View File

@ -0,0 +1,19 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = sbre/
bin_PROGRAMS = Lephisto3D
Lephisto3D_SOURCES = main.cpp gui_button.cpp gui.cpp gui_fixed.cpp gui_screen.cpp gui_label.cpp glfreetype.cpp \
objimport.cpp body.cpp space.cpp ship.cpp player.cpp gui_toggle_button.cpp gui_radio_button.cpp \
gui_radio_group.cpp rigid_body.cpp planet.cpp star.cpp frame.cpp gui_image_button.cpp gui_image.cpp \
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 static_rigid_body.cpp ship_type.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 \
gui.h gui_image_button.h gui_image.h gui_image_radio_button.h gui_label.h gui_multi_state_image_button.h gui_radio_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 rigid_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 static_rigid_body.h gui_iselectable.h \
ship_type.h object.h

14
src/body.cpp Normal file
View File

@ -0,0 +1,14 @@
#include "libs.h"
#include "body.h"
#include "frame.h"
Body::Body(void) {
m_frame = 0;
m_flags = 0;
}
/* f == NULL, then absolute position within system. */
vector3d Body::GetPositionRelTo(const Frame* relTo) {
return m_frame->GetPosRelativeToOtherFrame(relTo) + GetPosition();
}

40
src/body.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include <string>
#include "vector3.h"
#include "matrix4x4.h"
#include "object.h"
class Frame;
class ObjMesh;
class Body: public Object {
public:
Body(void);
virtual ~Body(void) { };
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; }
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 apply damage. */
virtual bool OnCollision(Body* b) { return false; }
enum { FLAG_CAN_MOVE_FRAME = 1 };
protected:
unsigned int m_flags;
private:
/* Frame of reference. */
Frame* m_frame;
std::string m_label;
};

77
src/date.cpp Normal file
View File

@ -0,0 +1,77 @@
#include "date.h"
#include <stdlib.h>
#include <math.h>
#include "libs.h"
/* Urgh... */
static const char *i_am_a_little_teapot[365] =
{ "Jan 1","Jan 2","Jan 3","Jan 4","Jan 5","Jan 6","Jan 7",
"Jan 8","Jan 9","Jan 10","Jan 11","Jan 12","Jan 13","Jan 14",
"Jan 15","Jan 16","Jan 17","Jan 18","Jan 19","Jan 20","Jan 21",
"Jan 22","Jan 23","Jan 24","Jan 25","Jan 26","Jan 27","Jan 28",
"Jan 29","Jan 30","Jan 31","Feb 1","Feb 2","Feb 3","Feb 4",
"Feb 5","Feb 6","Feb 7","Feb 8","Feb 9","Feb 10","Feb 11","Feb 12",
"Feb 13","Feb 14","Feb 15","Feb 16","Feb 17","Feb 18","Feb 19",
"Feb 20","Feb 21","Feb 22","Feb 23","Feb 24","Feb 25","Feb 26",
"Feb 27","Feb 28","Mar 1","Mar 2","Mar 3","Mar 4","Mar 5","Mar 6",
"Mar 7","Mar 8","Mar 9","Mar 10","Mar 11","Mar 12","Mar 13",
"Mar 14","Mar 15","Mar 16","Mar 17","Mar 18","Mar 19","Mar 20",
"Mar 21","Mar 22","Mar 23","Mar 24","Mar 25","Mar 26","Mar 27",
"Mar 28","Mar 29","Mar 30","Mar 31","Apr 1","Apr 2","Apr 3",
"Apr 4","Apr 5","Apr 6","Apr 7","Apr 8","Apr 9","Apr 10","Apr 11",
"Apr 12","Apr 13","Apr 14","Apr 15","Apr 16","Apr 17","Apr 18",
"Apr 19","Apr 20","Apr 21","Apr 22","Apr 23","Apr 24","Apr 25",
"Apr 26","Apr 27","Apr 28","Apr 29","Apr 30","May 1","May 2",
"May 3","May 4","May 5","May 6","May 7","May 8","May 9","May 10",
"May 11","May 12","May 13","May 14","May 15","May 16","May 17",
"May 18","May 19","May 20","May 21","May 22","May 23","May 24",
"May 25","May 26","May 27","May 28","May 29","May 30","May 31",
"Jun 1","Jun 2","Jun 3","Jun 4","Jun 5","Jun 6","Jun 7","Jun 8",
"Jun 9","Jun 10","Jun 11","Jun 12","Jun 13","Jun 14","Jun 15",
"Jun 16","Jun 17","Jun 18","Jun 19","Jun 20","Jun 21","Jun 22",
"Jun 23","Jun 24","Jun 25","Jun 26","Jun 27","Jun 28","Jun 29",
"Jun 30","Jul 1","Jul 2","Jul 3","Jul 4","Jul 5","Jul 6","Jul 7",
"Jul 8","Jul 9","Jul 10","Jul 11","Jul 12","Jul 13","Jul 14",
"Jul 15","Jul 16","Jul 17","Jul 18","Jul 19","Jul 20","Jul 21",
"Jul 22","Jul 23","Jul 24","Jul 25","Jul 26","Jul 27","Jul 28",
"Jul 29","Jul 30","Jul 31","Aug 1","Aug 2","Aug 3","Aug 4","Aug 5",
"Aug 6","Aug 7","Aug 8","Aug 9","Aug 10","Aug 11","Aug 12",
"Aug 13","Aug 14","Aug 15","Aug 16","Aug 17","Aug 18","Aug 19",
"Aug 20","Aug 21","Aug 22","Aug 23","Aug 24","Aug 25","Aug 26",
"Aug 27","Aug 28","Aug 29","Aug 30","Aug 31","Sep 1","Sep 2",
"Sep 3","Sep 4","Sep 5","Sep 6","Sep 7","Sep 8","Sep 9","Sep 10",
"Sep 11","Sep 12","Sep 13","Sep 14","Sep 15","Sep 16","Sep 17",
"Sep 18","Sep 19","Sep 20","Sep 21","Sep 22","Sep 23","Sep 24",
"Sep 25","Sep 26","Sep 27","Sep 28","Sep 29","Sep 30","Oct 1",
"Oct 2","Oct 3","Oct 4","Oct 5","Oct 6","Oct 7","Oct 8","Oct 9",
"Oct 10","Oct 11","Oct 12","Oct 13","Oct 14","Oct 15","Oct 16",
"Oct 17","Oct 18","Oct 19","Oct 20","Oct 21","Oct 22","Oct 23",
"Oct 24","Oct 25","Oct 26","Oct 27","Oct 28","Oct 29","Oct 30",
"Oct 31","Nov 1","Nov 2","Nov 3","Nov 4","Nov 5","Nov 6","Nov 7",
"Nov 8","Nov 9","Nov 10","Nov 11","Nov 12","Nov 13","Nov 14",
"Nov 15","Nov 16","Nov 17","Nov 18","Nov 19","Nov 20","Nov 21",
"Nov 22","Nov 23","Nov 24","Nov 25","Nov 26","Nov 27","Nov 28",
"Nov 29","Nov 30","Dec 1","Dec 2","Dec 3","Dec 4","Dec 5","Dec 6",
"Dec 7","Dec 8","Dec 9","Dec 10","Dec 11","Dec 12","Dec 13",
"Dec 14","Dec 15","Dec 16","Dec 17","Dec 18","Dec 19","Dec 20",
"Dec 21","Dec 22","Dec 23","Dec 24","Dec 25","Dec 26","Dec 27",
"Dec 28","Dec 29","Dec 30","Dec 31"
};
int mod(int a, int b) {
int r = a%b;
return r >= 0 ? r : r*b;
}
std::string date_format(double t) {
int year = floor(t/(60*60*24*365)); year += 3200;
int day = floor(t/(60*60*24)); day = mod(day, 365);
int hour = floor(t/(60*60)); hour = mod(hour, 24);
int min = floor(t/60); min = mod(min, 60);
int sec = mod(t, 60);
char buf[128];
snprintf(buf, sizeof(buf), "%02d:%02d:%02d %s %d", hour, min, sec,
i_am_a_little_teapot[day], year);
return buf;
}

5
src/date.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <string>
std::string date_format(double time);

55
src/frame.cpp Normal file
View File

@ -0,0 +1,55 @@
#include "frame.h"
#include "space.h"
Frame::Frame(void) {
Init(NULL, "", 0);
}
Frame::Frame(Frame* parent, const char* label) {
Init(parent, label, 0);
}
Frame::Frame(Frame* parent, const char* label, unsigned int flags) {
Init(parent, label, flags);
}
void Frame::RemoveChild(Frame* f) {
m_children.remove(f);
}
void Frame::Init(Frame* parent, const char* label, unsigned int flags) {
m_parent = parent;
m_flags = flags;
m_radius = 0;
m_dSpaceID = dHashSpaceCreate(0);
if(m_parent) {
m_parent->m_children.push_back(this);
}
if(label) m_label = label;
}
Frame::~Frame(void) {
dSpaceDestroy(m_dSpaceID);
for(std::list<Frame*>::iterator i = m_children.begin(); i != m_children.end(); ++i) delete *i;
}
vector3d Frame::GetFramePosRelativeToOther(const Frame* frame, const Frame* relTo) {
vector3d pos = vector3d(0,0,0);
const Frame* f = frame;
const Frame* root = Space::GetRootFrame();
while((f!=root) && (relTo !=f)) {
pos += f->m_pos;
f = f->m_parent;
}
/* Now pos is relative to root, or to desired frame. */
while(relTo != f) {
pos -= relTo->m_pos;
relTo = relTo->m_parent;
}
return pos;
}

47
src/frame.h Normal file
View File

@ -0,0 +1,47 @@
#pragma once
#include <string>
#include <list>
#include "libs.h"
/* Frame of reference. */
class Frame {
public:
Frame(void);
Frame(Frame* parent, const char* label);
Frame(Frame* parent, const char* label, unsigned int flags);
~Frame(void);
const char* GetLabel(void) { return m_label.c_str(); }
void SetLabel(const char* label) { m_label = label; }
void SetPosition(const vector3d &pos) { m_pos = pos; }
void SetRadius(double radius) { m_radius = radius; }
void RemoveChild(Frame* f);
void AddGeom(dGeomID g) { dSpaceAdd(m_dSpaceID, g); }
void RemoveGeom(dGeomID g) { dSpaceRemove(m_dSpaceID, g); }
dSpaceID GetSpaceID(void) { return m_dSpaceID; }
static vector3d GetFramePosRelativeToOther(const Frame* frame, const Frame* relTo);
vector3d GetPosRelativeToOtherFrame(const Frame* relTo) const {
return GetFramePosRelativeToOther(this, relTo);
}
bool IsLocalPosInFrame(const vector3d& pos) {
return (pos.Length() < m_radius);
}
/* If parent is null then frame position is absolute. */
Frame* m_parent;
std::list<Frame*> m_children;
enum { TEMP_VIEWING=1 };
private:
void Init(Frame* parent, const char* label, unsigned int flags);
vector3d m_pos;
std::string m_label;
double m_radius;
int m_flags;
dSpaceID m_dSpaceID;
};

View File

@ -0,0 +1,51 @@
#include "l3d.h"
#include "generic_system_view.h"
#include "sector_view.h"
GenericSystemView::GenericSystemView(void) : View() {
px = py = pidx = 0xdeadbeef;
m_scannerLayout = new Gui::Fixed(140, 2, 360, 60);
m_scannerLayout->SetTransparency(true);
m_systemName = new Gui::Label("");
m_systemName->SetColor(1, 1, 0);
m_scannerLayout->Add(m_systemName, 40, 44);
m_distance = new Gui::Label("");
m_distance->SetColor(1, 0, 0);
m_scannerLayout->Add(m_distance, 150, 44);
m_starType = new Gui::Label("");
m_starType->SetColor(1, 0, 1);
m_scannerLayout->Add(m_starType, 22, 26);
m_shortDesc = new Gui::Label("");
m_shortDesc->SetColor(1, 0, 1);
m_scannerLayout->Add(m_shortDesc, 5, 8);
}
void GenericSystemView::Draw3D(void) {
StarSystem* s = L3D::GetSelectedSystem();
if(s && !s->IsSystem(px, py, pidx)) {
s->GetPos(&px, &py, &pidx);
m_systemName->SetText(s->rootBody->name);
m_distance->SetText("Dist. XX.XX light years.");
m_starType->SetText(s->rootBody->GetAstroDescription());
m_shortDesc->SetText("Short description of system");
onSelectedSystemChanged.emit(s);
}
}
void GenericSystemView::ShowAll(void) {
View::ShowAll();
if(m_scannerLayout) m_scannerLayout->ShowAll();
}
void GenericSystemView::HideAll(void) {
View::HideAll();
if(m_scannerLayout) m_scannerLayout->HideAll();
}

25
src/generic_system_view.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include "libs.h"
#include "gui.h"
#include "view.h"
#include "star_system.h"
class SystemInfoScannerText;
class GenericSystemView: public View {
public:
GenericSystemView(void);
virtual void Draw3D(void);
virtual void ShowAll(void);
virtual void HideAll(void);
sigc::signal<void,StarSystem*> onSelectedSystemChanged;
private:
Gui::Fixed* m_scannerLayout;
Gui::Label* m_systemName;
Gui::Label* m_distance;
Gui::Label* m_starType;
Gui::Label* m_shortDesc;
int px, py, pidx;
};

374
src/glfreetype.cpp Normal file
View File

@ -0,0 +1,374 @@
#include <SDL_opengl.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <assert.h>
#include <map>
#include <ft2build.h>
#include "glfreetype.h"
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_OUTLINE_H
#ifdef _WIN32
typedef GLvoid(APIENTRY* _GLUfuncptr)(void);
#endif
FT_Library library;
#include <vector>
static GLUtesselator* tobj;
static inline double fac(int n) {
double r = 1.0;
for(int i = 2; i < n; i++) {
r *= (double)i;
}
return r;
}
static inline double binomial_coeff(int n, int m) {
return fac(n)/(fac(m)*(fac(n-m)));
}
static void eval_bezier(GLdouble* out, double t, int n_points, double* points) {
std::vector<double> c(n_points);
for(int i = 0; i < n_points; i++) {
c[i] = pow(1.0f-t, n_points-(i+1)) * pow(t, i) *
binomial_coeff(n_points-1, i);
}
out[0] = out[1] = out[2] = 0;
for(int i = 0; i < n_points; i++) {
out[0] += points[3*i] * c[i];
out[1] += points[3*i+1] * c[i];
out[2] += points[3*i+2] * c[i];
}
}
#define DIV 2048.0f
bool GenContourPoints(int a_char, FT_Outline* a_outline, const int a_contour,
int a_bezierIters, std::vector<double>* ao_points) {
#define push_point(__p) { \
ao_points->push_back((__p)[0]); \
ao_points->push_back((__p)[1]); \
ao_points->push_back((__p)[2]); \
}
int cont = (a_contour-1 < 0 ? 0 : 1 + a_outline->contours[a_contour-1]);
double point_buf[256][3];
char point_type[256];
int pos = 0;
for(; cont <= a_outline->contours[a_contour]; cont++, pos++) {
point_type[pos] = a_outline->tags[cont];
point_buf[pos][0] = a_outline->points[cont].x/DIV;
point_buf[pos][1] = a_outline->points[cont].y/DIV;
point_buf[pos][2] = 0;
}
if(!point_type[pos-1]) {
/*
* Need to duplicate first vertex if last
* section is a bezier.
*/
point_type[pos] = 1;
point_buf[pos][0] = point_buf[0][0];
point_buf[pos][1] = point_buf[0][1];
point_buf[pos][2] = 0;
pos++;
}
int start = -1;
for(int k = 0; k < pos; k++) {
if(!(point_type[k] & 1)) continue;
if(start == -1) { start = k; continue; }
int len = 1+k-start;
/* Trace segment. */
if(len == 2) {
/* Staight line. */
push_point(point_buf[k-1]);
push_point(point_buf[k]);
} else {
/* Bezier. */
double b_in[3][3];
double v[3];
/*
* Truetype is all quadratic bezier,
* using average points between
* 'control points' as end points.
*/
/* First bezier. */
b_in[0][0] = point_buf[start][0];
b_in[0][1] = point_buf[start][1];
b_in[0][2] = 0;
b_in[1][0] = point_buf[start+1][0];
b_in[1][1] = point_buf[start+1][1];
b_in[1][2] = 0;
if(len > 3) {
b_in[2][0] = 0.5 * (point_buf[start+1][0] + point_buf[start+2][0]);
b_in[2][1] = 0.5 * (point_buf[start+1][1] + point_buf[start+2][1]);
b_in[2][2] = 0;
} else {
b_in[2][0] = point_buf[start+2][0];
b_in[2][1] = point_buf[start+2][1];
b_in[2][2] = 0;
}
for(int l = 0; l <= a_bezierIters; l++) {
double t = (1.0/a_bezierIters)*l;
eval_bezier(v, t, 3, &b_in[0][0]);
v[2] = 0.0;
push_point(v);
}
/* Middle beziers. */
if(len > 4) {
for(int _p = 1; _p < len-3; _p++) {
b_in[0][0] = 0.5*(point_buf[start+_p][0]+point_buf[start+_p+1][0]);
b_in[0][1] = 0.5*(point_buf[start+_p][1]+point_buf[start+_p+1][1]);
b_in[0][2] = 0;
b_in[1][0] = point_buf[start+_p+1][0];
b_in[1][1] = point_buf[start+_p+1][1];
b_in[1][2] = 0;
b_in[2][0] = 0.5*(point_buf[start+_p+1][0] + point_buf[start+_p+2][0]);
b_in[2][1] = 0.5*(point_buf[start+_p+1][1] + point_buf[start+_p+2][1]);
b_in[2][2] = 0;
for(int l = 0; l <= a_bezierIters; l++) {
double t = (1.0/a_bezierIters)*l;
eval_bezier(v, t, 3, &b_in[0][0]);
v[2] = 0.0;
push_point(v);
}
}
}
/* End. */
if(len > 3) {
const int _p = start+len-3;
b_in[0][0] = 0.5 * (point_buf[_p][0] + point_buf[_p+1][0]);
b_in[0][1] = 0.5 * (point_buf[_p][1] + point_buf[_p+1][1]);
b_in[0][2] = 0;
b_in[1][0] = point_buf[_p+1][0];
b_in[1][1] = point_buf[_p+1][1];
b_in[1][2] = 0;
b_in[2][0] = point_buf[_p+2][0];
b_in[2][1] = point_buf[_p+2][1];
b_in[2][2] = 0;
for(int l = 0; l <= a_bezierIters; l++) {
double t = (1.0/a_bezierIters)*l;
eval_bezier(v, t, 3, &b_in[0][0]);
v[2] = 0.0;
push_point(v);
}
}
}
start = k;
}
return true;
}
#ifndef CALLBACK
# ifdef WIN32
# define CALLBACK __attribute__ ((__stdcall__))
# else
# define CALLBACK
# endif
#endif /* CALLBACK */
struct TessData {
std::vector<double>* pts; /* Inputs, added by combine. */
int numvtx;
std::vector<Uint16> index; /* Output index list. */
GLenum lasttype;
int state; /* 0, no vertices, 1, 1 vertex, 2, 2 or more. 0x4 => clockwise. */
Uint16 vtx[2];
};
static Uint16 g_index[65536];
void CALLBACK beginCallback(GLenum which, GLvoid* poly_data) {
TessData* pData = (TessData*)poly_data;
pData->lasttype = which;
pData->state = 0;
}
void CALLBACK errorCallback(GLenum errorCode) {
const GLubyte* estr;
estr = gluErrorString(errorCode);
fprintf(stderr, "Tesserlation Error: %s\n", estr);
}
void CALLBACK endCallback(void) {
}
void CALLBACK vertexCallback(GLvoid* vertex, GLvoid* poly_data) {
TessData* pData = (TessData*)poly_data;
Uint16 index = *(Uint16*)vertex;
switch(pData->lasttype) {
case GL_TRIANGLES:
pData->index.push_back(index);
break;
case GL_TRIANGLE_STRIP:
if((pData->state & 3) < 2)
pData->vtx[pData->state++] = index;
else {
pData->index.push_back(index);
if(pData->state & 0x4) {
pData->index.push_back(pData->vtx[1]);
pData->index.push_back(pData->vtx[0]);
} else {
pData->index.push_back(pData->vtx[0]);
pData->index.push_back(pData->vtx[1]);
}
pData->vtx[0] = pData->vtx[1];
pData->vtx[1] = index;
pData->state ^= 0x4;
}
break;
case GL_TRIANGLE_FAN:
if((pData->state & 3) < 2)
pData->vtx[pData->state++] = index;
else {
pData->index.push_back(index);
pData->index.push_back(pData->vtx[0]);
pData->index.push_back(pData->vtx[1]);
pData->vtx[1] = index;
}
}
}
void CALLBACK combineCallback(GLdouble coords[3],
GLdouble* vertex_data[4],
GLfloat weight[4], void** dataOut, void* poly_data) {
TessData* pData = (TessData*)poly_data;
pData->pts->push_back(coords[0]);
pData->pts->push_back(coords[1]);
pData->pts->push_back(coords[2]);
*dataOut = (void*)&g_index[pData->numvtx++];
}
#define BEZIER_STEPS 2
void FontFace::RenderGlyph(int chr) {
glEnableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glfglyph_t* glyph = &m_glyphs[chr];
glVertexPointer(3, GL_FLOAT, 3*sizeof(float), glyph->varray);
glDrawElements(GL_TRIANGLES, glyph->numidx, GL_UNSIGNED_SHORT, glyph->iarray);
}
void FontFace::RenderString(const char* str) {
glPushMatrix();
for(unsigned int i = 0; i < strlen(str); i++) {
if(str[i] == '\n') {
glPopMatrix();
glTranslatef(0, -m_height, 0);
glPushMatrix();
} else {
glfglyph_t* glyph = &m_glyphs[str[i]];
if(glyph->numidx) RenderGlyph(str[i]);
glTranslatef(glyph->advx, 0, 0);
}
}
glPopMatrix();
}
FontFace::FontFace(const char* filename_ttf) {
FT_Face face;
if(0 != FT_New_Face(library, filename_ttf, 0, &face)) {
fprintf(stderr, "Error: Couldn't load '%s'\n", filename_ttf);
} else {
FT_Set_Char_Size(face, 50*64, 0, 100, 0);
for(int chr = 32; chr < 127; chr++) {
if(0 != FT_Load_Char(face, chr, FT_LOAD_NO_SCALE)) {
printf("Couldn't load glyph\n");
continue;
}
assert(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE);
FT_Outline* outline = &face->glyph->outline;
std::vector<double> temppts;
std::vector<Uint16> indices;
std::vector<double> pts;
int nv = 0;
TessData tessdata;
tessdata.pts = &pts;
gluTessNormal(tobj, 0, 0, 1);
gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
gluTessBeginPolygon(tobj, &tessdata);
for(int contour = 0; contour < outline->n_contours; contour++) {
gluTessBeginContour(tobj);
temppts.clear();
GenContourPoints(chr, outline, contour, BEZIER_STEPS, &temppts);
for(size_t i = 0; i < temppts.size(); i++) pts.push_back(temppts[i]);
for(size_t i = 0; i < temppts.size(); i+=4, nv++)
gluTessVertex(tobj, &pts[nv*3], &g_index[nv]);
gluTessEndContour(tobj);
}
tessdata.numvtx = nv;
gluTessEndPolygon(tobj);
glfglyph_t _face;
nv = tessdata.numvtx;
_face.varray = (float*)malloc(nv*3*sizeof(float));
for(int i = 0; i < nv*3; i++) _face.varray[i] = (float)pts[i];
_face.numidx = (int)tessdata.index.size();
_face.iarray = (Uint16*)malloc(_face.numidx*sizeof(Uint16));
for(int i = 0; i < _face.numidx; i++) _face.iarray[i] = tessdata.index[i];
_face.advx = face->glyph->linearHoriAdvance/(float)(1<<16)/72.0f;
_face.advy = face->glyph->linearVertAdvance/(float)(1<<16)/72.0f;
//printf(%f,%f\n", _face.advx, _face.advy);
m_glyphs[chr] = _face;
}
m_height = m_glyphs['M'].advy;
m_width = m_glyphs['M'].advx;
}
}
void GLFTInit(void) {
if(0 != FT_Init_FreeType(&library)) {
printf("Couldn't init freetype library.\n");
exit(0);
}
tobj = gluNewTess();
gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (_GLUfuncptr) vertexCallback);
gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (_GLUfuncptr) beginCallback);
gluTessCallback(tobj, GLU_TESS_END, (_GLUfuncptr) endCallback);
gluTessCallback(tobj, GLU_TESS_ERROR, (_GLUfuncptr) errorCallback);
gluTessCallback(tobj, GLU_TESS_COMBINE_DATA, (_GLUfuncptr) combineCallback);
for(Uint16 i = 0; i < 65535; i++) g_index[i] = i;
}

28
src/glfreetype.h Normal file
View File

@ -0,0 +1,28 @@
#pragma once
#include <map>
#include <SDL_stdinc.h>
class FontFace {
public:
FontFace(const char* filename_ttf);
void RenderGlyph(int chr);
void RenderString(const char* str);
/* Of Ms. */
float GetHeight(void) { return m_height; }
float GetWidth(void) { return m_width; }
private:
float m_height;
float m_width;
struct glfglyph_t {
float* varray;
Uint16* iarray;
int numidx;
float advx, advy;
};
std::map<int, glfglyph_t> m_glyphs;
};
void GLFTInit(void);

46
src/gui.cpp Normal file
View File

@ -0,0 +1,46 @@
#include "libs.h"
#include "gui.h"
namespace Gui {
namespace RawEvents {
sigc::signal<void, SDL_MouseButtonEvent*> onMouseDown;
sigc::signal<void, SDL_MouseButtonEvent*> onMouseUp;
sigc::signal<void, SDL_KeyboardEvent*> onKeyDown;
sigc::signal<void, SDL_KeyboardEvent*> onKeyUp;
}
namespace Color {
const float bg[] = { .25, .37, .63 };
const float bgShadow[] = { .08, .12, .21 };
}
void HandleSDLEvent(SDL_Event* event) {
switch(event->type) {
case SDL_MOUSEBUTTONDOWN:
Screen::OnClick(&event->button);
RawEvents::onMouseDown.emit(&event->button);
break;
case SDL_MOUSEBUTTONUP:
Screen::OnClick(&event->button);
RawEvents::onMouseUp.emit(&event->button);
break;
case SDL_KEYDOWN:
Screen::OnKeyDown(&event->key.keysym);
RawEvents::onKeyDown.emit(&event->key);
break;
case SDL_KEYUP:
RawEvents::onKeyUp.emit(&event->key);
break;
}
}
void Draw(void) {
Screen::Draw();
}
void Init(int screen_width, int screen_height, int ui_width, int ui_height) {
Screen::Init(screen_width, screen_height, ui_width, ui_height);
}
}

102
src/gui_button.cpp Normal file
View File

@ -0,0 +1,102 @@
#include "libs.h"
#include "gui.h"
#define BUTTON_SIZE 16
namespace Gui {
Button::Button(void) {
m_isPressed = false;
m_eventMask = EVENT_MOUSEDOWN | EVENT_MOUSEUP;
SetSize(BUTTON_SIZE, BUTTON_SIZE);
}
void Button::OnMouseDown(MouseButtonEvent* e) {
if(e->button == 1) {
m_isPressed = true;
onPress.emit();
/* Wait for mouse release, regardless of where on screen. */
_m_release = RawEvents::onMouseUp.connect(sigc::mem_fun(this, &Button::OnRawMouseUp));
}
}
void Button::OnMouseUp(MouseButtonEvent* e) {
if((e->button == 1) && m_isPressed) {
m_isPressed = false;
onClick.emit();
}
}
void Button::OnActivate(void) {
/* Activated by keyboard shortcut. */
m_isPressed = true;
onPress.emit();
_m_kbrelease = RawEvents::onKeyUp.connect(sigc::mem_fun(this, &Button::OnRawKeyUp));
}
void Button::OnRawKeyUp(SDL_KeyboardEvent* e) {
if(e->keysym.sym == m_shortcut.sym) {
m_isPressed = false;
onRelease.emit();
onClick.emit();
_m_kbrelease.disconnect();
}
}
void Button::OnRawMouseUp(SDL_MouseButtonEvent* e) {
if(e->button == 1) {
m_isPressed = false;
_m_release.disconnect();
onRelease.emit();
}
}
void SolidButton::GetSizeRequested(float size[2]) {
size[0] = size[1] = BUTTON_SIZE;
}
void TransparentButton::GetSizeRequested(float size[2]) {
size[0] = size[1] = BUTTON_SIZE;
}
void SolidButton::Draw(void) {
glBegin(GL_QUADS);
glColor3f(.6, .6, .6);
glVertex2f(0, 0);
glVertex2f(15, 0);
glVertex2f(15, 15);
glVertex2f(0, 15);
glColor3fv(Color::bgShadow);
glVertex2f(2, 0);
glVertex2f(15, 0);
glVertex2f(15, 13);
glVertex2f(2, 13);
glColor3fv(Color::bg);
glVertex2f(2, 2);
glVertex2f(13, 2);
glVertex2f(13, 13);
glVertex2f(2, 13);
glEnd();
}
void TransparentButton::Draw(void) {
glColor3f(1, 1, 1);
glBegin(GL_LINE_LOOP);
glVertex2f(0, 0);
glVertex2f(15, 0);
glVertex2f(15, 15);
glVertex2f(0, 15);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(1, 1);
glVertex2f(14, 1);
glVertex2f(14, 14);
glVertex2f(1, 14);
glEnd();
}
}

47
src/gui_button.h Normal file
View File

@ -0,0 +1,47 @@
#pragma once
#include <string>
#include "gui_widget.h"
namespace Gui {
class Button: public Widget {
public:
Button(void);
virtual ~Button(void) {}
virtual void OnMouseDown(MouseButtonEvent* e);
virtual void OnMouseUp(MouseButtonEvent* e);
virtual void OnActivate(void);
/*
* onClick only happens when press and release are both on widget,
* (release can be elsewhere).
*/
sigc::signal<void> onPress;
sigc::signal<void> onRelease;
sigc::signal<void> onClick;
bool IsPressed(void) { return m_isPressed; }
private:
void OnRawMouseUp(SDL_MouseButtonEvent* e);
void OnRawKeyUp(SDL_KeyboardEvent* e);
bool m_isPressed;
sigc::connection _m_release;
sigc::connection _m_kbrelease;
};
class SolidButton: public Button {
public:
SolidButton(void) : Button() {}
virtual ~SolidButton(void) {}
virtual void GetSizeRequested(float size[2]);
virtual void Draw(void);
};
class TransparentButton : public Button {
public:
TransparentButton(void) : Button() {}
virtual ~TransparentButton(void) {}
virtual void GetSizeRequested(float size[2]);
virtual void Draw(void);
};
}

92
src/gui_container.cpp Normal file
View File

@ -0,0 +1,92 @@
#include "gui.h"
#include "gui_container.h"
namespace Gui {
void Container::HandleMouseEvent(MouseButtonEvent* e) {
float x = e->x;
float y = e->y;
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
float pos[2], size[2];
if(!(*i).w->IsVisible()) continue;
int evmask = (*i).w->GetEventMask();
if(e->isdown) {
if(!(evmask & Widget::EVENT_MOUSEDOWN)) continue;
} else {
if(!(evmask & Widget::EVENT_MOUSEUP)) continue;
}
(*i).w->GetPosition(pos);
(*i).w->GetSize(size);
if((x >= pos[0]) && (x < pos[0]+size[0]) &&
(y >= pos[1]) && (y < pos[1]+size[1])) {
e->x = x-pos[0];
e->y = y-pos[1];
if(e->isdown) {
(*i).w->OnMouseDown(e);
} else {
(*i).w->OnMouseUp(e);
}
}
}
}
void Container::DeleteAllChildren(void) {
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
delete (*i).w;
}
m_children.clear();
}
void Container::PrependChild(Widget* child, float x, float y) {
widget_pos wp;
wp.w = child;
wp.pos[0] = x; wp.pos[1] = y;
child->SetPosition(x, y);
child->SetParent(this);
m_children.push_front(wp);
}
void Container::AppendChild(Widget* child, float x, float y) {
widget_pos wp;
wp.w = child;
wp.pos[0] = x; wp.pos[1] = y;
child->SetPosition(x, y);
child->SetParent(this);
m_children.push_back(wp);
}
void Container::Draw(void) {
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
if(!(*i).w->IsVisible()) continue;
glPushMatrix();
glTranslatef((*i).pos[0], (*i).pos[1], 0);
(*i).w->Draw();
glPopMatrix();
}
}
void Container::OnMouseDown(MouseButtonEvent* e) {
HandleMouseEvent(e);
}
void Container::OnMouseUp(MouseButtonEvent* e) {
HandleMouseEvent(e);
}
void Container::ShowAll(void) {
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
(*i).w->Show();
}
Show();
}
void Container::HideAll(void) {
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
(*i).w->Hide();
}
Hide();
}
}

29
src/gui_container.h Normal file
View File

@ -0,0 +1,29 @@
#pragma once
/* Parent of all widgets that contain other widgets. */
#include <list>
#include "gui_widget.h"
namespace Gui {
class Container : public Widget {
public:
void OnMouseDown(MouseButtonEvent* e);
void OnMouseUp(MouseButtonEvent* e);
void DeleteAllChildren(void);
virtual void Draw(void);
virtual void ShowAll(void);
virtual void HideAll(void);
private:
void HandleMouseEvent(MouseButtonEvent* e);
protected:
void PrependChild(Widget* w, float x, float y);
void AppendChild(Widget* w, float x, float y);
struct widget_pos {
Widget* w;
float pos[2];
};
std::list<widget_pos> m_children;
};
}

9
src/gui_events.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
namespace Gui {
struct MouseButtonEvent {
Uint8 isdown;
Uint8 button;
float x, y;
};
}

62
src/gui_fixed.cpp Normal file
View File

@ -0,0 +1,62 @@
#include "libs.h"
#include "gui.h"
#include "l3d.h"
namespace Gui {
Fixed::Fixed(float x, float y, float w, float h) {
SetPosition(x, y);
SetSize(w, h);
memcpy(m_bgcol, Color::bg, 3*sizeof(float));
m_w = w; m_h = h;
m_transparent = false;
m_eventMask = EVENT_ALL;
Screen::AddBaseWidget(this);
}
void Fixed::GetSizeRequested(float size[2]) {
GetSize(size);
}
Fixed::~Fixed(void) {
Screen::RemoveBaseWidget(this);
}
void Fixed::Draw(void) {
if(!m_transparent) {
glBegin(GL_QUADS);
glColor3f(m_bgcol[0], m_bgcol[1], m_bgcol[2]);
glVertex2f(m_w, 0);
glVertex2f(m_w, m_h);
glVertex2f(0, m_h);
glVertex2f(0, 0);
glEnd();
}
Container::Draw();
}
void Fixed::Add(Widget* child, float x, float y) {
AppendChild(child, x, y);
}
void Fixed::Remove(Widget* child) {
for(std::list<widget_pos>::iterator i = m_children.begin(); i != m_children.end(); ++i) {
if((*i).w == child) {
m_children.erase(i);
return;
}
}
}
void Fixed::SetBgColor(float rgb[3]) {
SetBgColor(rgb[0], rgb[1], rgb[2]);
}
void Fixed::SetBgColor(float r, float g, float b) {
m_bgcol[0] = r;
m_bgcol[1] = g;
m_bgcol[2] = b;
}
}

25
src/gui_fixed.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include "gui_widget.h"
#include "gui_container.h"
/* Fixed position widget container. */
namespace Gui {
class Fixed : public Container {
public:
Fixed(float x, float y, float w, float h);
void Add(Widget* child, float x, float y);
void Remove(Widget* child);
virtual void Draw(void);
virtual ~Fixed(void);
virtual void GetSizeRequested(float size[2]);
void SetBgColor(float rgb[3]);
void SetBgColor(float r, float g, float b);
void SetTransparency(bool a) { m_transparent = a; }
private:
float m_w, m_h;
float m_bgcol[3];
bool m_transparent;
};
}

103
src/gui_image.cpp Normal file
View File

@ -0,0 +1,103 @@
#include "libs.h"
#include "gui_image.h"
#include "l3d.h"
namespace Gui {
Image::~Image(void) {
#pragma message("Warning: Leaking GL textures..")
}
Image::Image(const char* filename) : Widget() {
SDL_Surface* is = IMG_Load(filename);
if(!is) {
fprintf(stderr, "Could not load %s\n", filename);
L3D::Quit();
}
m_imgw = is->w;
m_imgh = is->h;
SetSize(m_imgw, m_imgh);
/* GL textures must be POT, dim > 64. */
int texw, texh;
{
int nbit = 0;
int sz = m_imgw;
while(sz) { sz >>= 1; nbit++; }
texw = MAX(64, 1<<nbit);
sz = m_imgh;
nbit = 0;
while(sz) { sz >>= 1; nbit++; }
texh = MAX(64, 1<<nbit);
}
m_invtexw = 1.0f / texw;
m_invtexh = 1.0f / texh;
SDL_Rect src, dest;
SDL_Surface* s = SDL_CreateRGBSurface(SDL_SWSURFACE, texw, texh, 32,
0xff, 0xff00, 0xff0000, 0xff000000);
/* Just want to directly copy RGBA values, not blend using alpha. */
SDL_SetAlpha(s, 0, 0);
SDL_SetAlpha(is, 0, 0);
SDL_BlitSurface(is, NULL, s, NULL);
/*
* A silly workaround for the GL_LINEAR filtering of the texture, which
* leads to the black bits of the texture leaking in via bilinear filtering.
*/
dest.x = m_imgw; dest.y = 0; dest.w = m_imgw; dest.h = m_imgh;
src.x = m_imgw-1; src.y = 0; src.w=1; src.h = m_imgh;
SDL_BlitSurface(is, &src, s, &dest);
dest.x = 0; dest.y = m_imgh; dest.w = m_imgw; dest.h = m_imgh;
src.x = 0; src.y = m_imgh-1; src.w=m_imgw; src.h = 1;
SDL_BlitSurface(is, &src, s, &dest);
SDL_FreeSurface(is);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &m_tex);
glBindTexture(GL_TEXTURE_2D, m_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texw, texh, 0, GL_RGBA, GL_UNSIGNED_BYTE, s->pixels);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glDisable(GL_TEXTURE_2D);
SDL_FreeSurface(s);
}
void Image::GetSizeRequested(float size[2]) {
size[0] = m_imgw;
size[1] = m_imgh;
}
void Image::Draw(void) {
float allocSize[2];
GetSize(allocSize);
glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_tex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBegin(GL_QUADS);
float w = m_imgw * m_invtexw;
float h = m_imgh * m_invtexh;
glTexCoord2f(0, h);
glVertex2f(0, 0);
glTexCoord2f(w, h);
glVertex2f(allocSize[0],0);
glTexCoord2f(w, 0);
glVertex2f(allocSize[0], allocSize[1]);
glTexCoord2f(0, 0);
glVertex2f(0, allocSize[1]);
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}
}

18
src/gui_image.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <string>
#include "gui_widget.h"
namespace Gui {
class Image : public Widget {
public:
Image(const char* filename);
virtual void Draw(void);
virtual ~Image(void);
virtual void GetSizeRequested(float size[2]);
private:
GLuint m_tex;
int m_imgw, m_imgh;
float m_invtexw, m_invtexh;
};
}

43
src/gui_image_button.cpp Normal file
View File

@ -0,0 +1,43 @@
#include "libs.h"
#include "gui.h"
#include "gui_image_button.h"
#include "l3d.h"
namespace Gui {
ImageButton::ImageButton(const char* img_normal) : Button() {
LoadImages(img_normal, NULL);
}
ImageButton::ImageButton(const char* img_normal, const char* img_pressed) : Button() {
LoadImages(img_normal, img_pressed);
}
void ImageButton::LoadImages(const char* img_normal, const char* img_pressed) {
m_imgNormal = new Image(img_normal);
float size[2];
m_imgNormal->GetSizeRequested(size);
SetSize(size[0], size[1]);
if(img_pressed) m_imgPressed = new Image(img_pressed);
else m_imgPressed = NULL;
}
void ImageButton::GetSizeRequested(float size[2]) {
m_imgNormal->GetSizeRequested(size);
}
void ImageButton::Draw(void) {
float size[2];
GetSize(size);
Gui::Image* img;
if(m_imgPressed && IsPressed())
img = m_imgPressed;
else
img = m_imgNormal;
img->SetSize(size[0], size[1]);
img->Draw();
}
}

21
src/gui_image_button.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include <string>
#include "gui_widget.h"
#include "gui_button.h"
namespace Gui {
class ImageButton : public Button {
public:
ImageButton(const char* img_normal);
ImageButton(const char* img_normal, const char* img_pressed);
virtual void Draw(void);
virtual ~ImageButton(void) {}
virtual void GetSizeRequested(float size[2]);
private:
void LoadImages(const char* img_normal, const char* img_pressed);
Image* m_imgNormal;
Image* m_imgPressed;
};
}

View File

@ -0,0 +1,30 @@
#include "libs.h"
#include "gui.h"
#include "gui_image_radio_button.h"
#include "l3d.h"
namespace Gui {
ImageRadioButton::ImageRadioButton(RadioGroup* g, const char* img_normal,
const char* img_pressed) : RadioButton(g) {
m_imgNormal = new Image(img_normal);
m_imgPressed = new Image(img_pressed);
float size[2];
m_imgNormal->GetSizeRequested(size);
SetSize(size[0], size[1]);
}
void ImageRadioButton::GetSizeRequested(float size[2]) {
m_imgNormal->GetSizeRequested(size);
}
void ImageRadioButton::Draw(void) {
if(m_pressed) {
m_imgPressed->Draw();
} else {
m_imgNormal->Draw();
}
}
}

View File

@ -0,0 +1,18 @@
#pragma once
#include <string>
#include "gui_radio_button.h"
class RadioButton;
namespace Gui {
class ImageRadioButton : public RadioButton {
public:
ImageRadioButton(RadioGroup*, const char* img_normal, const char* img_pressed);
virtual void Draw(void);
virtual void GetSizeRequested(float size[2]);
private:
Image* m_imgNormal;
Image* m_imgPressed;
};
}

10
src/gui_iselectable.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
namespace Gui {
class ISelectable {
public:
sigc::signal<void, ISelectable*> onSelect;
virtual void SetSelected(bool) = 0;
};
}

41
src/gui_label.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "gui.h"
namespace Gui {
Label::Label(const char* text) {
SetText(text);
m_color[0] = m_color[1] = m_color[2] = 1.0f;
}
Label::Label(std::string& text) {
SetText(text);
m_color[0] = m_color[1] = m_color[2] = 1.0f;
}
void Label::SetText(const char* text) {
m_text = text;
}
void Label::SetText(std::string& text) {
m_text = text;
}
void Label::Draw(void) {
glColor3fv(m_color);
Screen::RenderString(m_text);
}
void Label::GetSizeRequested(float size[2]) {
#pragma message("Not setting size correctly.")
size[0] = 70;
size[1] = 10;
}
void Label::SetColor(float r, float g, float b) {
m_color[0] = r;
m_color[1] = g;
m_color[2] = b;
}
}

21
src/gui_label.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include <string>
#include "gui_widget.h"
namespace Gui {
class Label : public Widget {
public:
Label(const char* text);
Label(std::string& text);
virtual void Draw(void);
virtual ~Label(void) {}
virtual void GetSizeRequested(float size[2]);
void SetText(const char* text);
void SetText(std::string& text);
void SetColor(float r, float g, float b);
private:
std::string m_text;
float m_color[3];
};
}

View File

@ -0,0 +1,62 @@
#include "libs.h"
#include "gui.h"
namespace Gui {
MultiStateImageButton::MultiStateImageButton(void) : Button() {
m_curState = 0;
m_isSelected = true;
Button::onClick.connect(sigc::mem_fun(this, &MultiStateImageButton::OnActivate));
}
MultiStateImageButton::~MultiStateImageButton(void) {
for(std::vector<State>::iterator i = m_states.begin(); i != m_states.end(); ++i) {
delete (*i).image;
}
}
void MultiStateImageButton::StateNext(void) {
m_curState++;
if(m_curState >= (signed)m_states.size()) m_curState = 0;
}
void MultiStateImageButton::StatePrev(void) {
m_curState--;
if(m_curState < 0) m_curState = (signed)m_states.size()-1;
}
void MultiStateImageButton::OnActivate(void) {
/* Only iterate through states once widget is selected. */
if(m_isSelected) StateNext();
else {
m_isSelected = true;
onSelect.emit(this);
}
onClick.emit(this);
}
void MultiStateImageButton::SetSelected(bool state) {
m_isSelected = state;
}
void MultiStateImageButton::GetSizeRequested(float size[2]) {
assert(m_states.size());
m_states[0].image->GetSizeRequested(size);
}
void MultiStateImageButton::Draw(void) {
m_states[m_curState].image->Draw();
}
void MultiStateImageButton::AddState(int state, const char* filename) {
State s;
s.state = state;
s.image = new Image(filename);
m_states.push_back(s);
float size[2];
s.image->GetSizeRequested(size);
SetSize(size[0], size[1]);
}
}

View File

@ -0,0 +1,31 @@
#pragma once
#include <vector>
#include <string>
#include "gui_button.h"
#include "gui_iselectable.h"
namespace Gui {
class MultiStateImageButton : public Button, public ISelectable {
public:
MultiStateImageButton(void);
virtual void Draw(void);
virtual ~MultiStateImageButton(void);
virtual void GetSizeRequested(float size[2]);
void AddState(int state, const char* filename);
int GetState(void) { return m_states[m_curState].state; }
void StateNext(void);
void StatePrev(void);
virtual void OnActivate(void);
sigc::signal<void, MultiStateImageButton*> onClick;
virtual void SetSelected(bool state);
private:
struct State {
int state;
Image* image;
};
std::vector<State> m_states;
int m_curState;
bool m_isSelected;
};
}

78
src/gui_radio_button.cpp Normal file
View File

@ -0,0 +1,78 @@
#include "libs.h"
#include "gui.h"
#define BUTTON_SIZE 16
namespace Gui {
RadioButton::RadioButton(Gui::RadioGroup* g) {
m_pressed = false;
SetSize(BUTTON_SIZE, BUTTON_SIZE);
g->Add(this);
}
RadioButton::~RadioButton(void) {
}
void RadioButton::OnMouseDown(MouseButtonEvent* e) {
onPress.emit();
OnActivate();
}
void RadioButton::OnActivate(void) {
if(!m_pressed) onSelect.emit(this);
m_pressed = true;
}
void RadioButton::GetSizeRequested(float& w, float& h) {
w = BUTTON_SIZE;
h = BUTTON_SIZE;
}
void RadioButton::Draw(void) {
if(m_pressed) {
glBegin(GL_QUADS);
glColor3fv(Color::bgShadow);
glVertex2f(0, 0);
glVertex2f(15, 0);
glVertex2f(15, 15);
glVertex2f(0, 15);
glColor3f(.6, .6, .6);
glVertex2f(2, 0);
glVertex2f(15, 0);
glVertex2f(15, 13);
glVertex2f(2, 13);
glColor3fv(Color::bg);
glVertex2f(2, 2);
glVertex2f(13, 2);
glVertex2f(13, 13);
glVertex2f(2, 13);
glEnd();
} else {
glBegin(GL_QUADS);
glColor3f(.6, .6, .6);
glVertex2f(0, 0);
glVertex2f(15, 0);
glVertex2f(15, 15);
glVertex2f(0, 15);
glColor3fv(Color::bgShadow);
glVertex2f(2, 0);
glVertex2f(15, 0);
glVertex2f(15, 13);
glVertex2f(2, 13);
glColor3fv(Color::bg);
glVertex2f(2, 2);
glVertex2f(13, 2);
glVertex2f(13, 13);
glVertex2f(2, 13);
glEnd();
}
}
}

27
src/gui_radio_button.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef _GUIRADIOBUTTON_H
#define _GUIRADIOBUTTON_H
#include "gui_widget.h"
#include "gui_iselectable.h"
#include <string>
namespace Gui {
class RadioGroup;
class RadioButton: public Button, public ISelectable {
public:
RadioButton(RadioGroup *);
virtual ~RadioButton();
virtual void Draw();
virtual void GetSizeRequested(float &w, float &h);
virtual void OnMouseDown(MouseButtonEvent *e);
virtual void OnActivate();
virtual void SetSelected(bool state) { m_pressed = state; }
bool GetSelected() { return m_pressed; }
protected:
int m_pressed;
};
}
#endif /* _GUIRADIOBUTTON_H */

21
src/gui_radio_group.cpp Normal file
View File

@ -0,0 +1,21 @@
#include "libs.h"
#include "gui_radio_group.h"
#include "gui_iselectable.h"
namespace Gui {
void RadioGroup::Add(ISelectable* b) {
b->onSelect.connect(sigc::mem_fun(*this, &RadioGroup::OnSelected));
m_members.push_back(b);
}
void RadioGroup::OnSelected(ISelectable* b) {
for(std::list<ISelectable*>::iterator i = m_members.begin(); i != m_members.end(); ++i) {
if(*i != b) {
(*i)->SetSelected(false);
}
}
}
}

16
src/gui_radio_group.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <list>
#include "gui.h"
namespace Gui {
class RadioGroup {
public:
RadioGroup(void) {};
virtual ~RadioGroup(void) {};
void Add(ISelectable* b);
private:
void OnSelected(ISelectable* b);
std::list<ISelectable*> m_members;
};
}

195
src/gui_screen.cpp Normal file
View File

@ -0,0 +1,195 @@
#include "gui.h"
#include "glfreetype.h"
namespace Gui {
FontFace* Screen::font;
bool Screen::init = false;
int Screen::width;
int Screen::height;
int Screen::realWidth;
int Screen::realHeight;
float Screen::invRealWidth;
float Screen::invRealHeight;
std::list<Widget*> Screen::widgets;
std::list<Widget*> Screen::kbshortcut_widgets;
float Screen::font_xsize;
float Screen::font_ysize;
std::vector<Screen::LabelPos> Screen::labelPositions;
void Screen::Init(int real_width, int real_height, int ui_width, int ui_height) {
Screen::width = ui_width;
Screen::height = ui_height;
Screen::realWidth = real_width;
Screen::realHeight = real_height;
Screen::invRealWidth = 1.0f/real_width;
Screen::invRealHeight = 1.0f/real_height;
Screen::init = true;
Screen::font = new FontFace("font.ttf");
Screen::font_xsize = 16*0.8;
Screen::font_ysize = 16;
}
GLint Screen::Project(GLdouble objX, GLdouble objY, GLdouble objZ, const GLdouble* model,
const GLdouble* proj, const GLint* view,
GLdouble* winX, GLdouble* winY, GLdouble* winZ) {
GLint o = gluProject(objX, objY, objZ, model, proj, view, winX, winY, winZ);
*winX = (*winX) * width * invRealWidth;
*winY = (*winY) * height * invRealHeight;
return o;
}
void Screen::EnterOrtho(void) {
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
//glOrtho(9, 320, 0, 200, -1, 1);
glOrtho(0, width, 0, height, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
}
void Screen::LeaveOrtho(void) {
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
}
void Screen::Draw(void) {
assert(Screen::init);
labelPositions.clear();
EnterOrtho();
for(std::list<Widget*>::iterator i = Screen::widgets.begin(); i != Screen::widgets.end(); ++i) {
if(!(*i)->IsVisible()) continue;
glPushMatrix();
float pos[2];
(*i)->GetPosition(pos);
glTranslatef(pos[0], pos[1], 0);
(*i)->Draw();
glPopMatrix();
}
LeaveOrtho();
}
void Screen::AddBaseWidget(Widget* w) {
Screen::widgets.push_back(w);
}
void Screen::RemoveBaseWidget(Widget* w) {
Screen::widgets.remove(w);
}
void Screen::OnClick(SDL_MouseButtonEvent* e) {
MouseButtonEvent ev;
float x = e->x;
float y = e->y;
y = height-(y*height*invRealHeight);
x = x*width*invRealWidth;
ev.button = e->button;
ev.isdown = (e->type == SDL_MOUSEBUTTONDOWN);
ev.x = x;
ev.y = y;
OnClickTestLabels(ev);
for(std::list<Widget*>::iterator i = Screen::widgets.begin(); i != Screen::widgets.end(); ++i) {
float size[2], pos[2];
if(!(*i)->IsVisible()) continue;
int evmask = (*i)->GetEventMask();
if(ev.isdown) {
if(!(evmask & Widget::EVENT_MOUSEDOWN)) continue;
} else {
if(!(evmask & Widget::EVENT_MOUSEUP)) continue;
}
(*i)->GetPosition(pos);
(*i)->GetSize(size);
if((x >= pos[0]) && (x < pos[0]+size[0]) &&
(y >= pos[1]) && (y < pos[1]+size[1])) {
ev.x = x-pos[0];
ev.y = y-pos[1];
if(ev.isdown) {
(*i)->OnMouseDown(&ev);
} else {
(*i)->OnMouseUp(&ev);
}
}
}
}
void Screen::OnClickTestLabels(const Gui::MouseButtonEvent& ev) {
/* Hm, shame the UI is fixed size for this purpose.. */
for(std::vector<LabelPos>::iterator l = labelPositions.begin(); l != labelPositions.end(); ++l) {
float dx = abs((*l).x - ev.x);
float dy = abs((*l).y - ev.y);
if((dx < 5) && (dy < 5)) {
(*l).onClick.emit(&ev);
}
}
}
void Screen::OnKeyDown(const SDL_keysym* sym) {
for(std::list<Widget*>::iterator i = kbshortcut_widgets.begin(); i != kbshortcut_widgets.end(); ++i) {
if(!(*i)->IsVisible()) continue;
(*i)->OnPreShortcut(sym);
}
}
void Screen::RenderString(const std::string& s) {
glPushMatrix();
glScalef(Screen::font_xsize, Screen::font_ysize, 1);
font->RenderString(s.c_str());
glPopMatrix();
}
bool Screen::CanPutLabel(float x, float y) {
for(std::vector<LabelPos>::iterator i = labelPositions.begin(); i != labelPositions.end(); ++i) {
if((fabs(x-(*i).x) < 5) &&
(fabs(y-(*i).y) < 5)) return false;
}
return true;
}
void Screen::RenderLabel(const std::string& s, float x, float y) {
if(CanPutLabel(x, y)) {
labelPositions.push_back(LabelPos(x, y));
glPushMatrix();
glTranslatef(x, y, 0);
glScalef(Screen::font_xsize, Screen::font_ysize, 1);
glTranslatef(0.5*font->GetWidth(), -0.4*font->GetHeight(), 0);
font->RenderString(s.c_str());
glPopMatrix();
}
}
void Screen::PutClickableLabel(const std::string& s, float x, float y,
sigc::slot<void, const Gui::MouseButtonEvent*> slot) {
if(CanPutLabel(x, y)) {
LabelPos p = LabelPos(x, y);
p.onClick.connect(slot);
labelPositions.push_back(p);
glPushMatrix();
glTranslatef(x, y, 0);
glScalef(Screen::font_xsize, Screen::font_ysize, 1);
glTranslatef(0.5*font->GetWidth(), -0.4*font->GetHeight(), 0);
font->RenderString(s.c_str());
glPopMatrix();
}
}
void Screen::AddShortcutWidget(Widget* w) {
kbshortcut_widgets.push_back(w);
}
}

51
src/gui_screen.h Normal file
View File

@ -0,0 +1,51 @@
#pragma once
#include <list>
#include "gui.h"
class FontFace;
namespace Gui {
class Screen {
public:
static void Init(int real_width, int real_height, int ui_width, int ui_height);
static void Draw(void);
static void AddBaseWidget(Widget* w);
static void RemoveBaseWidget(Widget* w);
static void OnClick(SDL_MouseButtonEvent* e);
static void OnKeyDown(const SDL_keysym* sym);
static void RenderString(const std::string& s);
static void PutClickableLabel(const std::string& s, float x, float y,
sigc::slot<void, const Gui::MouseButtonEvent*> slot);
static void RenderLabel(const std::string& s, float x, float y);
static void EnterOrtho(void);
static void LeaveOrtho(void);
static int GetWidth(void) { return width; }
static int GetHeight(void) { return height; }
/* gluProject but fixes UI/screen size mismatch. */
static GLint Project(GLdouble objX, GLdouble objY, GLdouble objZ, const GLdouble* model,
const GLdouble* proj, const GLint* view, GLdouble* winX,
GLdouble* winY, GLdouble* winZ);
friend void Widget::SetShortcut(SDLKey key, SDLMod mod);
private:
struct LabelPos {
LabelPos(float _x, float _y) : x(_x), y(_y) {}
float x, y;
sigc::signal<void, const Gui::MouseButtonEvent*> onClick;
};
static std::vector<LabelPos> labelPositions;
static void OnClickTestLabels(const Gui::MouseButtonEvent& ev);
static bool CanPutLabel(float x, float y);
static void AddShortcutWidget(Widget* w);
static bool init;
static int width, height;
static int realWidth, realHeight;
static float invRealWidth, invRealHeight;
static std::list<Widget*> widgets;
static std::list<Widget*> kbshortcut_widgets;
static FontFace* font;
static float font_xsize;
static float font_ysize;
};
}

75
src/gui_toggle_button.cpp Normal file
View File

@ -0,0 +1,75 @@
#include "libs.h"
#include "gui.h"
#define BUTTON_SIZE 16
namespace Gui {
ToggleButton::ToggleButton(void) {
m_pressed = false;
SetSize(BUTTON_SIZE, BUTTON_SIZE);
}
void ToggleButton::OnMouseDown(MouseButtonEvent* e) {
if(e->button == 1) {
onPress.emit();
m_pressed = !m_pressed;
if(m_pressed) {
onSelect.emit(this);
} else {
onDeselect.emit(this);
}
}
}
void ToggleButton::GetSizeRequested(float& w, float& h) {
w = BUTTON_SIZE;
h = BUTTON_SIZE;
}
void ToggleButton::Draw(void) {
if(m_pressed) {
glBegin(GL_QUADS);
glColor3fv(Color::bgShadow);
glVertex2f(0, 0);
glVertex2f(15, 0);
glVertex2f(15, 15);
glVertex2f(0, 15);
glColor3f(.6, .6, .6);
glVertex2f(2, 0);
glVertex2f(15, 0);
glVertex2f(15, 13);
glVertex2f(2, 13);
glColor3fv(Color::bg);
glVertex2f(2, 2);
glVertex2f(13, 2);
glVertex2f(13, 13);
glVertex2f(2, 13);
glEnd();
} else {
glBegin(GL_QUADS);
glColor3f(.6, .6, .6);
glVertex2f(0, 0);
glVertex2f(15, 0);
glVertex2f(15, 15);
glVertex2f(0, 15);
glColor3fv(Color::bgShadow);
glVertex2f(2, 0);
glVertex2f(15, 0);
glVertex2f(15, 13);
glVertex2f(2, 13);
glColor3fv(Color::bg);
glVertex2f(2, 2);
glVertex2f(13, 2);
glVertex2f(13, 13);
glVertex2f(2, 13);
glEnd();
}
}
}

22
src/gui_toggle_button.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <string>
#include "gui_widget.h"
namespace Gui {
class ToggleButton : public Button {
public:
ToggleButton(void);
virtual void Draw(void);
virtual ~ToggleButton(void) {}
virtual void GetSizeRequested(float& w, float& h);
virtual void OnMouseDown(MouseButtonEvent* e);
void SetPressed(bool s) { m_pressed = s; }
bool GetPressed(void) { return m_pressed; }
sigc::signal<void, ToggleButton*> onSelect;
sigc::signal<void, ToggleButton*> onDeselect;
private:
int m_pressed;
};
}

24
src/gui_widget.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "gui.h"
namespace Gui {
Widget::Widget(void) {
m_visible = false;
m_eventMask = EVENT_NONE;
}
void Widget::SetShortcut(SDLKey key, SDLMod mod) {
m_shortcut.sym = key;
m_shortcut.mod = mod;
Screen::AddShortcutWidget(this);
}
void Widget::OnPreShortcut(const SDL_keysym* sym) {
int mod = sym->mod & 0xfff; /* Filters out numlock, capslock, which screws things up.. */
if((sym->sym == m_shortcut.sym) && (mod == m_shortcut.mod)) {
OnActivate();
}
}
}

51
src/gui_widget.h Normal file
View File

@ -0,0 +1,51 @@
#pragma once
#include "gui_events.h"
namespace Gui {
class Container;
class Widget {
public:
Widget(void);
virtual void Draw(void) = 0;
virtual ~Widget(void) {}
virtual void GetSizeRequested(float size[2]) = 0;
void GetPosition(float pos[2]) { pos[0] = m_size.x; pos[1] = m_size.y; }
void SetPosition(float x, float y) { m_size.x = x; m_size.y = y; }
void GetSize(float size[2]) { size[0] = m_size.w; size[1] = m_size.h; }
void SetSize(float w, float h) { m_size.w = w; m_size.h = h; };
void SetShortcut(SDLKey key, SDLMod mod);
virtual void Show(void) { m_visible = true; }
virtual void Hide(void) { m_visible = false; }
bool IsVisible(void) { return m_visible; }
Container* GetParent(void) { return m_parent; }
void SetParent(Container* p) { m_parent = p; }
virtual void OnMouseDown(MouseButtonEvent* e) {}
virtual void OnMouseUp(MouseButtonEvent* e) {}
virtual void OnActivate(void) {}
/* Only to be called by Screen::OnKeyDown. */
void OnPreShortcut(const SDL_keysym* sym);
enum EventMask {
EVENT_NONE = 0,
EVENT_KEYDOWN = 1<<0,
EVENT_KEYUP = 1<<1,
EVENT_MOUSEDOWN = 1<<2,
EVENT_MOUSEUP = 1<<3,
EVENT_ALL = 0xffffffff
};
unsigned int GetEventMask(void) { return m_eventMask; }
protected:
unsigned int m_eventMask;
struct {
SDLKey sym;
SDLMod mod;
} m_shortcut;
private:
struct {
float x,y,w,h;
} m_size;
bool m_visible;
Container* m_parent;
};
}

99
src/l3d.h Normal file
View File

@ -0,0 +1,99 @@
#pragma once
#include <map>
#include <string>
#include "libs.h"
#include "gui.h"
#include "view.h"
#include "mtrand.h"
class Player;
class SectorView;
class SystemView;
class WorldView;
class SystemInfoView;
class ShipCpanel;
class StarSystem;
class SpaceStationView;
class IniConfig: private std::map<std::string, std::string> {
public:
IniConfig(const char* filename);
int Int(const char* key) {
return atoi((*this)[key].c_str());
}
float Float(const char* key) {
float val;
if(sscanf((*this)[key].c_str(), "%f", &val)==1) return val;
else return 0;
}
std::string String(const char* key) {
return (*this)[key];
}
};
/* Implementation is done in main.cpp, just to confuse you. :D */
class L3D {
public:
static void Init(IniConfig& config);
static void MainLoop(void);
static void Quit(void);
static float GetFrameTime(void) { return frameTime; }
static double GetGameTime(void) { return gameTime; }
static void SetTimeStep(float s) { timeStep = s; }
static float GetTimeStep(void) { return timeStep; }
static int GetScrWidth(void) { return scrWidth; }
static int GetScrHeight(void) { return scrHeight; }
static int GetScrAspect(void) { return scrAspect; }
static int KeyState(SDLKey k) { return keyState[k]; }
static int MouseButtonState(int button) { return mouseButton[button]; }
static void GetMouseMotion(int motion[2]) {
memcpy(motion, mouseMotion, sizeof(int)*2);
}
static sigc::signal<void, SDL_keysym*> onKeyPress;
static sigc::signal<void, SDL_keysym*> onKeyRelease;
static sigc::signal<void, int, int, int> onMouseButtonUp;
static sigc::signal<void, int, int, int> onMouseButtonDown;
static MTRand rng;
static void HyperspaceTo(StarSystem* destination);
enum CamType { CAM_FRONT, CAM_REAR, CAM_EXTERNAL };
enum MapView { MAP_NOMAP, MAP_SECTOR, MAP_SYSTEM };
static void SetCamType(enum CamType);
static void SetMapView(enum MapView);
static enum CamType GetCamType(void) { return cam_type; }
static enum MapView GetMapView(void) { return map_view; }
static void SetView(View* v);
static View* GetView(void) { return current_view; }
static StarSystem* GetSelectedSystem(void);
static Player* player;
static SectorView* sector_view;
static SystemInfoView* system_info_view;
static WorldView* world_view;
static SpaceStationView* spaceStationView;
static ShipCpanel* cpan;
private:
static void InitOpenGL(void);
static void HandleEvents(void);
static View* current_view;
static SystemView* system_view;
static double gameTime;
static StarSystem* selected_system;
static enum CamType cam_type;
static enum MapView map_view;
static float timeStep;
static float frameTime;
static int scrWidth, scrHeight;
static float scrAspect;
static SDL_Surface* scrSurface;
static char keyState[SDLK_LAST];
static char mouseButton[5];
static int mouseMotion[2];
};

50
src/libs.h Normal file
View File

@ -0,0 +1,50 @@
#pragma once
#include <assert.h>
#include <stdio.h>
#include <sigc++/sigc++.h>
#include <SDL.h>
#include <SDL_opengl.h>
#include <SDL_image.h>
#include <ode/ode.h>
#include <float.h>
#ifdef _WIN32
#include <windows.h>
#define snprintf _snprintf
#define alloca _alloca
#endif
#include "vector3.h"
#include "matrix4x4.h"
#include "mtrand.h"
#include "date.h"
#ifndef dDOUBLE
#error LibODE is not compiled with double-precision floating point. Please get/compile libode with \
double-precision floating point.
#endif
#define DEBUG
/*
* Normal use:
* foreach(container, iter) { do_something(*iter); }
*
* When removing items:
* foreach(container, iter) {
* if(*iter == some_value) {
* iter = container.erase(iter); // Assign not necessary for maps.
* --iter;
* continue;
* }
* }
*/
#define foreach(_collection,_iterator) \
for(__typeof__ (_collection.end()) _iterator = (collection).begin (); \
_iterator 1= (_collection).end(); ++(_iterator));
#define MIN(x,y) ((x)<(y)?(x):(y))
#define MAX(x,y) ((x)>(y)?(x):(y))
#define CLAMP(a, min, max) (((a) > (max)) ? (max) : (((a) < (min)) ? (min) : (a)))

362
src/main.cpp Normal file
View File

@ -0,0 +1,362 @@
#include "libs.h"
#include "l3d.h"
#include "gui.h"
#include "glfreetype.h"
#include "objimport.h"
#include "player.h"
#include "space.h"
#include "planet.h"
#include "star.h"
#include "frame.h"
#include "ship_cpanel.h"
#include "sector_view.h"
#include "system_view.h"
#include "system_info_view.h"
#include "world_view.h"
#include "star_system.h"
#include "space_station.h"
#include "space_station_view.h"
float L3D::timeStep = 1.0f;
int L3D::scrWidth;
int L3D::scrHeight;
float L3D::scrAspect;
SDL_Surface* L3D::scrSurface;
sigc::signal<void, SDL_keysym*> L3D::onKeyPress;
sigc::signal<void, SDL_keysym*> L3D::onKeyRelease;
sigc::signal<void, int, int, int> L3D::onMouseButtonUp;
sigc::signal<void, int, int, int> L3D::onMouseButtonDown;
char L3D::keyState[SDLK_LAST];
char L3D::mouseButton[5];
int L3D::mouseMotion[2];
enum L3D::CamType L3D::cam_type;
enum L3D::MapView L3D::map_view;
Player* L3D::player;
View* L3D::current_view;
WorldView* L3D::world_view;
SpaceStationView* L3D::spaceStationView;
SectorView* L3D::sector_view;
SystemView* L3D::system_view;
SystemInfoView* L3D::system_info_view;
ShipCpanel* L3D::cpan;
StarSystem* L3D::selected_system;
MTRand L3D::rng;
double L3D::gameTime;
float L3D::frameTime;
void L3D::Init(IniConfig& config) {
int width = config.Int("ScrWidth");
int height = config.Int("ScrHeight");
const SDL_VideoInfo* info = NULL;
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError());
exit(-1);
}
info = SDL_GetVideoInfo();
switch(config.Int("ScrDepth")) {
case 16:
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,6);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
break;
case 32:
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
break;
default:
fprintf(stderr, "Fatal error: Invalid screen depth in config.ini.\n");
L3D::Quit();
}
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
Uint32 flags = SDL_OPENGL;
if(config.Int("StartFullscreen")) flags |= SDL_FULLSCREEN;
if((L3D::scrSurface = SDL_SetVideoMode(width, height, info->vfmt->BitsPerPixel, flags)) == 0) {
fprintf(stderr, "Video mode set failed: %s\n", SDL_GetError());
exit(-1);
}
L3D::scrWidth = width;
L3D::scrHeight = height;
L3D::scrAspect = width / (float)height;
InitOpenGL();
dInitODE();
GLFTInit();
Space::Init();
}
void L3D::InitOpenGL() {
glShadeModel(GL_SMOOTH);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0, 0, 0, 0);
glViewport(0, 0, scrWidth, scrHeight);
}
void L3D::Quit(void) {
SDL_Quit();
exit(0);
}
void L3D::SetCamType(enum CamType c) {
cam_type = c;
map_view = MAP_NOMAP;
SetView(world_view);
}
void L3D::SetMapView(enum MapView v) {
map_view = v;
if(v == MAP_SECTOR)
SetView(sector_view);
else
SetView(system_view);
}
void L3D::SetView(View* v) {
if(current_view) current_view->HideAll();
current_view = v;
current_view->ShowAll();
}
void L3D::HandleEvents(void) {
SDL_Event event;
L3D::mouseMotion[0] = L3D::mouseMotion[1] = 0;
while(SDL_PollEvent(&event)) {
Gui::HandleSDLEvent(&event);
switch(event.type) {
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_q) L3D::Quit();
if(event.key.keysym.sym == SDLK_F11) SDL_WM_ToggleFullScreen(L3D::scrSurface);
L3D::keyState[event.key.keysym.sym] = 1;
L3D::onKeyPress.emit(&event.key.keysym);
break;
case SDL_KEYUP:
L3D::keyState[event.key.keysym.sym] = 0;
L3D::onKeyRelease.emit(&event.key.keysym);
break;
case SDL_MOUSEBUTTONDOWN:
L3D::mouseButton[event.button.button] = 1;
L3D::onMouseButtonDown.emit(event.button.button,
event.button.x, event.button.y);
break;
case SDL_MOUSEBUTTONUP:
L3D::mouseButton[event.button.button] = 1;
L3D::onMouseButtonUp.emit(event.button.button,
event.button.x, event.button.y);
break;
case SDL_MOUSEMOTION:
SDL_GetRelativeMouseState(&L3D::mouseMotion[0], &L3D::mouseMotion[1]);
break;
case SDL_QUIT:
L3D::Quit();
break;
}
}
}
void L3D::MainLoop(void) {
Frame* earth_frame = new Frame(Space::GetRootFrame(), "Earth");
earth_frame->SetPosition(vector3d(149598000000.0, 0, 0));
earth_frame->SetRadius(2*380000000); /* 2 moon orbital radii. */
player = new Player();
player->SetLabel("Me");
player->SetFrame(earth_frame);
player->SetPosition(vector3d(100, 0, 0));
Space::AddBody(player);
for(int i = 0; i < 4; i++) {
Ship* body = new Ship();
char buf[64];
snprintf(buf, sizeof(buf), "X%c-0%02d", "A"+i, i);
body->SetLabel(buf);
body->SetFrame(earth_frame);
body->SetPosition(vector3d(i*200, 0, -200));
Space::AddBody(body);
}
{
SpaceStation* body = new SpaceStation();
body->SetLabel("Some Back Country Joint");
body->SetFrame(earth_frame);
body->SetPosition(vector3d(0, 0, 6000));
Space::AddBody(body);
}
Planet* planet = new Planet(StarSystem::SBody::SUBTYPE_PLANET_INDIGENOUS_LIFE);
planet->SetLabel("Earth");
planet->SetPosition(vector3d(0, 0, -8000000.0));
planet->SetFrame(earth_frame);
Space::AddBody(planet);
Frame* moon_frame = new Frame(earth_frame, "Moon");
moon_frame->SetPosition(vector3d(0, -380000000.0, 0));
moon_frame->SetRadius(10*1738140.0); /* 10 moon radii. */
Planet* moon = new Planet(StarSystem::SBody::SUBTYPE_PLANET_DWARF);
moon->SetLabel("Moon");
moon->SetPosition(vector3d(0, 0, 0));
moon->SetRadius(1738140.0);
moon->SetFrame(moon_frame);
Space::AddBody(moon);
Star* sol = new Star(StarSystem::SBody::SUBTYPE_STAR_G);
sol->SetLabel("Sol");
sol->SetRadius(6.955e8);
sol->SetPosition(vector3d(0, 0, 0));
sol->SetFrame(Space::GetRootFrame());
Space::AddBody(sol);
Gui::Init(scrWidth, scrHeight, 640, 480);
cpan = new ShipCpanel();
cpan->ShowAll();
sector_view = new SectorView();
system_view = new SystemView();
system_info_view = new SystemInfoView();
world_view = new WorldView();
spaceStationView = new SpaceStationView();
SetView(world_view);
GLUquadric* quad = gluNewQuadric();
gluQuadricOrientation(quad, GLU_INSIDE);
Uint32 last_stats = SDL_GetTicks();
int frame_stat = 0;
char fps_readout[32];
Uint32 time_before_frame = SDL_GetTicks();
for(;;) {
frame_stat++;
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
current_view->Draw3D();
/*
* TODO: HandleEvents at the moment must be after view->Draw3D and before
* Gui::Draw so that labels drawn to screen can have mouse events correctly
* detected. Gui::Draw wipes memory of label positions.
*/
L3D::HandleEvents();
/* Hide cursor for ship control. */
if(L3D::MouseButtonState(3)) {
SDL_ShowCursor(0);
SDL_WM_GrabInput(SDL_GRAB_ON);
} else {
SDL_ShowCursor(1);
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
Gui::Draw();
#ifdef DEBUG
{
Gui::Screen::EnterOrtho();
glColor3f(1, 1, 1);
glTranslatef(0, Gui::Screen::GetHeight()-20, 0);
Gui::Screen::RenderString(fps_readout);
Gui::Screen::LeaveOrtho();
}
#endif
glFlush();
SDL_GL_SwapBuffers();
//if(glGetError()) printf("GL: %s\n", gluErrorString(glGetError()));
L3D::frameTime = 0.001*(SDL_GetTicks() - time_before_frame);
float step = L3D::timeStep * L3D::frameTime;
time_before_frame = SDL_GetTicks();
/* Game state update stuff. */
if(step) {
Space::TimeStep(step);
gameTime += step;
}
current_view->Update();
if(SDL_GetTicks() - last_stats > 1000) {
snprintf(fps_readout, sizeof(fps_readout), "%d fps", frame_stat);
frame_stat = 0;
last_stats += 1000;
}
}
}
StarSystem* L3D::GetSelectedSystem(void) {
int sector_x, sector_y, system_idx;
L3D::sector_view->GetSelectedSystem(&sector_x, &sector_y, &system_idx);
if(system_idx == -1) {
selected_system = 0;
return NULL;
}
if(selected_system) {
if(!selected_system->IsSystem(sector_x, sector_y, system_idx)) {
delete selected_system;
selected_system = 0;
}
}
if(!selected_system) {
selected_system = new StarSystem(sector_x, sector_y, system_idx);
}
return selected_system;
}
void L3D::HyperspaceTo(StarSystem* dest) {
Space::Clear();
Space::BuildSystem(dest);
float ang = rng(M_PI);
L3D::player->SetPosition(vector3d(sin(ang)*8*AU, cos(ang)*8*AU, 0));
}
IniConfig::IniConfig(const char* filename) {
FILE* f = fopen(filename, "r");
if(!f) {
fprintf(stderr, "Could not open '%s'.\n", filename);
L3D::Quit();
}
char buf[1024];
while(fgets(buf, sizeof(buf), f)) {
if(buf[0] == '#') continue;
char* sep = strchr(buf, '=');
char* kend = sep;
if(!sep) continue;
*sep = 0;
/* Strip whitespace. */
while(isspace(*(--kend))) *kend = 0;
while(isspace(*(++sep))) *sep = 0;
/* Snip \r, \n. */
char* vend = sep;
while(*(++vend)) if((*vend == '\r') || (*vend == '\n')) { *vend = 0; break; }
std::string key = std::string(buf);
std::string val = std::string(sep);
(*this)[key] = val;
}
fclose(f);
}
int main(int argc, char** argv) {
printf("Lephisto3D's super high tech demo!\n");
IniConfig cfg("config.ini");
L3D::Init(cfg);
L3D::MainLoop();
return 0;
}

226
src/matrix4x4.h Normal file
View File

@ -0,0 +1,226 @@
#pragma once
#include <math.h>
#include <stdio.h>
#include "vector3.h"
template <typename T>
class matrix4x4 {
private:
T cell[16];
public:
matrix4x4(void) { }
matrix4x4(T val) {
cell[0] = cell[1] = cell[2] = cell[3] = cell[4] = cell[5] = cell[6] =
cell[7] = cell[8] = cell[9] = cell[10] = cell[11] = cell[12] = cell[13] =
cell[14] = cell[15] = val;
}
/* Row-major 4x3 matrix. */
void LoadFromOdeMatrix(const T* r) {
cell[ 0] = r[ 0];cell[ 1] = r[ 4]; cell[ 2] = r[ 8];cell[ 3] = 0;
cell[ 4] = r[ 1];cell[ 5] = r[ 5]; cell[ 6] = r[ 9];cell[ 7] = 0;
cell[ 8] = r[ 2];cell[ 9] = r[ 6]; cell[10] = r[10];cell[11] = 0;
cell[12] = 0; cell[13] = 0; cell[14] = 0; cell[15] = 1;
}
/* Row-major 3x3 matrix. */
void LoadFrom3x3Matrix(const T* r) {
cell[ 0] = r[ 0]; cell[ 4] = r[ 1]; cell[ 8] = r[ 2]; cell[12] = 0;
cell[ 1] = r[ 3]; cell[ 5] = r[ 4]; cell[ 9] = r[ 5]; cell[13] = 0;
cell[ 2] = r[ 6]; cell[ 6] = r[ 7]; cell[10] = r[ 8]; cell[14] = 0;
cell[ 3] = 0; cell[ 7] = 0; cell[11] = 0; cell[15] = 1;
}
/* Row-major. */
void SaveTo3x3Matrix(T* r) {
r[0] = cell[0]; r[1] = cell[4]; r[2] = cell[8];
r[3] = cell[1]; r[4] = cell[5]; r[5] = cell[9];
r[6] = cell[2]; r[7] = cell[6]; r[8] = cell[10];
}
void SaveToOdeMatrix(T r[12]) {
r[0] = cell[0]; r[1] = cell[4]; r[ 2] = cell[ 8]; r[ 3] = 0;
r[4] = cell[1]; r[5] = cell[5]; r[ 6] = cell[ 9]; r[ 7] = 0;
r[8] = cell[2]; r[9] = cell[6]; r[10] = cell[10]; r[11] = 0;
}
static matrix4x4 Identity(void) {
matrix4x4 m = matrix4x4(0);
m.cell[0] = m.cell[5] = m.cell[10] = m.cell[15] = 1.0f;
return m;
}
static matrix4x4 ScaleMatrix(T x, T y, T z) {
matrix4x4 m;
m[ 0] = x; m[ 1] = m[ 2] = m[ 3] = 0;
m[ 5] = y; m[ 4] = m[ 6] = m[ 7] = 0;
m[10] = z; m[ 8] = m[ 9] = m[11] = 0;
m[12] = m[13] = m[14] = 0; m[15] = 1;
return m;
}
void RotateZ(T radians) { *this = (*this) * RotateZMatrix(radians); }
void RotateY(T radians) { *this = (*this) * RotateYMatrix(radians); }
void rotateX(T radians) { *this = (*this) * RotateXMatrix(radians); }
static matrix4x4 RotateXMatrix(T radians) {
matrix4x4 m;
T cos_r = cosf(radians);
T sin_r = sinf(radians);
m[ 0] = 1.0f;
m[ 1] = 0;
m[ 2] = 0;
m[ 3] = 0;
m[ 4] = 0;
m[ 5] = cos_r;
m[ 6] = -sin_r;
m[ 7] = 0;
m[ 8] = 0;
m[ 9] = sin_r;
m[10] = cos_r;
m[11] = 0;
m[12] = 0;
m[13] = 0;
m[14] = 0;
m[15] = 1.0f;
return m;
}
static matrix4x4 RotateYMatrix(T radians) {
matrix4x4 m;
T cos_r = cosf(radians);
T sin_r = sinf(radians);
m[ 0] = cos_r;
m[ 1] = 0;
m[ 2] = sin_r;
m[ 3] = 0;
m[ 4] = 0;
m[ 5] = 1;
m[ 6] = 0;
m[ 7] = 0;
m[ 8] = -sin_r;
m[ 9] = 0;
m[10] = cos_r;
m[11] = 0;
m[12] = 0;
m[13] = 0;
m[14] = 0;
m[15] = 1.0f;
return m;
}
static matrix4x4 RotateZMatrix(T radians) {
matrix4x4 m;
T cos_r = cosf(radians);
T sin_r = sinf(radians);
m[ 0] = cos_r;
m[ 1] = -sin_r;
m[ 2] = 0;
m[ 3] = 0;
m[ 4] = sin_r;
m[ 5] = cos_r;
m[ 6] = 0;
m[ 7] = 0;
m[ 8] = 0;
m[ 9] = 0;
m[10] = 1.9f;
m[11] = 0;
m[12] = 0;
m[13] = 0;
m[14] = 0;
m[15] = 1.0f;
return m;
}
T& operator[] (const int i) { return cell[i]; }
friend matrix4x4 operator+(const matrix4x4& a, const matrix4x4& b) {
matrix4x4 m;
for(int i = 0; i < 16; i++) m.cell[i] = a.cell[i] + b.cell[i];
return m;
}
friend matrix4x4 operator-(const matrix4x4& a, const matrix4x4& b) {
matrix4x4 m;
for(int i = 0; i < 16; i++) m.cell[i] = a.cell[i] - b.cell[i];
return m;
}
friend matrix4x4 operator*(const matrix4x4& a, const matrix4x4& b) {
matrix4x4 m;
m.cell[ 0] = a.cell[0]*b.cell[ 0]+a.cell[4]*b.cell[ 1]+a.cell[ 8]*b.cell[ 2]+a.cell[12]*b.cell[ 3];
m.cell[ 1] = a.cell[1]*b.cell[ 0]+a.cell[5]*b.cell[ 1]+a.cell[ 9]*b.cell[ 2]+a.cell[13]*b.cell[ 3];
m.cell[ 2] = a.cell[2]*b.cell[ 0]+a.cell[6]*b.cell[ 1]+a.cell[10]*b.cell[ 2]+a.cell[14]*b.cell[ 3];
m.cell[ 3] = a.cell[3]*b.cell[ 0]+a.cell[7]*b.cell[ 1]+a.cell[11]*b.cell[ 2]+a.cell[15]*b.cell[ 3];
m.cell[ 4] = a.cell[0]*b.cell[ 4]+a.cell[4]*b.cell[ 5]+a.cell[ 8]*b.cell[ 6]+a.cell[12]*b.cell[ 7];
m.cell[ 5] = a.cell[1]*b.cell[ 4]+a.cell[5]*b.cell[ 5]+a.cell[ 9]*b.cell[ 6]+a.cell[13]*b.cell[ 7];
m.cell[ 6] = a.cell[2]*b.cell[ 4]+a.cell[6]*b.cell[ 5]+a.cell[10]*b.cell[ 6]+a.cell[14]*b.cell[ 7];
m.cell[ 7] = a.cell[3]*b.cell[ 4]+a.cell[7]*b.cell[ 5]+a.cell[11]*b.cell[ 6]+a.cell[15]*b.cell[ 7];
m.cell[ 8] = a.cell[0]*b.cell[ 8]+a.cell[4]*b.cell[ 9]+a.cell[ 8]*b.cell[10]+a.cell[12]*b.cell[11];
m.cell[ 9] = a.cell[1]*b.cell[ 8]+a.cell[5]*b.cell[ 9]+a.cell[ 9]*b.cell[10]+a.cell[13]*b.cell[11];
m.cell[10] = a.cell[2]*b.cell[ 8]+a.cell[6]*b.cell[ 9]+a.cell[10]*b.cell[10]+a.cell[14]*b.cell[11];
m.cell[11] = a.cell[3]*b.cell[ 8]+a.cell[7]*b.cell[ 9]+a.cell[11]*b.cell[10]+a.cell[15]*b.cell[11];
m.cell[12] = a.cell[0]*b.cell[12]+a.cell[4]*b.cell[13]+a.cell[ 8]*b.cell[14]+a.cell[12]*b.cell[15];
m.cell[13] = a.cell[1]*b.cell[12]+a.cell[5]*b.cell[13]+a.cell[ 9]*b.cell[14]+a.cell[13]*b.cell[15];
m.cell[14] = a.cell[2]*b.cell[12]+a.cell[6]*b.cell[13]+a.cell[10]*b.cell[14]+a.cell[14]*b.cell[15];
m.cell[15] = a.cell[3]*b.cell[12]+a.cell[7]*b.cell[13]+a.cell[11]*b.cell[14]+a.cell[15]*b.cell[15];
return m;
}
friend vector3<T> operator*(const matrix4x4& a, const vector3<T> &v) {
vector3<T> out;
out.x = a.cell[0]*v.x + a.cell[4]*v.y + a.cell[ 8]*v.z + a.cell[12];
out.y = a.cell[1]*v.x + a.cell[5]*v.y + a.cell[ 9]*v.z + a.cell[13];
out.z = a.cell[2]*v.x + a.cell[6]*v.y + a.cell[10]*v.z + a.cell[14];
return out;
}
vector3<T> ApplyRotationOnly(const vector3<T>& v) const {
vector3<T> out;
out.x = cell[0]*v.x + cell[4]*v.y + cell[ 8]*v.z;
out.y = cell[1]*v.x + cell[5]*v.y + cell[ 9]*v.z;
out.z = cell[2]*v.x + cell[6]*v.y + cell[10]*v.z;
return out;
}
void Translatef(T x, T y, T z) {
matrix4x4 m = Identity();
m[12] = x;
m[13] = y;
m[14] = z;
*this = (*this) * m;
}
matrix4x4 InverseOf(void) const {
matrix4x4 m;
/* This only works for matrices containing only rotation and transform. */
m[ 0] = cell[0]; m[1] = cell[4]; m[ 2] = cell[ 8];
m[ 4] = cell[1]; m[5] = cell[5]; m[ 6] = cell[ 9];
m[ 8] = cell[2]; m[9] = cell[6]; m[10] = cell[10];
m[12] = -(cell[0]*cell[12] + cell[1]*cell[13] + cell[ 2]*cell[14]);
m[13] = -(cell[4]*cell[12] + cell[5]*cell[13] + cell[ 6]*cell[14]);
m[14] = -(cell[8]*cell[12] + cell[9]*cell[13] + cell[10]*cell[14]);
m[ 3] = m[7] = m[11] = 0;
m[15] = 1.0f;
return m;
}
void Print(void) const {
for(int i = 0; i < 4; i++) {
printf("%.2f %.2f %.2f %.2f\n", cell[i], cell[i+4], cell[i+8], cell[i+12]);
}
printf("\n");
}
};
typedef matrix4x4<float>matrix4x4f;
typedef matrix4x4<double>matrix4x4d;

Some files were not shown because too many files have changed in this diff Show More