program "mesh2c"
{
- source "mesh2c.cpp";
+ source "tools/mesh2c.cpp";
build_info
{
library "mspgl";
program "viewer"
{
- source "viewer.cpp";
+ source "tools/viewer.cpp";
build_info
{
library "mspgl";
+++ /dev/null
-#include <msp/core/getopt.h>
-#include <msp/gl/mesh.h>
-#include <msp/io/print.h>
-#include <msp/strings/format.h>
-
-using namespace std;
-using namespace Msp;
-
-const char *types[] =
-{
- "unsigned char", "GL_UNSIGNED_BYTE",
- "unsigned short", "GL_UNSIGNED_SHORT",
- "unsigned", "GL_UNSIGNED_INT"
-};
-
-int main(int argc, char **argv)
-{
- string prefix;
- bool render_func = false;
- bool separate_arrays = false;
- GetOpt getopt;
- getopt.add_option('p', "prefix", prefix, GetOpt::REQUIRED_ARG);
- getopt.add_option('r', "render-func", render_func, GetOpt::NO_ARG);
- getopt.add_option('s', "separate-arrays", separate_arrays, GetOpt::NO_ARG);
- getopt(argc, argv);
-
- const vector<string> &args = getopt.get_args();
- if(args.empty())
- {
- IO::print(IO::cerr, "Usage: %s [options] <meshfile>\n", argv[0]);
- return 1;
- }
-
- GL::Mesh mesh;
- mesh.use_buffers(false);
- DataFile::load(mesh, args[0]);
-
- IO::print("/* Exported from %s */\n", args[0]);
-
- const GL::VertexArray &array = mesh.get_vertices();
- const GL::VertexFormat &fmt = array.get_format();
- unsigned stride = fmt.stride();
- if(separate_arrays)
- {
- unsigned offset = 0;
- for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i)
- {
- unsigned kind = (*i)>>2;
- unsigned size = ((*i)&3)+1;
- string name;
- switch(kind)
- {
- case 0:
- name = "vertex";
- break;
- case 1:
- name = "normal";
- break;
- case 2:
- name = "color";
- break;
- case 3:
- name = "texcoord";
- break;
- default:
- if(kind<11)
- name = format("texcoord%d", kind-3);
- else
- name = format("attrib%d", kind-11);
- break;
- }
-
- IO::print("float %s%s_data[] =\n{", prefix, name);
- for(unsigned j=0; j<array.size(); ++j)
- {
- const float *ptr = array[j]+offset;
- IO::print("\n\t");
- for(unsigned k=0; k<size; ++k)
- IO::print("%g, ", ptr[k]);
- }
- IO::print("\n};\n\n");
-
- offset += size;
- }
- }
- else
- {
- IO::print("float %svertex_data[] =\n{", prefix);
- for(unsigned i=0; i<array.size(); ++i)
- {
- const float *ptr = array[i];
- IO::print("\n\t");
- for(unsigned j=0; j<stride; ++j)
- IO::print("%g, ", ptr[j]);
- }
- IO::print("\n};\n\n");
- }
-
- const char **type = 0;
- if(array.size()<0x100)
- type = types;
- else if(array.size()<0x10000)
- type = types+2;
- else
- type = types+4;
-
- IO::print("%s %sindices[] =\n{", type[0], prefix);
- for(list<GL::Batch>::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i)
- {
- unsigned count = i->size();
- for(unsigned j=0; j<count; ++j)
- {
- if(j%16==0)
- IO::print("\n\t");
- IO::print("%d, ", i->get_index(j));
- }
- }
- IO::print("\n};\n\n");
-
- if(render_func)
- IO::print("void %srender()\n{\n", prefix);
- else
- IO::print("/*\nTo render the object, #include this file and add the following code:\n");
- unsigned offset = 0;
- for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i)
- {
- unsigned kind = (*i)>>2;
- unsigned size = ((*i)&3)+1;
- string source = format("%svertex_data+%d", prefix, offset);
- switch((*i)>>2)
- {
- case 0:
- if(separate_arrays)
- source = prefix+"vertex_data";
- IO::print("\tglVertexPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
- size, stride, source);
- IO::print("\tglEnableClientState(GL_VERTEX_ARRAY);\n");
- break;
- case 1:
- if(separate_arrays)
- source = prefix+"normal_data";
- IO::print("\tglNormalPointer(GL_FLOAT, %d*sizeof(float), %s);\n",
- stride, source);
- IO::print("\tglEnableClientState(GL_NORMAL_ARRAY);\n");
- break;
- case 2:
- if(separate_arrays)
- source = prefix+"color_data";
- IO::print("\tglColorPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
- size, stride, source);
- IO::print("\tglEnableClientState(GL_COLOR_ARRAY);\n");
- break;
- case 3:
- if(separate_arrays)
- source = prefix+"texcoord_data";
- IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
- size, stride, source);
- IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n");
- break;
- default:
- if(kind<11)
- {
- if(separate_arrays)
- source = format("%stexcoord%d_data", prefix, kind-3);
- IO::print("\tglClientActiveTexture(GL_TEXTURE%d);\n", kind-3);
- IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
- size, stride, source);
- IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n");
- }
- else
- {
- if(separate_arrays)
- source = format("%sattrib%d_data", prefix, kind-11);
- IO::print("\tglVertexAttribPointer(%d, %d, GL_FLOAT, GL_FALSE, %d*sizeof(float), %s);\n",
- kind-11, size, stride, source);
- IO::print("\tglEnableVertexAttribArray(%d);\n", kind-11);
- }
- break;
- }
- offset += size;
- }
- offset = 0;
- for(list<GL::Batch>::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i)
- {
- string mode;
- switch(i->get_type())
- {
- case GL_TRIANGLE_STRIP: mode = "GL_TRIANGLE_STRIP"; break;
- case GL_TRIANGLES: mode = "GL_TRIANGLES"; break;
- default: mode = format("%d", i->get_type()); break;
- }
- IO::print("\tglDrawElements(%s, %d, %s, %sindices+%d);\n", mode, i->size(), type[1], prefix, offset);
- offset += i->size();
- }
- if(render_func)
- {
- IO::print("}\n\n");
- IO::print("/* To render this object, #include this file and call %srender() */\n", prefix);
- }
- else
- IO::print("*/\n");
-
- return 0;
-}
--- /dev/null
+#include <msp/core/getopt.h>
+#include <msp/gl/mesh.h>
+#include <msp/io/print.h>
+#include <msp/strings/format.h>
+
+using namespace std;
+using namespace Msp;
+
+const char *types[] =
+{
+ "unsigned char", "GL_UNSIGNED_BYTE",
+ "unsigned short", "GL_UNSIGNED_SHORT",
+ "unsigned", "GL_UNSIGNED_INT"
+};
+
+int main(int argc, char **argv)
+{
+ string prefix;
+ bool render_func = false;
+ bool separate_arrays = false;
+ GetOpt getopt;
+ getopt.add_option('p', "prefix", prefix, GetOpt::REQUIRED_ARG);
+ getopt.add_option('r', "render-func", render_func, GetOpt::NO_ARG);
+ getopt.add_option('s', "separate-arrays", separate_arrays, GetOpt::NO_ARG);
+ getopt(argc, argv);
+
+ const vector<string> &args = getopt.get_args();
+ if(args.empty())
+ {
+ IO::print(IO::cerr, "Usage: %s [options] <meshfile>\n", argv[0]);
+ return 1;
+ }
+
+ GL::Mesh mesh;
+ mesh.use_buffers(false);
+ DataFile::load(mesh, args[0]);
+
+ IO::print("/* Exported from %s */\n", args[0]);
+
+ const GL::VertexArray &array = mesh.get_vertices();
+ const GL::VertexFormat &fmt = array.get_format();
+ unsigned stride = fmt.stride();
+ if(separate_arrays)
+ {
+ unsigned offset = 0;
+ for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i)
+ {
+ unsigned kind = (*i)>>2;
+ unsigned size = ((*i)&3)+1;
+ string name;
+ switch(kind)
+ {
+ case 0:
+ name = "vertex";
+ break;
+ case 1:
+ name = "normal";
+ break;
+ case 2:
+ name = "color";
+ break;
+ case 3:
+ name = "texcoord";
+ break;
+ default:
+ if(kind<11)
+ name = format("texcoord%d", kind-3);
+ else
+ name = format("attrib%d", kind-11);
+ break;
+ }
+
+ IO::print("float %s%s_data[] =\n{", prefix, name);
+ for(unsigned j=0; j<array.size(); ++j)
+ {
+ const float *ptr = array[j]+offset;
+ IO::print("\n\t");
+ for(unsigned k=0; k<size; ++k)
+ IO::print("%g, ", ptr[k]);
+ }
+ IO::print("\n};\n\n");
+
+ offset += size;
+ }
+ }
+ else
+ {
+ IO::print("float %svertex_data[] =\n{", prefix);
+ for(unsigned i=0; i<array.size(); ++i)
+ {
+ const float *ptr = array[i];
+ IO::print("\n\t");
+ for(unsigned j=0; j<stride; ++j)
+ IO::print("%g, ", ptr[j]);
+ }
+ IO::print("\n};\n\n");
+ }
+
+ const char **type = 0;
+ if(array.size()<0x100)
+ type = types;
+ else if(array.size()<0x10000)
+ type = types+2;
+ else
+ type = types+4;
+
+ IO::print("%s %sindices[] =\n{", type[0], prefix);
+ for(list<GL::Batch>::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i)
+ {
+ unsigned count = i->size();
+ for(unsigned j=0; j<count; ++j)
+ {
+ if(j%16==0)
+ IO::print("\n\t");
+ IO::print("%d, ", i->get_index(j));
+ }
+ }
+ IO::print("\n};\n\n");
+
+ if(render_func)
+ IO::print("void %srender()\n{\n", prefix);
+ else
+ IO::print("/*\nTo render the object, #include this file and add the following code:\n");
+ unsigned offset = 0;
+ for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i)
+ {
+ unsigned kind = (*i)>>2;
+ unsigned size = ((*i)&3)+1;
+ string source = format("%svertex_data+%d", prefix, offset);
+ switch((*i)>>2)
+ {
+ case 0:
+ if(separate_arrays)
+ source = prefix+"vertex_data";
+ IO::print("\tglVertexPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
+ size, stride, source);
+ IO::print("\tglEnableClientState(GL_VERTEX_ARRAY);\n");
+ break;
+ case 1:
+ if(separate_arrays)
+ source = prefix+"normal_data";
+ IO::print("\tglNormalPointer(GL_FLOAT, %d*sizeof(float), %s);\n",
+ stride, source);
+ IO::print("\tglEnableClientState(GL_NORMAL_ARRAY);\n");
+ break;
+ case 2:
+ if(separate_arrays)
+ source = prefix+"color_data";
+ IO::print("\tglColorPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
+ size, stride, source);
+ IO::print("\tglEnableClientState(GL_COLOR_ARRAY);\n");
+ break;
+ case 3:
+ if(separate_arrays)
+ source = prefix+"texcoord_data";
+ IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
+ size, stride, source);
+ IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n");
+ break;
+ default:
+ if(kind<11)
+ {
+ if(separate_arrays)
+ source = format("%stexcoord%d_data", prefix, kind-3);
+ IO::print("\tglClientActiveTexture(GL_TEXTURE%d);\n", kind-3);
+ IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
+ size, stride, source);
+ IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n");
+ }
+ else
+ {
+ if(separate_arrays)
+ source = format("%sattrib%d_data", prefix, kind-11);
+ IO::print("\tglVertexAttribPointer(%d, %d, GL_FLOAT, GL_FALSE, %d*sizeof(float), %s);\n",
+ kind-11, size, stride, source);
+ IO::print("\tglEnableVertexAttribArray(%d);\n", kind-11);
+ }
+ break;
+ }
+ offset += size;
+ }
+ offset = 0;
+ for(list<GL::Batch>::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i)
+ {
+ string mode;
+ switch(i->get_type())
+ {
+ case GL_TRIANGLE_STRIP: mode = "GL_TRIANGLE_STRIP"; break;
+ case GL_TRIANGLES: mode = "GL_TRIANGLES"; break;
+ default: mode = format("%d", i->get_type()); break;
+ }
+ IO::print("\tglDrawElements(%s, %d, %s, %sindices+%d);\n", mode, i->size(), type[1], prefix, offset);
+ offset += i->size();
+ }
+ if(render_func)
+ {
+ IO::print("}\n\n");
+ IO::print("/* To render this object, #include this file and call %srender() */\n", prefix);
+ }
+ else
+ IO::print("*/\n");
+
+ return 0;
+}
--- /dev/null
+#include <cmath>
+#include <msp/core/application.h>
+#include <msp/core/getopt.h>
+#include <msp/fs/utils.h>
+#include <msp/graphics/simplewindow.h>
+#include <msp/gl/blend.h>
+#include <msp/gl/camera.h>
+#include <msp/gl/framebuffer.h>
+#include <msp/gl/light.h>
+#include <msp/gl/lighting.h>
+#include <msp/gl/mesh.h>
+#include <msp/gl/object.h>
+#include <msp/gl/tests.h>
+#include <msp/input/mouse.h>
+#include <msp/io/print.h>
+
+using namespace std;
+using namespace Msp;
+
+class Viewer: public RegisteredApplication<Viewer>
+{
+private:
+ Graphics::SimpleGLWindow window;
+ Input::Mouse mouse;
+ GL::Object *object;
+ GL::Mesh *mesh;
+ GL::Light light;
+ GL::Lighting lighting;
+ GL::Camera camera;
+ float yaw;
+ float pitch;
+ float distance;
+ float light_yaw;
+ float light_pitch;
+ unsigned dragging;
+
+public:
+ Viewer(int, char **);
+ ~Viewer();
+
+ virtual int main();
+private:
+ virtual void tick();
+
+ void button_press(unsigned);
+ void button_release(unsigned);
+ void axis_motion(unsigned, float, float);
+
+ void update_camera();
+ void update_light();
+};
+
+
+Viewer::Viewer(int argc, char **argv):
+ window(1024, 768, false),
+ mouse(window),
+ object(0),
+ mesh(0),
+ yaw(0),
+ pitch(0),
+ distance(10),
+ light_yaw(0),
+ light_pitch(0),
+ dragging(0)
+{
+ if(argc<2)
+ throw usage_error("Filename must be provided");
+
+ string fn = argv[1];
+ string ext = FS::extpart(fn);
+
+ if(ext==".mesh")
+ {
+ mesh = new GL::Mesh;
+ DataFile::load(*mesh, fn);
+ }
+ else if(ext==".object")
+ {
+ object = new GL::Object;
+ DataFile::load(*object, fn);
+ }
+ else
+ throw usage_error("Don't know how to view this file");
+
+ window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &Viewer::exit), 0));
+ mouse.signal_button_press.connect(sigc::mem_fun(this, &Viewer::button_press));
+ mouse.signal_button_release.connect(sigc::mem_fun(this, &Viewer::button_release));
+ mouse.signal_axis_motion.connect(sigc::mem_fun(this, &Viewer::axis_motion));
+
+ light.set_position(GL::Vector4(0, 0, 1, 0));
+ lighting.attach(0, light);
+
+ camera.set_up_direction(GL::Vector3(0, 0, 1));
+ update_camera();
+}
+
+Viewer::~Viewer()
+{
+ delete object;
+ delete mesh;
+}
+
+int Viewer::main()
+{
+ window.show();
+ return Application::main();
+}
+
+void Viewer::tick()
+{
+ window.tick();
+
+ GL::Framebuffer::system().clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT);
+
+ camera.apply();
+
+ GL::Bind bind_lighting(lighting);
+ GL::Bind bind_depth(GL::DepthTest::lequal());
+ GL::Bind bind_blend(GL::Blend::alpha());
+ if(object)
+ object->render();
+ else if(mesh)
+ mesh->draw();
+
+ window.swap_buffers();
+}
+
+void Viewer::button_press(unsigned btn)
+{
+ if(btn==1)
+ {
+ dragging = 1;
+ }
+ else if(btn==3)
+ {
+ dragging = 3;
+ axis_motion(0, 0, 0);
+ }
+ else if(btn==4)
+ {
+ distance *= 0.9;
+ update_camera();
+ }
+ else if(btn==5)
+ {
+ distance *= 1.1;
+ update_camera();
+ }
+}
+
+void Viewer::button_release(unsigned btn)
+{
+ if(btn==dragging)
+ dragging = 0;
+}
+
+void Viewer::axis_motion(unsigned axis, float, float delta)
+{
+ if(dragging==1)
+ {
+ float dx = (axis==0 ? delta : 0);
+ float dy = (axis==1 ? delta : 0);
+
+ yaw -= dx*M_PI*2;
+ while(yaw>M_PI)
+ yaw -= M_PI*2;
+ while(yaw<-M_PI)
+ yaw += M_PI*2;
+
+ pitch += dy*M_PI;
+ if(pitch>M_PI*0.49)
+ pitch = M_PI*0.49;
+ if(pitch<-M_PI*0.49)
+ pitch = -M_PI*0.49;
+
+ update_camera();
+ }
+ else if(dragging==3)
+ {
+ float x = mouse.get_axis_value(0);
+ float y = mouse.get_axis_value(1);
+
+ light_yaw = yaw+x*M_PI;
+ light_pitch = pitch-y*M_PI;
+
+ update_light();
+ }
+}
+
+void Viewer::update_camera()
+{
+ float cy = cos(yaw);
+ float sy = sin(yaw);
+ float cp = cos(pitch);
+ float sp = sin(pitch);
+ camera.set_position(GL::Vector3(-cy*cp*distance, -sy*cp*distance, -sp*distance));
+ camera.set_depth_clip(distance*0.02, distance*50);
+ camera.look_at(GL::Vector3(0, 0, 0));
+}
+
+void Viewer::update_light()
+{
+ float cy = cos(light_yaw);
+ float sy = sin(light_yaw);
+ float cp = cos(light_pitch);
+ float sp = sin(light_pitch);
+ light.set_position(GL::Vector4(-cy*cp, -sy*cp, -sp, 0));
+}
+++ /dev/null
-#include <cmath>
-#include <msp/core/application.h>
-#include <msp/core/getopt.h>
-#include <msp/fs/utils.h>
-#include <msp/graphics/simplewindow.h>
-#include <msp/gl/blend.h>
-#include <msp/gl/camera.h>
-#include <msp/gl/framebuffer.h>
-#include <msp/gl/light.h>
-#include <msp/gl/lighting.h>
-#include <msp/gl/mesh.h>
-#include <msp/gl/object.h>
-#include <msp/gl/tests.h>
-#include <msp/input/mouse.h>
-#include <msp/io/print.h>
-
-using namespace std;
-using namespace Msp;
-
-class Viewer: public RegisteredApplication<Viewer>
-{
-private:
- Graphics::SimpleGLWindow window;
- Input::Mouse mouse;
- GL::Object *object;
- GL::Mesh *mesh;
- GL::Light light;
- GL::Lighting lighting;
- GL::Camera camera;
- float yaw;
- float pitch;
- float distance;
- float light_yaw;
- float light_pitch;
- unsigned dragging;
-
-public:
- Viewer(int, char **);
- ~Viewer();
-
- virtual int main();
-private:
- virtual void tick();
-
- void button_press(unsigned);
- void button_release(unsigned);
- void axis_motion(unsigned, float, float);
-
- void update_camera();
- void update_light();
-};
-
-
-Viewer::Viewer(int argc, char **argv):
- window(1024, 768, false),
- mouse(window),
- object(0),
- mesh(0),
- yaw(0),
- pitch(0),
- distance(10),
- light_yaw(0),
- light_pitch(0),
- dragging(0)
-{
- if(argc<2)
- throw usage_error("Filename must be provided");
-
- string fn = argv[1];
- string ext = FS::extpart(fn);
-
- if(ext==".mesh")
- {
- mesh = new GL::Mesh;
- DataFile::load(*mesh, fn);
- }
- else if(ext==".object")
- {
- object = new GL::Object;
- DataFile::load(*object, fn);
- }
- else
- throw usage_error("Don't know how to view this file");
-
- window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &Viewer::exit), 0));
- mouse.signal_button_press.connect(sigc::mem_fun(this, &Viewer::button_press));
- mouse.signal_button_release.connect(sigc::mem_fun(this, &Viewer::button_release));
- mouse.signal_axis_motion.connect(sigc::mem_fun(this, &Viewer::axis_motion));
-
- light.set_position(GL::Vector4(0, 0, 1, 0));
- lighting.attach(0, light);
-
- camera.set_up_direction(GL::Vector3(0, 0, 1));
- update_camera();
-}
-
-Viewer::~Viewer()
-{
- delete object;
- delete mesh;
-}
-
-int Viewer::main()
-{
- window.show();
- return Application::main();
-}
-
-void Viewer::tick()
-{
- window.tick();
-
- GL::Framebuffer::system().clear(GL::COLOR_BUFFER_BIT|GL::DEPTH_BUFFER_BIT);
-
- camera.apply();
-
- GL::Bind bind_lighting(lighting);
- GL::Bind bind_depth(GL::DepthTest::lequal());
- GL::Bind bind_blend(GL::Blend::alpha());
- if(object)
- object->render();
- else if(mesh)
- mesh->draw();
-
- window.swap_buffers();
-}
-
-void Viewer::button_press(unsigned btn)
-{
- if(btn==1)
- {
- dragging = 1;
- }
- else if(btn==3)
- {
- dragging = 3;
- axis_motion(0, 0, 0);
- }
- else if(btn==4)
- {
- distance *= 0.9;
- update_camera();
- }
- else if(btn==5)
- {
- distance *= 1.1;
- update_camera();
- }
-}
-
-void Viewer::button_release(unsigned btn)
-{
- if(btn==dragging)
- dragging = 0;
-}
-
-void Viewer::axis_motion(unsigned axis, float, float delta)
-{
- if(dragging==1)
- {
- float dx = (axis==0 ? delta : 0);
- float dy = (axis==1 ? delta : 0);
-
- yaw -= dx*M_PI*2;
- while(yaw>M_PI)
- yaw -= M_PI*2;
- while(yaw<-M_PI)
- yaw += M_PI*2;
-
- pitch += dy*M_PI;
- if(pitch>M_PI*0.49)
- pitch = M_PI*0.49;
- if(pitch<-M_PI*0.49)
- pitch = -M_PI*0.49;
-
- update_camera();
- }
- else if(dragging==3)
- {
- float x = mouse.get_axis_value(0);
- float y = mouse.get_axis_value(1);
-
- light_yaw = yaw+x*M_PI;
- light_pitch = pitch-y*M_PI;
-
- update_light();
- }
-}
-
-void Viewer::update_camera()
-{
- float cy = cos(yaw);
- float sy = sin(yaw);
- float cp = cos(pitch);
- float sp = sin(pitch);
- camera.set_position(GL::Vector3(-cy*cp*distance, -sy*cp*distance, -sp*distance));
- camera.set_depth_clip(distance*0.02, distance*50);
- camera.look_at(GL::Vector3(0, 0, 0));
-}
-
-void Viewer::update_light()
-{
- float cy = cos(light_yaw);
- float sy = sin(light_yaw);
- float cp = cos(light_pitch);
- float sp = sin(light_pitch);
- light.set_position(GL::Vector4(-cy*cp, -sy*cp, -sp, 0));
-}