compression functions; fixed texture seams
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 13 Jul 2011 06:39:05 +0000 (00:39 -0600)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 13 Jul 2011 06:39:05 +0000 (00:39 -0600)
15 files changed:
data/textures/BigExplosion.png
data/textures/Bonuses.png
data/textures/Building.png
data/textures/Particles.png
data/textures/TowerBlock1.png
data/textures/Trees.png
src/moof/compression.cc [new file with mode: 0644]
src/moof/compression.hh [new file with mode: 0644]
src/moof/debug.hh
src/moof/image.cc
src/moof/image.hh
src/moof/mesh.cc
src/moof/mesh.hh
src/moof/video.cc
src/moof/video.hh

index 7681d1bfd4a21a003c1e199360c6719655e08f48..f02f001e016947ecae3baf5f4ae8ef598ba26ebc 100644 (file)
Binary files a/data/textures/BigExplosion.png and b/data/textures/BigExplosion.png differ
index 5fc78c91bd51adfadf6f215ce8baa2024b3534f4..99a646e4f77913889a00af59079647347e5d0fa6 100644 (file)
Binary files a/data/textures/Bonuses.png and b/data/textures/Bonuses.png differ
index 1965bd11551ff2103d8b46fb79a2e14c4c37ad61..50ad4c7060f05308438339b6eb4da841faeffb35 100644 (file)
Binary files a/data/textures/Building.png and b/data/textures/Building.png differ
index bcc011c449e1dc8d333d6f53a8918ef83e227c07..1d430ccb1b4437bda36119db34792bdada7ed3bb 100644 (file)
Binary files a/data/textures/Particles.png and b/data/textures/Particles.png differ
index 4bb9b3594654eea13c60e0fe2fc3a07baca41c82..a920f2c517b048a8381f175c692b250176b56a3a 100644 (file)
Binary files a/data/textures/TowerBlock1.png and b/data/textures/TowerBlock1.png differ
index f64646fce5e5f613a8bd9d570976b26bfd92f6bb..f89a8c1dd60541489b3dd2e9e70bf662fbbc1e9d 100644 (file)
Binary files a/data/textures/Trees.png and b/data/textures/Trees.png differ
diff --git a/src/moof/compression.cc b/src/moof/compression.cc
new file mode 100644 (file)
index 0000000..6362fc0
--- /dev/null
@@ -0,0 +1,111 @@
+
+/*]  Copyright (c) 2009-2011, Charles McGarvey  [*****************************
+**]  All rights reserved.
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+*****************************************************************************/
+
+#include <iostream>
+#include <stdexcept>
+#include <zlib.h>
+
+#include "compression.hh"
+
+#define ZLIB_BUF_SIZE          262114
+
+
+namespace moof {
+
+
+void inflate(std::istream& in, std::ostream& out)
+{
+       char inbuf[ZLIB_BUF_SIZE];
+       char outbuf[ZLIB_BUF_SIZE];
+
+       z_stream zstream;
+
+       zstream.zalloc          = Z_NULL;
+       zstream.zfree           = Z_NULL;
+       zstream.opaque          = Z_NULL;
+       zstream.avail_in        = 0;
+       zstream.next_in         = Z_NULL;
+       
+       int result = inflateInit2(&zstream, 32 + MAX_WBITS);
+       if (result != Z_OK) throw std::runtime_error("zlib init error");
+
+       do {
+               in.read(inbuf, sizeof(inbuf));
+               zstream.next_in = (Bytef*)inbuf;
+               zstream.avail_in = in.gcount();
+
+               if (zstream.avail_in == 0) break;
+
+               do {
+                       zstream.next_out = (Bytef*)outbuf;
+                       zstream.avail_out = sizeof(outbuf);
+
+                       result = inflate(&zstream, Z_NO_FLUSH);
+                       switch (result)
+                       {
+                       case Z_NEED_DICT:
+                       case Z_DATA_ERROR:
+                       case Z_MEM_ERROR:
+                               inflateEnd(&zstream);
+                               throw std::runtime_error("zlib inflate error");
+                       case Z_STREAM_ERROR:
+                               throw std::runtime_error("zlib stream error");
+                       }
+
+                       int inflated = sizeof(outbuf) - zstream.avail_out;
+                       out.write(outbuf, inflated);
+               }
+               while (zstream.avail_out == 0);
+       }
+       while(result != Z_STREAM_END);
+
+       inflateEnd(&zstream);
+}
+
+void inflate(const char* in, size_t size, std::ostream& out)
+{
+       char buf[ZLIB_BUF_SIZE];
+
+       z_stream zstream;
+       zstream.zalloc          = Z_NULL;
+       zstream.zfree           = Z_NULL;
+       zstream.opaque          = Z_NULL;
+       zstream.avail_in        = size;
+       zstream.next_in         = (Bytef*)in;
+       
+       int result = inflateInit2(&zstream, 32 + MAX_WBITS);
+       if (result != Z_OK) throw std::runtime_error("zlib init error");
+
+       do {
+               zstream.next_out = (Bytef*)buf;
+               zstream.avail_out = sizeof(buf);
+
+               result = inflate(&zstream, Z_NO_FLUSH);
+               switch (result)
+               {
+               case Z_NEED_DICT:
+               case Z_DATA_ERROR:
+               case Z_MEM_ERROR:
+                       inflateEnd(&zstream);
+                       throw std::runtime_error("zlib inflate error");
+               case Z_STREAM_ERROR:
+                       throw std::runtime_error("zlib stream error");
+               }
+
+               size_t inflated = sizeof(buf) - zstream.avail_out;
+               out.write(buf, inflated);
+       }
+       while (zstream.avail_out == 0);
+
+       inflateEnd(&zstream);
+}
+
+
+} // namespace moof
+
diff --git a/src/moof/compression.hh b/src/moof/compression.hh
new file mode 100644 (file)
index 0000000..b726088
--- /dev/null
@@ -0,0 +1,26 @@
+
+/*]  Copyright (c) 2009-2011, Charles McGarvey  [*****************************
+**]  All rights reserved.
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+*****************************************************************************/
+
+#ifndef _MOOF_COMPRESSION_H_
+#define _MOOF_COMPRESSION_H_
+
+#include <iostream>
+
+
+namespace moof {
+
+
+void inflate(std::istream& in, std::ostream& out);
+void inflate(const char* in, size_t size, std::ostream& out);
+
+
+} // namespace moof
+
+#endif // _MOOF_COMPRESSION_H_
+
index ef42dff33a7c22ab8d7e0b962aa2c19f526e98d7..a131ce950458ad2cc7d5f06fc41de5f729b6c889 100644 (file)
@@ -20,7 +20,9 @@
  * Debugging facilities.
  */
 
-
+#define STRINGIZE(X) #X
+#define QUOTE_MACRO(X) STRINGIZE(X)
+#define FILELINE __FILE__":"QUOTE_MACRO(__LINE__)
 
 #undef ASSERT
 #ifdef NDEBUG
@@ -31,9 +33,9 @@
  * assertion is false.
  * \param X test to perform.
  */
-#define ASSERT(X) if (!(X)) moof::log_error \
-       << "false assertion at " << __FILE__ << ":" << __LINE__ << ", " \
-       << #X, exit(1)
+#define ASSERT(X) \
+       if (!(X)) moof::log_error \
+       << "false assertion at " << FILELINE << ", " << #X, std::terminate()
 #endif
 
 
index 77b15c13903bead2a4bd05bc33e3a0081fbd2f91..c9c0638dba4adf6561eccdfc9ba941ab00f9f33c 100644 (file)
@@ -115,7 +115,7 @@ static SDL_Surface* load_png(const std::string& path, texture_attributes& attrib
        int             bpp;
 
        png_byte        colors;
-       png_bytepp      rows = 0;
+       png_bytepp      rows;
 
        png_textp       texts = 0;
        int             nutext_s;
@@ -170,53 +170,139 @@ static SDL_Surface* load_png(const std::string& path, texture_attributes& attrib
        png_read_update_info(png.context, png.info);
 
        bpp = png_get_bit_depth(png.context, png.info);
-       channels_ = png_get_channels(png.context, png.info);
-       depth_ = bpp * channels_;
+       int channels = png_get_channels(png.context, png.info);
+       int depth = bpp * channels;
 
        // read comments
        bool texture = false;
        png_get_text(png.context, png.info, &texts, &nutext_s);
        for (int i = 0; i < nutext_s; ++i)
        {
-               if (strncmp(texts[i].key, "X-Yoink-Texture", 11) == 0)
+               if (std::string(texts[i].key) == "X-Yoink-Texture")
                {
-                       set_texture_info(texts[i].text);
+                       attribs.init(texts[i].text);
                        texture = true;
                        break;
                }
        }
 
-       width_  = png_get_image_width(png.context, png.info);
-       height_ = png_get_image_height(png.context, png.info);
+       int width       = png_get_image_width(png.context, png.info);
+       int height      = png_get_image_height(png.context, png.info);
+       int pitch       = png_get_rowbytes(png.context, png.info);
+       char* pixels    = new char[height * pitch];
 
-       pitch_ = png_get_rowbytes(png.context, png.info);
-       pixels_ = new char[width_ * pitch_];
-
-       rows = new png_bytep[height_];
+       rows = new png_bytep[height];
        if (texture)
        {
                log_debug("texture detected; loading flipped");
-               for (int i = 0; i < height_; ++i)
+               for (int i = 0; i < height; ++i)
                {
-                       rows[height_-1-i] = (png_bytep)(pixels_ +
-                                       i * channels_ * width_);
+                       rows[height-1-i] = (png_bytep)(pixels +
+                                       i * channels * width);
                }
        }
        else
        {
                log_debug("no texture attributes found");
-               for (int i = 0; i < height_; ++i)
+               for (int i = 0; i < height; ++i)
                {
-                       rows[i] = (png_bytep)(pixels_ +
-                                       i * channels_ * width_);
+                       rows[i] = (png_bytep)(pixels +
+                                       i * channels * width);
                }
        }
 
        png_read_image(png.context, rows);
+       delete[] rows;
+
        png_read_end(png.context, 0);
 
-       // TODO leak
-       delete[] rows;
+       SDL_Surface* src = SDL_CreateRGBSurfaceFrom
+       (
+               pixels,
+               width,
+               height, 
+               depth,
+               pitch,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+               0x000000FF,
+               0x0000FF00,
+               0x00FF0000,
+               0xFF000000
+#else
+               0xFF000000,
+               0x00FF0000,
+               0x0000FF00,
+               0x000000FF
+#endif
+       );
+       if (!src) throw std::runtime_error(SDL_GetError());
+       return src;
+}
+
+static SDL_Surface* load_bmp(const std::string& path)
+{
+       return SDL_LoadBMP(path.c_str());
+}
+
+
+#if 0
+static void save_bmp(SDL_Surface* image, const std::string& path)
+{
+       if (SDL_SaveBMP(image, path.c_str()) != 0)
+               throw std::runtime_error(SDL_GetError());
+}
+
+
+static void destroy_context(SDL_Surface* context)
+{
+       if (context->flags & SDL_PREALLOC) delete[] (char*)context->pixels;
+       SDL_FreeSurface(context);
+}
+#endif
+
+
+image::image(const std::string& path) :
+       pixels_(0),
+       object_(0),
+       min_filter_(GL_NEAREST),
+       mag_filter_(GL_NEAREST),
+       tile_s_(1),
+       tile_t_(1),
+       wrap_s_(GL_CLAMP_TO_EDGE),
+       wrap_t_(GL_CLAMP_TO_EDGE)
+{
+       std::string ext = stlplus::extension_part(path);
+
+       SDL_Surface* context = 0;
+       if (ext == "png")
+       {
+               texture_attributes attribs;
+               context = load_png(path, attribs);
+               pixels_ = (char*)context->pixels;
+               width_ = context->w;
+               height_ = context->h;
+               depth_ = 32;
+               pitch_ = context->pitch;
+               channels_ = 4;
+               min_filter_ = attribs.min_filter;
+               mag_filter_ = attribs.mag_filter;
+               tile_s_ = attribs.tile_s;
+               tile_t_ = attribs.tile_t;
+               wrap_s_ = attribs.wrap_s;
+               wrap_t_ = attribs.wrap_t;
+               postprocess();
+       }
+       else if (ext == "bmp")
+       {
+               context = load_bmp(path);
+               pixels_ = (char*)context->pixels;
+               width_ = context->w;
+               height_ = context->h;
+               depth_ = 32;
+               pitch_ = context->pitch;
+               channels_ = 4;
+       }
+       // TODO leaking context
 }
 
 image::~image()
@@ -226,6 +312,189 @@ image::~image()
 }
 
 
+void image::postprocess()
+{
+       if (1 == tile_s_ && 1 == tile_t_) return;
+
+       SDL_Surface* src = SDL_CreateRGBSurfaceFrom
+       (
+               pixels_,
+               width_,
+               height_, 
+               depth_,
+               pitch_,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+               0x000000FF,
+               0x0000FF00,
+               0x00FF0000,
+               0xFF000000
+#else
+               0xFF000000,
+               0x00FF0000,
+               0x0000FF00,
+               0x000000FF
+#endif
+       );
+       SDL_Surface* dst = SDL_CreateRGBSurface(
+               SDL_SWSURFACE,
+               higher_power_of_two(width_),
+               higher_power_of_two(height_),
+               depth_,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+               0x000000FF,
+               0x0000FF00,
+               0x00FF0000,
+               0xFF000000
+#else
+               0xFF000000,
+               0x00FF0000,
+               0x0000FF00,
+               0x000000FF
+#endif
+       );
+       ASSERT(src && dst);
+
+       SDL_SetAlpha(src, 0, 128);
+       SDL_SetAlpha(dst, 0, 128);
+
+       int src_tilew = src->w / tile_s_;
+       int src_tileh = src->h / tile_t_;
+       int dst_tilew = dst->w / tile_s_;
+       int dst_tileh = dst->h / tile_t_;
+
+       for (int t = 0; t < tile_t_; ++t) for (int s = 0; s < tile_s_; ++s)
+       {
+               SDL_Rect srcrect;
+               SDL_Rect dstrect;
+               srcrect.x = s * src_tilew;
+               srcrect.y = t * src_tileh;
+               srcrect.w = src_tilew;
+               srcrect.h = src_tileh;
+               dstrect.x = s * dst_tilew + (src_tilew / 2);
+               dstrect.y = t * dst_tileh + (src_tileh / 2);
+               log_warning("SRC", srcrect.x, srcrect.y, srcrect.w, srcrect.h);
+               log_warning("DST", dstrect.x, dstrect.y);
+               SDL_BlitSurface(src, &srcrect, dst, &dstrect);
+
+               srcrect.x = s * src_tilew;
+               srcrect.y = t * src_tileh;
+               srcrect.w = 1;
+               srcrect.h = src_tileh;
+               dstrect.y = t * dst_tileh + (src_tileh / 2);
+               for (int x = s * dst_tilew + (src_tilew / 2) - 1; s * dst_tilew <= x; --x)
+               {
+                       dstrect.x = x;
+                       SDL_BlitSurface(src, &srcrect, dst, &dstrect);
+               }
+
+               srcrect.x = (s + 1) * src_tilew - 1;
+               srcrect.y = t * src_tileh;
+               srcrect.w = 1;
+               srcrect.h = src_tileh;
+               dstrect.y = t * dst_tileh + (src_tileh / 2);
+               for (int x = (s + 1) * dst_tilew - (src_tilew / 2); x < (s + 1) * dst_tilew; ++x)
+               {
+                       dstrect.x = x;
+                       SDL_BlitSurface(src, &srcrect, dst, &dstrect);
+               }
+
+               srcrect.x = s * src_tilew;
+               srcrect.y = t * src_tileh;
+               srcrect.w = src_tilew;
+               srcrect.h = 1;
+               dstrect.x = s * dst_tilew + (src_tilew / 2);
+               for (int y = t * dst_tileh + (src_tileh / 2) - 1; t * dst_tileh <= y; --y)
+               {
+                       dstrect.y = y;
+                       SDL_BlitSurface(src, &srcrect, dst, &dstrect);
+               }
+
+               srcrect.x = s * src_tilew;
+               srcrect.y = (t + 1) * src_tileh - 1;
+               srcrect.w = src_tilew;
+               srcrect.h = 1;
+               dstrect.x = s * dst_tilew + (src_tilew / 2);
+               for (int y = (t + 1) * dst_tileh - (src_tileh / 2); y < (t + 1) * dst_tileh; ++y)
+               {
+                       dstrect.y = y;
+                       SDL_BlitSurface(src, &srcrect, dst, &dstrect);
+               }
+       }
+       SDL_FreeSurface(src);
+
+       char* pixels = new char[dst->w * dst->pitch];
+       SDL_Surface* finaldst = SDL_CreateRGBSurfaceFrom
+       (
+               pixels,
+               dst->w,
+               dst->h, 
+               depth_,
+               dst->pitch,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+               0x000000FF,
+               0x0000FF00,
+               0x00FF0000,
+               0xFF000000
+#else
+               0xFF000000,
+               0x00FF0000,
+               0x0000FF00,
+               0x000000FF
+#endif
+       );
+       SDL_BlitSurface(dst, 0, finaldst, 0);
+
+       //SDL_SaveBMP(dst, (stlplus::basename_part(path) + ".bmp").c_str());
+       SDL_FreeSurface(dst);
+
+       width_ = finaldst->w;
+       height_ = finaldst->h;
+       pitch_ = finaldst->pitch;
+
+       SDL_FreeSurface(finaldst);
+
+       delete[] pixels_;
+       pixels_ = pixels;
+}
+
+
+void image::fix_uv(std::vector<vector2>& p) const
+{
+       vector2 mid(SCALAR(0.0), SCALAR(0.0));
+       for (int i = 0; i < p.size(); ++i)
+       {
+               mid[0] += p[i][0];
+               mid[1] += p[i][1];
+       }
+       mid[0] /= p.size();
+       mid[1] /= p.size();
+       mid[0] *= tile_s_;
+       mid[1] *= tile_t_;
+       mid[0] = std::floor(mid[0]);
+       mid[1] = std::floor(mid[1]);
+       log_warning("midpoint:", mid);
+       scalar s = mid[0];
+       scalar t = mid[1];
+
+       scalar  src_width = width_ >> 1;
+       scalar  src_height = height_ >> 1;
+       int     src_tilew = src_width / tile_s_;
+       int     src_tileh = src_height / tile_t_;
+       int     dst_tilew = width_ / tile_s_;
+       int     dst_tileh = height_ / tile_t_;
+
+       for (int i = 0; i < p.size(); ++i)
+       {
+               //scalar s = p[i][0] * src_width;
+               scalar x = s * dst_tilew + (src_tilew / 2) + (p[i][0] * src_width - s * src_tilew);
+               p[i][0] = x / width_;
+               //scalar t = p[i][1] * src_height;
+               scalar y = t * dst_tileh + (src_tileh / 2) + (p[i][1] * src_height - t * src_tileh);;
+               p[i][1] = y / height_;
+       }
+}
+
+
 void image::set_as_icon() const
 {
        backend backend;
@@ -276,7 +545,7 @@ bool image::tile_coordinates(int index, scalar coords[8]) const
 
 void image::bind() const
 {
-       ASSERT(video::current() && "should have a video context set");
+       ASSERT(video::ready() && "should have a video context set");
 
        if (object_ == 0)
        {
@@ -291,7 +560,7 @@ void image::bind() const
 
 void image::reset_binding()
 {
-       ASSERT(video::current() && "should have a video context set");
+       ASSERT(video::ready() && "should have a video context set");
 
        glBindTexture(GL_TEXTURE_2D, 0);
        global_object_ = 0;
@@ -364,40 +633,8 @@ void image::set_properties() const
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_t_);
 }
 
-void image::set_texture_info(const std::string& info)
-{
-       script script;
-       log::import(script);
-
-       script::slot g = script.globals();
-       g.set_field("CLAMP",   GL_CLAMP);
-       g.set_field("REPEAT",  GL_REPEAT);
-       g.set_field("LINEAR",  GL_LINEAR);
-       g.set_field("NEAREST", GL_NEAREST);
-       g.set_field("LINEAR_MIPMAP_LINEAR",   GL_LINEAR_MIPMAP_LINEAR);
-       g.set_field("LINEAR_MIPMAP_NEAREST",  GL_LINEAR_MIPMAP_NEAREST);
-       g.set_field("NEAREST_MIPMAP_LINEAR",  GL_NEAREST_MIPMAP_LINEAR);
-       g.set_field("NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST);
-
-       if (script.do_string(info) != script::success)
-       {
-               std::string str;
-               script[-1].get(str);
-               log_warning(str);
-       }
-       else
-       {
-               log_info("loading texture information...");
-
-               script::slot globals = script.globals();
-               globals.get(min_filter_, "min_filter");
-               globals.get(mag_filter_, "mag_filter");
-               globals.get(tile_s_, "tile_s");
-               globals.get(tile_t_, "tile_t");
-               globals.get(wrap_s_, "wrap_s");
-               globals.get(wrap_t_, "wrap_t");
-       }
-}
+
+unsigned image::global_object_ = 0;
 
 
 } // namespace moof
index 4dee19fde9ffe4a2e9ec65d4ee3e28c8c587df6c..89a7faa1518dfeeb8245ae31ba8e9446e662a396 100644 (file)
@@ -59,11 +59,6 @@ public:
                return channels_;
        }
 
-       std::string comment() const
-       {
-               return comment_;
-       }
-
        const char* pixels() const
        {
                return pixels_;
@@ -76,26 +71,28 @@ public:
         * are indexed start with zero as the top-left tile and moving across,
         * then down.
         * \param index The tile index.
-        * \param coords An array of scalars where the texture coordinates will
-        * be stored after this call.  The first coordinate (u,v) will be in
-        * the first two places and so on until all four coordinates are
+        * \param coords An array of scalars where the texture coordinates
+        * will be stored after this call.  The first coordinate (u,v) will be
+        * in the first two places and so on until all four coordinates are
         * stored, therefore requiring enough room for an array of eight
-        * scalars.  The winding of the coordinates is always counter-clockwise
-        * (the GL default).
+        * scalars.  The winding of the coordinates is always
+        * counter-clockwise (the GL default).
         * \return True if index is valid, false otherwise.
         */
        bool tile_coordinates(int index, scalar coords[8]) const;
 
+       void fix_uv(std::vector<vector2>& p) const;
+
        void bind() const;
        static void reset_binding();
 
 private:
 
+       void postprocess();
        void upload_to_gl() const;
        void unload_from_gl() const;
        void context_recreated();
        void set_properties() const;
-       void set_texture_info(const std::string& info);
 
        char*                   pixels_;
 
@@ -108,8 +105,6 @@ private:
        int                     pitch_;
        int                     channels_;
 
-       std::string             comment_;
-
        unsigned                min_filter_;
        unsigned                mag_filter_;
        int                     tile_s_;
index 32550f7fcfb3361aff55ea7e2748c0c2c62531df..eac6ef9151a74fb25767613d6f6ce847f1fa3c4b 100644 (file)
 #include <boost/algorithm/string/trim.hpp>
 #include <zlib.h>
 
+#include "compression.hh"
 #include "debug.hh"
 #include "log.hh"
 #include "mesh.hh"
 #include "opengl.hh"
 
-// TODO: this file needs to be cleaned up
-
 #define AC3D_FORMAT_VERSION    0x0b
-#define ZLIB_BUF_SIZE          262114
 
 
 namespace moof {
 
 
 MOOF_REGISTER_RESOURCE(mesh, ac, models);
+MOOF_REGISTER_RESOURCE(mesh, acz, models);
+
 
 static std::string read_string(std::istream& stream)
 {
@@ -74,9 +74,9 @@ static int read_hex(std::istream& stream)
 
 static vector2 read_pair(std::istream& stream)
 {
-       vector2 triplet;
-       stream >> triplet[0] >> triplet[1];
-       return triplet;
+       vector2 pair;
+       stream >> pair[0] >> pair[1];
+       return pair;
 }
 
 static vector3 read_triplet(std::istream& stream)
@@ -94,74 +94,47 @@ static vector4 read_color(std::istream& stream)
        return color;
 }
 
-void mesh::import(std::istream& stream)
+
+static inline void throw_invalid_atom(const std::string& atom)
 {
-       std::string     atom;
-       object_ptr      obj;
-       std::stack<int> kids;
+       throw std::runtime_error("unexpected atom: " + atom);
+}
 
+
+void mesh::load(std::istream& stream)
+{
        // read and verify the AC3D header
-       {
-               char            magic[5];
-               unsigned        version = 0;
+       char            magic[5];
+       unsigned        version = 0;
 
-               stream.get(magic, sizeof(magic));
-               if (!stream || strncmp(magic, "AC3D", 4) != 0)
-               {
-                       throw std::runtime_error("invalid mesh header");
-               }
+       stream.get(magic, sizeof(magic));
+       if (!stream || strncmp(magic, "AC3D", 4) != 0)
+       {
+               throw std::runtime_error("invalid mesh header");
+       }
 
-               version = read_hex(stream);
-               if (version > AC3D_FORMAT_VERSION)
-               {
-                       throw std::runtime_error("wrong mesh file format version");
-               }
+       version = read_hex(stream);
+       if (version > AC3D_FORMAT_VERSION)
+       {
+               throw std::runtime_error("wrong mesh file format version");
        }
 
+       std::string     atom;
+       object_ptr      obj;
+       std::stack<int> kids;
+
        while (stream)
        {
                stream >> atom;
                if (!stream) break;
 
-               if (atom == "MATERIAL")
+               if (atom == "OBJECT")
                {
-                       materials_.push_back(material(read_string(stream)));
-
-                       stream >> atom;
-                       materials_.back().diffuse = read_color(stream);
-                       stream >> atom;
-                       materials_.back().ambient = read_color(stream);
-                       stream >> atom;
-                       materials_.back().emissive = read_color(stream);
-                       stream >> atom;
-                       materials_.back().specular = read_color(stream);
-
-                       stream >> atom >> materials_.back().shininess;
-                       stream >> atom >> materials_.back().diffuse[3];
-                       materials_.back().diffuse[3] = SCALAR(1.0) -
-                                                                                  materials_.back().diffuse[3];
+                       obj = load_object(stream, obj);
                }
-               else if (atom == "OBJECT")
+               else if (atom == "MATERIAL")
                {
-                       stream >> atom;
-                       if (atom != "world" && atom != "group" && atom != "poly")
-                       {
-                               throw std::runtime_error("unexpected object type " + atom);
-                       }
-
-                       object_ptr newObj = object::alloc(*this);
-
-                       if (obj)
-                       {
-                               obj->kids.push_back(newObj);
-                               newObj->parent = obj;
-                       }
-                       else
-                       {
-                               objects_.push_back(newObj);
-                       }
-
-                       obj = newObj;
+                       load_material(stream);
                }
                else if (atom == "name")
                {
@@ -171,7 +144,10 @@ void mesh::import(std::istream& stream)
                                object_ptr parent = obj->parent.lock();
                                if (parent) parent->kids_byname.insert(std::make_pair(obj->name, obj));
                        }
-                       else throw std::runtime_error("unexpected atom: " + atom);
+                       else
+                       {
+                               throw_invalid_atom(atom);
+                       }
                }
                else if (atom == "data")
                {
@@ -185,7 +161,7 @@ void mesh::import(std::istream& stream)
                else if (atom == "texrep")
                {
                        if (obj) obj->texrep = read_pair(stream);
-                       else throw std::runtime_error("unexpected atom: " + atom);
+                       else throw_invalid_atom(atom);
                }
                else if (atom == "rot")
                {
@@ -200,11 +176,11 @@ void mesh::import(std::istream& stream)
                else if (atom == "url")
                {
                        if (obj) std::getline(stream, obj->url);
-                       else throw std::runtime_error("unexpected atom: " + atom);
+                       else throw_invalid_atom(atom);
                }
                else if (atom == "numvert")
                {
-                       if (!obj) throw std::runtime_error("unexpected atom: " + atom);
+                       if (!obj) throw_invalid_atom(atom);
 
                        int numvert = 0;
                        stream >> numvert;
@@ -216,7 +192,7 @@ void mesh::import(std::istream& stream)
                }
                else if (atom == "numsurf")
                {
-                       if (!obj) throw std::runtime_error("unexpected atom: " + atom);
+                       if (!obj) throw_invalid_atom(atom);
 
                        int numsurf = 0;
                        stream >> numsurf;
@@ -224,119 +200,19 @@ void mesh::import(std::istream& stream)
                        for (int i = 0; i < numsurf; ++i)
                        {
                                stream >> atom;
-                               if (atom != "SURF") throw std::runtime_error("uh oh");
-
-                               read_hex(stream);
-
-                               int material = 0;
-                               stream >> atom;
-                               if (atom == "mat") stream >> material >> atom;
-
-                               if (atom != "refs")
-                               {
-                                       throw std::runtime_error("blaaaaaaaahhh!!");
-                               }
-
-                               int numrefs = 0;
-                               stream >> numrefs;
-                               ASSERT(numrefs >= 3);
-
-                               if ((int)obj->faces.size() <= material)
-                               {
-                                       obj->faces.resize(material + 1);
-                               }
-                               material_group& face = obj->faces[material];
-
-                               unsigned vert;
-                               stream >> vert;
-                               vector2 uv = read_pair(stream);
-                               if (vert < face.triangles_uv.size())
-                               {
-                                       if (uv != face.triangles_uv[vert])
-                                       {
-                                               obj->verts.push_back(obj->verts[vert]);
-                                               face.triangles_uv.resize(obj->verts.size());
-                                               vert = obj->verts.size() - 1;
-                                       }
-                               }
-                               else face.triangles_uv.resize(vert + 1);
-                               face.triangles_uv[vert] = uv;
-                               face.triangles.push_back(vert);
-
-                               unsigned first = vert;
-
-                               stream >> vert;
-                               uv = read_pair(stream);
-                               if (vert < face.triangles_uv.size())
-                               {
-                                       if (uv != face.triangles_uv[vert])
-                                       {
-                                               obj->verts.push_back(obj->verts[vert]);
-                                               face.triangles_uv.resize(obj->verts.size());
-                                               vert = obj->verts.size() - 1;
-                                       }
-                               }
-                               else face.triangles_uv.resize(vert + 1);
-                               face.triangles_uv[vert] = uv;
-                               face.triangles.push_back(vert);
-
-                               stream >> vert;
-                               uv = read_pair(stream);
-                               if (vert < face.triangles_uv.size())
-                               {
-                                       if (uv != face.triangles_uv[vert])
-                                       {
-                                               obj->verts.push_back(obj->verts[vert]);
-                                               face.triangles_uv.resize(obj->verts.size());
-                                               vert = obj->verts.size() - 1;
-                                       }
-                               }
-                               else face.triangles_uv.resize(vert + 1);
-                               face.triangles_uv[vert] = uv;
-                               face.triangles.push_back(vert);
-
-                               unsigned last = vert;
-
-                               for (int j = 3; j < numrefs; ++j)
-                               {
-                                       face.triangles.push_back(first);
-                                       face.triangles.push_back(last);
-
-                                       stream >> vert;
-                                       uv = read_pair(stream);
-                                       if (vert < face.triangles_uv.size())
-                                       {
-                                               if (uv != face.triangles_uv[vert])
-                                               {
-                                                       obj->verts.push_back(obj->verts[vert]);
-                                                       face.triangles_uv.resize(obj->verts.size());
-                                                       vert = obj->verts.size() - 1;
-                                               }
-                                       }
-                                       else face.triangles_uv.resize(vert + 1);
-                                       face.triangles_uv[vert] = uv;
-                                       face.triangles.push_back(vert);
-
-                                       last = face.triangles.back();
-                               }
+                               if (atom != "SURF") throw_invalid_atom(atom);
+                               load_surface(stream, obj);
                        }
+
                }
                else if (atom == "kids")
                {
-                       //while (0 < kids.size())
-                       //{
-                               //if (--kids.top() <= 0)
-                               //{
-                                       //ASSERT(obj && "should be an object");
-                                       //obj = obj->parent;
-                                       //kids.pop();
-                               //}
-                               //else break;
-                       //}
-
                        int numkids = 0;
                        stream >> numkids;
-                       if (0 < numkids) kids.push(numkids);
+                       if (0 < numkids)
+                       {
+                               kids.push(numkids);
+                       }
                        else
                        {
                                if (0 < kids.size() && 0 < --kids.top()) kids.pop();
@@ -347,29 +223,188 @@ void mesh::import(std::istream& stream)
        while (stream);
 }
 
-//unsigned mesh::read_vertex_line(std::istream& stream)
-//{
-       //unsigned vert;
-       //stream >> vert;
-       //vector2 uv = read_pair(stream);
-       //if (vert < face.triangles_uv.size())
-       //{
-               //if (uv != face.triangles_uv[vert])
-               //{
-                       //obj->verts.push_back(obj->verts[vert]);
-                       //face.triangles_uv.resize(obj->verts.size());
-                       //vert = obj->verts.size() - 1;
-               //}
-       //}
-       //else face.triangles_uv.resize(vert + 1);
-       //face.triangles_uv[vert] = uv;
-       //face.triangles.push_back(vert);
-//}
+
+void mesh::load_material(std::istream& stream)
+{
+       materials_.push_back(material(read_string(stream)));
+
+       std::string atom;
+       stream >> atom;
+       materials_.back().diffuse = read_color(stream);
+       stream >> atom;
+       materials_.back().ambient = read_color(stream);
+       stream >> atom;
+       materials_.back().emissive = read_color(stream);
+       stream >> atom;
+       materials_.back().specular = read_color(stream);
+
+       stream >> atom >> materials_.back().shininess;
+       stream >> atom >> materials_.back().diffuse[3];
+       materials_.back().diffuse[3] = SCALAR(1.0) - materials_.back().diffuse[3];
+}
+
+mesh::object_ptr mesh::load_object(std::istream& stream, object_ptr parent)
+{
+       std::string atom;
+       stream >> atom;
+       if (atom != "world" && atom != "group" && atom != "poly")
+       {
+               throw_invalid_atom(atom);
+       }
+
+       object_ptr obj = object::alloc(*this);
+
+       if (parent)
+       {
+               parent->kids.push_back(obj);
+               obj->parent = parent;
+       }
+       else
+       {
+               objects_.push_back(obj);
+       }
+
+       return obj;
+}
+
+void mesh::load_surface(std::istream& stream, object_ptr obj)
+{
+       std::string atom;
+       read_hex(stream);
+
+       int material = 0;
+       stream >> atom;
+       if (atom == "mat") stream >> material >> atom;
+       if (atom != "refs") throw_invalid_atom(atom);
+
+       int numrefs = 0;
+       stream >> numrefs;
+       ASSERT(numrefs >= 3);
+
+       if ((int)obj->faces.size() <= material) obj->faces.resize(material + 1);
+       material_group& face = obj->faces[material];
+
+       std::vector<unsigned>   verts(numrefs);
+       std::vector<vector2>    uv(numrefs);
+
+       for (int i = 0; i < numrefs; ++i)
+       {
+               stream >> verts[i];
+               uv[i] = read_pair(stream);
+       }
+
+       // translate texture coordinates
+       if (obj->texture) obj->texture->fix_uv(uv);
+       // TODO why isn't texture always defined at this point?
+
+       for (int i = 0; i < numrefs; ++i)
+       {
+               scalar  vert = verts[i];
+               vector2 texcoord = uv[i];
+               if (vert < face.triangles_uv.size())
+               {
+                       if (texcoord != face.triangles_uv[vert])
+                       {
+                               obj->verts.push_back(obj->verts[vert]);
+                               face.triangles_uv.resize(obj->verts.size());
+                               vert = obj->verts.size() - 1;
+                       }
+               }
+               else face.triangles_uv.resize(vert + 1);
+               face.triangles_uv[vert] = texcoord;
+               verts[i] = vert;
+       }
+
+       face.triangles.push_back(verts[0]);
+       face.triangles.push_back(verts[1]);
+       face.triangles.push_back(verts[2]);
+       for (int i = 3; i < numrefs; ++i)
+       {
+               face.triangles.push_back(verts[0]);
+               face.triangles.push_back(verts[i-1]);
+               face.triangles.push_back(verts[i]);
+       }
+
+#if 0
+       unsigned vert;
+       stream >> vert;
+       vector2 uv = read_pair(stream);
+       if (vert < face.triangles_uv.size())
+       {
+               if (uv != face.triangles_uv[vert])
+               {
+                       obj->verts.push_back(obj->verts[vert]);
+                       face.triangles_uv.resize(obj->verts.size());
+                       vert = obj->verts.size() - 1;
+               }
+       }
+       else face.triangles_uv.resize(vert + 1);
+       face.triangles_uv[vert] = uv;
+       face.triangles.push_back(vert);
+
+       unsigned first = vert;
+
+       stream >> vert;
+       uv = read_pair(stream);
+       if (vert < face.triangles_uv.size())
+       {
+               if (uv != face.triangles_uv[vert])
+               {
+                       obj->verts.push_back(obj->verts[vert]);
+                       face.triangles_uv.resize(obj->verts.size());
+                       vert = obj->verts.size() - 1;
+               }
+       }
+       else face.triangles_uv.resize(vert + 1);
+       face.triangles_uv[vert] = uv;
+       face.triangles.push_back(vert);
+
+       stream >> vert;
+       uv = read_pair(stream);
+       if (vert < face.triangles_uv.size())
+       {
+               if (uv != face.triangles_uv[vert])
+               {
+                       obj->verts.push_back(obj->verts[vert]);
+                       face.triangles_uv.resize(obj->verts.size());
+                       vert = obj->verts.size() - 1;
+               }
+       }
+       else face.triangles_uv.resize(vert + 1);
+       face.triangles_uv[vert] = uv;
+       face.triangles.push_back(vert);
+
+       unsigned last = vert;
+
+       for (int j = 3; j < numrefs; ++j)
+       {
+               face.triangles.push_back(first);
+               face.triangles.push_back(last);
+
+               stream >> vert;
+               uv = read_pair(stream);
+               if (vert < face.triangles_uv.size())
+               {
+                       if (uv != face.triangles_uv[vert])
+                       {
+                               obj->verts.push_back(obj->verts[vert]);
+                               face.triangles_uv.resize(obj->verts.size());
+                               vert = obj->verts.size() - 1;
+                       }
+               }
+               else face.triangles_uv.resize(vert + 1);
+               face.triangles_uv[vert] = uv;
+               face.triangles.push_back(vert);
+
+               last = face.triangles.back();
+       }
+#endif
+}
+
 
 mesh::mesh(const std::string& path)
 {
-       std::ifstream file(path.c_str(), std::ifstream::in |
-                       std::ifstream::binary);
+       std::ifstream file(path.c_str(), std::ios::binary);
        if (!file) throw std::runtime_error("cannot find mesh file");
 
        // if we can read the header, the file isn't compressed
@@ -379,61 +414,15 @@ mesh::mesh(const std::string& path)
        {
                log_info("text mesh detected");
                file.seekg(std::ios::beg);
-               import(file);
+               load(file);
        }
        else
        {
-               log_info("compressed mesh detected");
+               log_info("decompressing mesh...");
                file.seekg(std::ios::beg);
-
                std::stringstream stream;
-               char in[ZLIB_BUF_SIZE];
-               char out[ZLIB_BUF_SIZE];
-
-               z_stream zstream;
-
-               zstream.zalloc = Z_NULL;
-               zstream.zfree = Z_NULL;
-               zstream.opaque = Z_NULL;
-               zstream.avail_in = 0;
-               zstream.next_in = Z_NULL;
-               
-               int result = inflateInit2(&zstream, 32+MAX_WBITS);
-               if (result != Z_OK)
-                       throw std::runtime_error("zlib init error");
-
-               do {
-                       file.read(in, sizeof(in));
-                       zstream.next_in = (Bytef*)in;
-                       zstream.avail_in = file.gcount();
-
-                       if (zstream.avail_in == 0) break;
-
-                       do {
-                               zstream.next_out = (Bytef*)out;
-                               zstream.avail_out = sizeof(out);
-
-                               result = inflate(&zstream, Z_NO_FLUSH);
-                               switch (result)
-                               {
-                               case Z_NEED_DICT:
-                               case Z_DATA_ERROR:
-                               case Z_MEM_ERROR:
-                                       inflateEnd(&zstream);
-                                       throw std::runtime_error("zlib inflate error");
-                               case Z_STREAM_ERROR:
-                                       throw std::runtime_error("zlib stream error");
-                               }
-
-                               int inflated = sizeof(out) - zstream.avail_out;
-                               stream.write(out, inflated);
-                       }
-                       while (zstream.avail_out == 0);
-               }
-               while(result != Z_STREAM_END);
-
-               inflateEnd(&zstream);
-               import(stream);
+               inflate(file, stream);
+               load(stream);
        }
 }
 
@@ -465,6 +454,7 @@ void mesh::set_material(const material& material) const
        glMaterial(GL_FRONT, GL_SHININESS, material.shininess);
 }
 
+
 void mesh::object::draw(scalar alpha, bool recurse) const
 {
        glVertexPointer(verts);
@@ -499,23 +489,6 @@ void mesh::object::draw(scalar alpha, bool recurse) const
        }
 }
 
-//class mesh_resource_loader
-//{
-//public:
-       
-       //mesh_resource_loader()
-       //{
-               //resource::register_type<mesh>("ac", "models");
-       //}
-
-       //~mesh_resource_loader()
-       //{
-               //resource::unregister_type("ac");
-       //}
-//};
-
-//static mesh_resource_loader loader;
-
 
 } // namespace moof
 
index 3f0dc24a6dc78c319be23ed521787a625a16e2da..5c9c34399f6be0bfd1223da75539463495851fb6 100644 (file)
@@ -114,7 +114,11 @@ public:
 
 private:
 
-       void import(std::istream& stream);
+       void load(std::istream& stream);
+
+       void load_material(std::istream& stream);
+       object_ptr load_object(std::istream& stream, object_ptr parent);
+       void load_surface(std::istream& stream, object_ptr obj);
        
        std::vector<material>   materials_;
        std::vector<object_ptr> objects_;
index 30de984d8a9ecc84644ae273db9cfba132c5ec9e..c4e8fd855e9c1f2f597d495eeda6ef100adeaea7 100644 (file)
@@ -97,9 +97,9 @@ void video::set_opengl_attributes()
        SDL_GL_SetAttribute(SDL_GL_STEREO,
                        attributes_.is_stereo);
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS,
-                       attributes_.multisample_buffers);
+                       0 < attributes_.multisamples);
        SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES,
-                       attributes_.multisample_samples);
+                       attributes_.multisamples);
        SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL,
                        attributes_.is_swap_control);
        SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL,
@@ -124,7 +124,7 @@ void video::mode(const int mode[3])
                if (context_) SDL_FreeSurface(context_);
 
                context_ = SDL_SetVideoMode(mode[0], mode[1], mode[2],
-                               flags_);
+                               SDL_OPENGL | flags_);
 
                if (context_)
                {
@@ -139,7 +139,7 @@ void video::mode(const int mode[3])
                }
                else
                {
-                       throw std::runtime_error("bad video mode attempted");
+                       throw std::runtime_error(SDL_GetError());
                }
        }
 }
@@ -322,8 +322,7 @@ video::attributes::attributes(const settings& settings)
        if (accum.size() > 3) accumulator_buffer[3] = accum[3];
 
        settings.get("stereo", is_stereo);
-       settings.get("multiesamplebuffers", multisample_buffers);
-       settings.get("multiesamplesamples", multisample_samples);
+       settings.get("multisamples", multisamples);
        settings.get("swapcontrol", is_swap_control);
        settings.get("hardwareonly", is_hardware_only);
 
@@ -380,8 +379,7 @@ void video::attributes::init()
        accumulator_buffer[2] = 0;
        accumulator_buffer[3] = 0;
        is_stereo = false;
-       multisample_buffers = 0;
-       multisample_samples = 0;
+       multisamples = 0;
        is_swap_control = false;
        is_hardware_only = false;
        mode[0] = 640;
index 9ec795f0f0ed1c4312f486e676f9d2703743990d..1349b673e3bd9eeefac0f4322b21f51fa623902b 100644 (file)
@@ -47,8 +47,7 @@ public:
                int     stencil_buffer;
                int     accumulator_buffer[4];  // rgba
                bool    is_stereo;
-               int     multisample_buffers;
-               int     multisample_samples;
+               int     multisamples;
                bool    is_swap_control;
                bool    is_hardware_only;
                int     mode[3];                // width, height, bpp
@@ -118,7 +117,16 @@ public:
        /**
         * Get the current video context where draw commands are sent.
         */
-       static video* current()
+       static video& current()
+       {
+               return *current_;
+       }
+
+       /**
+        * Get whether or not a video context is in place and is ready to
+        * received drawing commands.
+        */
+       static bool ready()
        {
                return current_;
        }
This page took 0.066078 seconds and 4 git commands to generate.