]> git.saurik.com Git - wxWidgets.git/commitdiff
Applied patch [ 1355355 ] Replace GPLed code in penguin sample and add features
authorJulian Smart <julian@anthemion.co.uk>
Mon, 14 Nov 2005 17:38:24 +0000 (17:38 +0000)
committerJulian Smart <julian@anthemion.co.uk>
Mon, 14 Nov 2005 17:38:24 +0000 (17:38 +0000)
(with Unicode and scope mods)
By Sandro Sigala

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@36174 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

20 files changed:
build/bakefiles/make_dist.mk
distrib/msw/generic.rsp
distrib/msw/makefile.rsp
distrib/msw/vc.rsp
distrib/msw/wince.rsp
samples/opengl/penguin/Makefile.in
samples/opengl/penguin/dxfrenderer.cpp [new file with mode: 0644]
samples/opengl/penguin/dxfrenderer.h [new file with mode: 0644]
samples/opengl/penguin/lw.cpp [deleted file]
samples/opengl/penguin/lw.h [deleted file]
samples/opengl/penguin/makefile.bcc
samples/opengl/penguin/makefile.gcc
samples/opengl/penguin/makefile.vc
samples/opengl/penguin/makefile.wat
samples/opengl/penguin/penguin.bkl
samples/opengl/penguin/penguin.cpp
samples/opengl/penguin/penguin.dsp
samples/opengl/penguin/penguin.dxf.gz [new file with mode: 0644]
samples/opengl/penguin/penguin.h
samples/opengl/penguin/penguin.lwo [deleted file]

index 2b30839093ee42bb08be332af0b9def6355362da..7a2b140846e8d40f5fb4ff668c6e87bed5ddc16c 100644 (file)
@@ -855,7 +855,7 @@ SAMPLES_DIST: ALL_GUI_DIST
        $(CP_P) $(SAMPDIR)/opengl/penguin/*.cpp $(DISTDIR)/samples/opengl/penguin
        $(CP_P) $(SAMPDIR)/opengl/penguin/*.c $(DISTDIR)/samples/opengl/penguin
        $(CP_P) $(SAMPDIR)/opengl/penguin/*.h $(DISTDIR)/samples/opengl/penguin
-       $(CP_P) $(SAMPDIR)/opengl/penguin/*.lwo $(DISTDIR)/samples/opengl/penguin
+       $(CP_P) $(SAMPDIR)/opengl/penguin/*.dxf.gz $(DISTDIR)/samples/opengl/penguin
        mkdir $(DISTDIR)/samples/opengl/cube
        $(CP_P) $(SAMPDIR)/opengl/cube/Makefile.in $(DISTDIR)/samples/opengl/cube
        $(CP_P) $(SAMPDIR)/opengl/cube/makefile.unx $(DISTDIR)/samples/opengl/cube
index 3ac61eb3f471072a716f8b6fdfc2acb8ce81ba18..20771ab8543bb22c2ba207d337263e8cbb3fd3cb 100644 (file)
@@ -974,7 +974,7 @@ samples/opengl/penguin/*.xbm
 samples/opengl/penguin/*.xpm
 samples/opengl/penguin/*.pro
 samples/opengl/penguin/make*.*
-samples/opengl/penguin/penguin.lwo
+samples/opengl/penguin/penguin.dxf.gz
 samples/opengl/penguin/*.bkl
 
 samples/png/*.cpp
index d9206458f2844984d94ff07030f0cd3f2898fe17..fe1e06171155964291029a1653d2a9c2f92d7a68 100644 (file)
@@ -67,6 +67,7 @@ samples/propsize/Makefile.in
 samples/regtest/Makefile.in
 samples/render/Makefile.in
 samples/richedit/Makefile.in
+samples/richtext/Makefile.in
 samples/rotate/Makefile.in
 samples/sashtest/Makefile.in
 samples/scroll/Makefile.in
index 9465a870179a75aabf1535390278fa339249e008..9dd2531c71a8f3cb8a079045cb9f105164bd483a 100644 (file)
@@ -211,6 +211,9 @@ samples/render/*.dsw
 samples/richedit/*.dsp
 samples/richedit/*.dsw
 
+samples/richtext/*.dsp
+samples/richtext/*.dsw
+
 samples/rotate/rotate.dsp
 samples/rotate/rotate.dsw
 
index bb5d2dfea5c811c5c5e286b9f864028aff7480c5..28a9bac02cebb5972ee3767d006be0aa182a30e6 100644 (file)
@@ -194,6 +194,9 @@ samples/render/render_render.vcw
 samples/richedit/richedit.vcp
 samples/richedit/richedit.vcw
 
+samples/richtext/richtext.vcp
+samples/richtext/richtext.vcw
+
 samples/rotate/rotate.vcp
 samples/rotate/rotate.vcw
 
index b54aea29004b2ac40b0335de3ad08fcbd847077a..48f3922b7a13c04d2b35b7329d68ba7eb4a8559f 100644 (file)
@@ -52,7 +52,7 @@ PENGUIN_CXXFLAGS = -D__WX$(TOOLKIT)__ $(__WXUNIV_DEFINE_p) \
 PENGUIN_OBJECTS =  \
        $(__penguin_os2_lib_res) \
        penguin_penguin.o \
-       penguin_lw.o \
+       penguin_dxfrenderer.o \
        penguin_trackball.o \
        $(__penguin___win32rc)
 
@@ -187,7 +187,7 @@ penguin.app/Contents/PkgInfo: $(__penguin___depname) $(top_srcdir)/src/mac/carbo
 
 data: 
        @mkdir -p .
-       @for f in penguin.lwo; do \
+       @for f in penguin.dxf.gz; do \
        if test ! -f ./$$f -a ! -d ./$$f ; \
        then x=yep ; \
        else x=`find $(srcdir)/$$f -newer ./$$f -print` ; \
@@ -200,8 +200,8 @@ data:
 penguin_penguin.o: $(srcdir)/penguin.cpp
        $(CXXC) -c -o $@ $(PENGUIN_CXXFLAGS) $(srcdir)/penguin.cpp
 
-penguin_lw.o: $(srcdir)/lw.cpp
-       $(CXXC) -c -o $@ $(PENGUIN_CXXFLAGS) $(srcdir)/lw.cpp
+penguin_dxfrenderer.o: $(srcdir)/dxfrenderer.cpp
+       $(CXXC) -c -o $@ $(PENGUIN_CXXFLAGS) $(srcdir)/dxfrenderer.cpp
 
 penguin_trackball.o: $(srcdir)/trackball.c
        $(CCC) -c -o $@ $(PENGUIN_CFLAGS) $(srcdir)/trackball.c
diff --git a/samples/opengl/penguin/dxfrenderer.cpp b/samples/opengl/penguin/dxfrenderer.cpp
new file mode 100644 (file)
index 0000000..5d18667
--- /dev/null
@@ -0,0 +1,680 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        dxfrenderer.cpp
+// Purpose:     DXF reader and renderer
+// Author:      Sandro Sigala
+// Modified by:
+// Created:     2005-11-10
+// RCS-ID:      $Id$
+// Copyright:   (c) Sandro Sigala
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// For compilers that support precompilation, includes "wx/wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+#include "wx/wx.h"
+#endif
+
+#include "wx/wfstream.h"
+#include "wx/txtstrm.h"
+
+#if !wxUSE_GLCANVAS
+    #error "OpenGL required: set wxUSE_GLCANVAS to 1 and rebuild the library"
+#endif
+
+#ifdef __WXMAC__
+#  ifdef __DARWIN__
+#    include <OpenGL/glu.h>
+#  else
+#    include <glu.h>
+#  endif
+#else
+#  include <GL/glu.h>
+#endif
+
+#include "dxfrenderer.h"
+
+#include <wx/listimpl.cpp>
+WX_DEFINE_LIST(DXFEntityList);
+WX_DEFINE_LIST(DXFLayerList);
+
+// Conversion table from AutoCAD ACI colours to RGB values
+static const struct { unsigned char r, g, b; } aci_to_rgb[256] = {
+/*   0 */ 255, 255, 255,
+/*   1 */ 255,   0,   0,
+/*   2 */ 255, 255,   0,
+/*   3 */   0, 255,   0,
+/*   4 */   0, 255, 255,
+/*   5 */   0,   0, 255,
+/*   6 */ 255,   0, 255,
+/*   7 */ 255, 255, 255,
+/*   8 */ 128, 128, 128,
+/*   9 */ 192, 192, 192,
+/*  10 */ 255,   0,   0,
+/*  11 */ 255, 127, 127,
+/*  12 */ 204,   0,   0,
+/*  13 */ 204, 102, 102,
+/*  14 */ 153,   0,   0,
+/*  15 */ 153,  76,  76,
+/*  16 */ 127,   0,   0,
+/*  17 */ 127,  63,  63,
+/*  18 */  76,   0,   0,
+/*  19 */  76,  38,  38,
+/*  20 */ 255,  63,   0,
+/*  21 */ 255, 159, 127,
+/*  22 */ 204,  51,   0,
+/*  23 */ 204, 127, 102,
+/*  24 */ 153,  38,   0,
+/*  25 */ 153,  95,  76,
+/*  26 */ 127,  31,   0,
+/*  27 */ 127,  79,  63,
+/*  28 */  76,  19,   0,
+/*  29 */  76,  47,  38,
+/*  30 */ 255, 127,   0,
+/*  31 */ 255, 191, 127,
+/*  32 */ 204, 102,   0,
+/*  33 */ 204, 153, 102,
+/*  34 */ 153,  76,   0,
+/*  35 */ 153, 114,  76,
+/*  36 */ 127,  63,   0,
+/*  37 */ 127,  95,  63,
+/*  38 */  76,  38,   0,
+/*  39 */  76,  57,  38,
+/*  40 */ 255, 191,   0,
+/*  41 */ 255, 223, 127,
+/*  42 */ 204, 153,   0,
+/*  43 */ 204, 178, 102,
+/*  44 */ 153, 114,   0,
+/*  45 */ 153, 133,  76,
+/*  46 */ 127,  95,   0,
+/*  47 */ 127, 111,  63,
+/*  48 */  76,  57,   0,
+/*  49 */  76,  66,  38,
+/*  50 */ 255, 255,   0,
+/*  51 */ 255, 255, 127,
+/*  52 */ 204, 204,   0,
+/*  53 */ 204, 204, 102,
+/*  54 */ 153, 153,   0,
+/*  55 */ 153, 153,  76,
+/*  56 */ 127, 127,   0,
+/*  57 */ 127, 127,  63,
+/*  58 */  76,  76,   0,
+/*  59 */  76,  76,  38,
+/*  60 */ 191, 255,   0,
+/*  61 */ 223, 255, 127,
+/*  62 */ 153, 204,   0,
+/*  63 */ 178, 204, 102,
+/*  64 */ 114, 153,   0,
+/*  65 */ 133, 153,  76,
+/*  66 */  95, 127,   0,
+/*  67 */ 111, 127,  63,
+/*  68 */  57,  76,   0,
+/*  69 */  66,  76,  38,
+/*  70 */ 127, 255,   0,
+/*  71 */ 191, 255, 127,
+/*  72 */ 102, 204,   0,
+/*  73 */ 153, 204, 102,
+/*  74 */  76, 153,   0,
+/*  75 */ 114, 153,  76,
+/*  76 */  63, 127,   0,
+/*  77 */  95, 127,  63,
+/*  78 */  38,  76,   0,
+/*  79 */  57,  76,  38,
+/*  80 */  63, 255,   0,
+/*  81 */ 159, 255, 127,
+/*  82 */  51, 204,   0,
+/*  83 */ 127, 204, 102,
+/*  84 */  38, 153,   0,
+/*  85 */  95, 153,  76,
+/*  86 */  31, 127,   0,
+/*  87 */  79, 127,  63,
+/*  88 */  19,  76,   0,
+/*  89 */  47,  76,  38,
+/*  90 */   0, 255,   0,
+/*  91 */ 127, 255, 127,
+/*  92 */   0, 204,   0,
+/*  93 */ 102, 204, 102,
+/*  94 */   0, 153,   0,
+/*  95 */  76, 153,  76,
+/*  96 */   0, 127,   0,
+/*  97 */  63, 127,  63,
+/*  98 */   0,  76,   0,
+/*  99 */  38,  76,  38,
+/* 100 */   0, 255,  63,
+/* 101 */ 127, 255, 159,
+/* 102 */   0, 204,  51,
+/* 103 */ 102, 204, 127,
+/* 104 */   0, 153,  38,
+/* 105 */  76, 153,  95,
+/* 106 */   0, 127,  31,
+/* 107 */  63, 127,  79,
+/* 108 */   0,  76,  19,
+/* 109 */  38,  76,  47,
+/* 110 */   0, 255, 127,
+/* 111 */ 127, 255, 191,
+/* 112 */   0, 204, 102,
+/* 113 */ 102, 204, 153,
+/* 114 */   0, 153,  76,
+/* 115 */  76, 153, 114,
+/* 116 */   0, 127,  63,
+/* 117 */  63, 127,  95,
+/* 118 */   0,  76,  38,
+/* 119 */  38,  76,  57,
+/* 120 */   0, 255, 191,
+/* 121 */ 127, 255, 223,
+/* 122 */   0, 204, 153,
+/* 123 */ 102, 204, 178,
+/* 124 */   0, 153, 114,
+/* 125 */  76, 153, 133,
+/* 126 */   0, 127,  95,
+/* 127 */  63, 127, 111,
+/* 128 */   0,  76,  57,
+/* 129 */  38,  76,  66,
+/* 130 */   0, 255, 255,
+/* 131 */ 127, 255, 255,
+/* 132 */   0, 204, 204,
+/* 133 */ 102, 204, 204,
+/* 134 */   0, 153, 153,
+/* 135 */  76, 153, 153,
+/* 136 */   0, 127, 127,
+/* 137 */  63, 127, 127,
+/* 138 */   0,  76,  76,
+/* 139 */  38,  76,  76,
+/* 140 */   0, 191, 255,
+/* 141 */ 127, 223, 255,
+/* 142 */   0, 153, 204,
+/* 143 */ 102, 178, 204,
+/* 144 */   0, 114, 153,
+/* 145 */  76, 133, 153,
+/* 146 */   0,  95, 127,
+/* 147 */  63, 111, 127,
+/* 148 */   0,  57,  76,
+/* 149 */  38,  66,  76,
+/* 150 */   0, 127, 255,
+/* 151 */ 127, 191, 255,
+/* 152 */   0, 102, 204,
+/* 153 */ 102, 153, 204,
+/* 154 */   0,  76, 153,
+/* 155 */  76, 114, 153,
+/* 156 */   0,  63, 127,
+/* 157 */  63,  95, 127,
+/* 158 */   0,  38,  76,
+/* 159 */  38,  57,  76,
+/* 160 */   0,  63, 255,
+/* 161 */ 127, 159, 255,
+/* 162 */   0,  51, 204,
+/* 163 */ 102, 127, 204,
+/* 164 */   0,  38, 153,
+/* 165 */  76,  95, 153,
+/* 166 */   0,  31, 127,
+/* 167 */  63,  79, 127,
+/* 168 */   0,  19,  76,
+/* 169 */  38,  47,  76,
+/* 170 */   0,   0, 255,
+/* 171 */ 127, 127, 255,
+/* 172 */   0,   0, 204,
+/* 173 */ 102, 102, 204,
+/* 174 */   0,   0, 153,
+/* 175 */  76,  76, 153,
+/* 176 */   0,   0, 127,
+/* 177 */  63,  63, 127,
+/* 178 */   0,   0,  76,
+/* 179 */  38,  38,  76,
+/* 180 */  63,   0, 255,
+/* 181 */ 159, 127, 255,
+/* 182 */  51,   0, 204,
+/* 183 */ 127, 102, 204,
+/* 184 */  38,   0, 153,
+/* 185 */  95,  76, 153,
+/* 186 */  31,   0, 127,
+/* 187 */  79,  63, 127,
+/* 188 */  19,   0,  76,
+/* 189 */  47,  38,  76,
+/* 190 */ 127,   0, 255,
+/* 191 */ 191, 127, 255,
+/* 192 */ 102,   0, 204,
+/* 193 */ 153, 102, 204,
+/* 194 */  76,   0, 153,
+/* 195 */ 114,  76, 153,
+/* 196 */  63,   0, 127,
+/* 197 */  95,  63, 127,
+/* 198 */  38,   0,  76,
+/* 199 */  57,  38,  76,
+/* 200 */ 191,   0, 255,
+/* 201 */ 223, 127, 255,
+/* 202 */ 153,   0, 204,
+/* 203 */ 178, 102, 204,
+/* 204 */ 114,   0, 153,
+/* 205 */ 133,  76, 153,
+/* 206 */  95,   0, 127,
+/* 207 */ 111,  63, 127,
+/* 208 */  57,   0,  76,
+/* 209 */  66,  38,  76,
+/* 210 */ 255,   0, 255,
+/* 211 */ 255, 127, 255,
+/* 212 */ 204,   0, 204,
+/* 213 */ 204, 102, 204,
+/* 214 */ 153,   0, 153,
+/* 215 */ 153,  76, 153,
+/* 216 */ 127,   0, 127,
+/* 217 */ 127,  63, 127,
+/* 218 */  76,   0,  76,
+/* 219 */  76,  38,  76,
+/* 220 */ 255,   0, 191,
+/* 221 */ 255, 127, 223,
+/* 222 */ 204,   0, 153,
+/* 223 */ 204, 102, 178,
+/* 224 */ 153,   0, 114,
+/* 225 */ 153,  76, 133,
+/* 226 */ 127,   0,  95,
+/* 227 */ 127,  63, 111,
+/* 228 */  76,   0,  57,
+/* 229 */  76,  38,  66,
+/* 230 */ 255,   0, 127,
+/* 231 */ 255, 127, 191,
+/* 232 */ 204,   0, 102,
+/* 233 */ 204, 102, 153,
+/* 234 */ 153,   0,  76,
+/* 235 */ 153,  76, 114,
+/* 236 */ 127,   0,  63,
+/* 237 */ 127,  63,  95,
+/* 238 */  76,   0,  38,
+/* 239 */  76,  38,  57,
+/* 240 */ 255,   0,  63,
+/* 241 */ 255, 127, 159,
+/* 242 */ 204,   0,  51,
+/* 243 */ 204, 102, 127,
+/* 244 */ 153,   0,  38,
+/* 245 */ 153,  76,  95,
+/* 246 */ 127,   0,  31,
+/* 247 */ 127,  63,  79,
+/* 248 */  76,   0,  19,
+/* 249 */  76,  38,  47,
+/* 250 */  51,  51,  51,
+/* 251 */  91,  91,  91,
+/* 252 */ 132, 132, 132,
+/* 253 */ 173, 173, 173,
+/* 254 */ 214, 214, 214,
+/* 255 */ 255, 255, 255,
+};
+
+inline DXFVector Cross(const DXFVector& v1, const DXFVector& v2)
+{
+    return DXFVector(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
+}
+
+void DXFFace::CalculateNormal()
+{
+    DXFVector v01, v02;
+    v01.x = v0.x - v1.x;
+    v01.y = v0.y - v1.y;
+    v01.z = v0.z - v1.z;
+    v02.x = v0.x - v2.x;
+    v02.y = v0.y - v2.y;
+    v02.z = v0.z - v2.z;
+    n = Cross(v01, v02);
+    float mod = sqrt(n.x*n.x + n.y*n.y + n.z*n.z);
+    n.x /= mod;
+    n.y /= mod;
+    n.z /= mod;
+}
+
+// convert an AutoCAD ACI colour to wxWidgets RGB colour
+inline wxColour ACIColourToRGB(int col)
+{
+    wxASSERT(col >= 0 && col <= 255);
+    return wxColour(aci_to_rgb[col].r, aci_to_rgb[col].g, aci_to_rgb[col].b);
+}
+
+// DXFReader constructor
+DXFRenderer::DXFRenderer()
+{
+    m_loaded = false;
+}
+
+// DXFReader destructor
+DXFRenderer::~DXFRenderer()
+{
+    Clear();
+}
+
+// deallocate all the dynamic data
+void DXFRenderer::Clear()
+{
+    m_loaded = false;
+    {
+        for (DXFLayerList::Node *node = m_layers.GetFirst(); node; node = node->GetNext())
+        {
+            DXFLayer *current = node->GetData();
+            delete current;
+        }
+    }
+    m_layers.Clear();
+    {
+        for (DXFEntityList::Node *node = m_entities.GetFirst(); node; node = node->GetNext())
+        {
+            DXFEntity *current = node->GetData();
+            delete current;
+        }
+        m_entities.Clear();
+    }
+}
+
+int DXFRenderer::GetLayerColour(const wxString& layer) const
+{
+    for (DXFLayerList::Node *node = m_layers.GetFirst(); node; node = node->GetNext())
+    {
+        DXFLayer *current = node->GetData();
+        if (current->name == layer)
+            return current->colour;
+    }
+    return 7;   // white
+}
+
+// read two sequential lines
+inline void GetLines(wxTextInputStream& text, wxString& line1, wxString& line2)
+{
+    line1 = text.ReadLine().Trim().Trim(false);
+    line2 = text.ReadLine().Trim().Trim(false);
+}
+
+// parse header section: just skip everything
+bool DXFRenderer::ParseHeader(wxInputStream& stream)
+{
+    wxTextInputStream text(stream);
+    wxString line1, line2;
+    while (stream.CanRead())
+    {
+        GetLines(text, line1, line2);
+        if (line1 == wxT("0") && line2 == wxT("ENDSEC"))
+            return true;
+    }
+    return false;
+}
+
+// parse tables section: save layers name and colour
+bool DXFRenderer::ParseTables(wxInputStream& stream)
+{
+    wxTextInputStream text(stream);
+    wxString line1, line2;
+    bool inlayer=false;
+    DXFLayer layer;
+    while (stream.CanRead())
+    {
+        GetLines(text, line1, line2);
+        if (line1 == wxT("0") && inlayer)
+        {
+            // flush layer
+            if (!layer.name.IsEmpty() && layer.colour != -1)
+            {
+                DXFLayer *p = new DXFLayer;
+                p->name = layer.name;
+                p->colour = layer.colour;
+                m_layers.Append(p);
+            }
+            layer = DXFLayer();
+            inlayer = false;
+        }
+        if (line1 == wxT("0") && line2 == wxT("ENDSEC"))
+            return true;
+        else if (line1 == wxT("0") && line2 == wxT("LAYER"))
+            inlayer = true;
+        else if (inlayer)
+        {
+            if (line1 == wxT("2")) // layer name
+                layer.name = line2;
+            else if (line1 == wxT("62")) // ACI colour
+            {
+                long l;
+                line2.ToLong(&l);
+                layer.colour = l;
+            }
+        }
+    }
+    return false;
+}
+
+// parse entities section: save 3DFACE and LINE entities
+bool DXFRenderer::ParseEntities(wxInputStream& stream)
+{
+    wxTextInputStream text(stream);
+    wxString line1, line2;
+    int state = 0;  // 0: none, 1: 3DFACE, 2: LINE
+    DXFVector v[4];
+    int colour = -1;
+    wxString layer;
+    while (stream.CanRead())
+    {
+        GetLines(text, line1, line2);
+        if (line1 == wxT("0") && state > 0)
+        {
+            // flush entity
+            if (state == 1) // 3DFACE
+            {
+                DXFFace *p = new DXFFace;
+                p->v0 = v[0];
+                p->v1 = v[1];
+                p->v2 = v[2];
+                p->v3 = v[3];
+                p->CalculateNormal();
+                if (colour != -1)
+                    p->colour = colour;
+                else
+                    p->colour = GetLayerColour(layer);
+                m_entities.Append(p);
+                colour = -1; layer = wxEmptyString;
+                v[0] = v[1] = v[2] = v[3] = DXFVector();
+                state = 0;
+            }
+            else if (state == 2) // LINE
+            {
+                DXFLine *p = new DXFLine;
+                p->v0 = v[0];
+                p->v1 = v[1];
+                if (colour != -1)
+                    p->colour = colour;
+                else
+                    p->colour = GetLayerColour(layer);
+                m_entities.Append(p);
+                colour = -1; layer = wxEmptyString;
+                v[0] = v[1] = v[2] = v[3] = DXFVector();
+                state = 0;
+            }
+        }
+        if (line1 == wxT("0") && line2 == wxT("ENDSEC"))
+            return true;
+        else if (line1 == wxT("0") && line2 == wxT("3DFACE"))
+            state = 1;
+        else if (line1 == wxT("0") && line2 == wxT("LINE"))
+            state = 2;
+        else if (state > 0)
+        {
+            double d;
+            line2.ToDouble(&d);
+            if (line1 == wxT("10"))
+                v[0].x = d;
+            else if (line1 == wxT("20"))
+                v[0].y = d;
+            else if (line1 == wxT("30"))
+                v[0].z = d;
+            else if (line1 == wxT("11"))
+                v[1].x = d;
+            else if (line1 == wxT("21"))
+                v[1].y = d;
+            else if (line1 == wxT("31"))
+                v[1].z = d;
+            else if (line1 == wxT("12"))
+                v[2].x = d;
+            else if (line1 == wxT("22"))
+                v[2].y = d;
+            else if (line1 == wxT("32"))
+                v[2].z = d;
+            else if (line1 == wxT("13"))
+                v[3].x = d;
+            else if (line1 == wxT("23"))
+                v[3].y = d;
+            else if (line1 == wxT("33"))
+                v[3].z = d;
+            else if (line1 == wxT("8"))  // layer
+                layer = line2;
+            else if (line1 == wxT("62")) // colour
+            {
+                long l;
+                line2.ToLong(&l);
+                colour = l;
+            }
+        }
+    }
+    return false;
+}
+
+// parse and load a DXF file
+// currently pretty limited, but knows enought do handle 3DFACEs and LINEs
+bool DXFRenderer::Load(wxInputStream& stream)
+{
+    Clear();
+    wxTextInputStream text(stream);
+
+    wxString line1, line2;
+    while (stream.CanRead())
+    {
+        GetLines(text, line1, line2);
+        if (line1 == wxT("999")) // comment
+            continue;
+        else if (line1 == wxT("0") && line2 == wxT("SECTION"))
+        {
+            GetLines(text, line1, line2);
+            if (line1 == wxT("2"))
+            {
+                if (line2 == wxT("HEADER"))
+                {
+                    if (!ParseHeader(stream))
+                        return false;
+                }
+                else if (line2 == wxT("TABLES"))
+                { 
+                    if (!ParseTables(stream))
+                        return false;
+                }
+                else if (line2 == wxT("ENTITIES"))
+                {
+                    if (!ParseEntities(stream))
+                        return false;
+                }
+            }
+        }
+    }
+
+    NormalizeEntities();
+    m_loaded = true;
+    return true;
+}
+
+inline float mymin(float x, float y) { return x < y ? x : y; }
+inline float mymax(float x, float y) { return x > y ? x : y; }
+
+// Scale object boundings to [-5,5]
+void DXFRenderer::NormalizeEntities()
+{
+    // calculate current min and max boundings of object
+    DXFVector minv(10e20f, 10e20f, 10e20f);
+    DXFVector maxv(-10e20f, -10e20f, -10e20f);
+    for (DXFEntityList::Node *node = m_entities.GetFirst(); node; node = node->GetNext())
+    {
+        DXFEntity *p = node->GetData();
+        if (p->type == DXFEntity::Line)
+        {
+            DXFLine *line = (DXFLine *)p;
+            const DXFVector *v[2] = { &line->v0, &line->v1 };
+            for (int i = 0; i < 2; ++i)
+            {
+                minv.x = mymin(v[i]->x, minv.x);
+                minv.y = mymin(v[i]->y, minv.y);
+                minv.z = mymin(v[i]->z, minv.z);
+                maxv.x = mymax(v[i]->x, maxv.x);
+                maxv.y = mymax(v[i]->y, maxv.y);
+                maxv.z = mymax(v[i]->z, maxv.z);
+            }
+        } else if (p->type == DXFEntity::Face)
+        {
+            DXFFace *face = (DXFFace *)p;
+            const DXFVector *v[4] = { &face->v0, &face->v1, &face->v2, &face->v3 };
+            for (int i = 0; i < 4; ++i)
+            {
+                minv.x = mymin(v[i]->x, minv.x);
+                minv.y = mymin(v[i]->y, minv.y);
+                minv.z = mymin(v[i]->z, minv.z);
+                maxv.x = mymax(v[i]->x, maxv.x);
+                maxv.y = mymax(v[i]->y, maxv.y);
+                maxv.z = mymax(v[i]->z, maxv.z);
+            }
+       }
+    }
+
+    // rescale object down to [-5,5]
+    DXFVector span(maxv.x - minv.x, maxv.y - minv.y, maxv.z - minv.z);
+    float factor = mymin(mymin(10.0f / span.x, 10.0f / span.y), 10.0f / span.z);
+    for (DXFEntityList::Node *node2 = m_entities.GetFirst(); node2; node2 = node2->GetNext())
+    {
+        DXFEntity *p = node2->GetData();
+        if (p->type == DXFEntity::Line)
+        {
+            DXFLine *line = (DXFLine *)p;
+            DXFVector *v[2] = { &line->v0, &line->v1 };
+            for (int i = 0; i < 2; ++i)
+            {
+                v[i]->x -= minv.x + span.x/2; v[i]->x *= factor;
+                v[i]->y -= minv.y + span.y/2; v[i]->y *= factor;
+                v[i]->z -= minv.z + span.z/2; v[i]->z *= factor;
+            }
+        } else if (p->type == DXFEntity::Face)
+        {
+            DXFFace *face = (DXFFace *)p;
+            DXFVector *v[4] = { &face->v0, &face->v1, &face->v2, &face->v3 };
+            for (int i = 0; i < 4; ++i)
+            {
+                v[i]->x -= minv.x + span.x/2; v[i]->x *= factor;
+                v[i]->y -= minv.y + span.y/2; v[i]->y *= factor;
+                v[i]->z -= minv.z + span.z/2; v[i]->z *= factor;
+            }
+       }
+    }
+}
+
+// OpenGL renderer for DXF entities
+void DXFRenderer::Render() const
+{
+    if (!m_loaded)
+        return;
+
+    for (DXFEntityList::Node *node = m_entities.GetFirst(); node; node = node->GetNext())
+    {
+        DXFEntity *p = node->GetData();
+        wxColour c = ACIColourToRGB(p->colour);
+        if (p->type == DXFEntity::Line)
+        {
+            DXFLine *line = (DXFLine *)p;
+            glBegin(GL_LINES);
+            glColor3f(c.Red()/255.0,c.Green()/255.0,c.Blue()/255.0);
+            glVertex3f(line->v0.x, line->v0.y, line->v0.z);
+            glVertex3f(line->v1.x, line->v1.y, line->v1.z);
+            glEnd();
+        }
+        else if (p->type == DXFEntity::Face)
+        {
+            DXFFace *face = (DXFFace *)p;
+            glBegin(GL_TRIANGLES);
+            glColor3f(c.Red()/255.0,c.Green()/255.0,c.Blue()/255.0);
+            glNormal3f(face->n.x, face->n.y, face->n.z);
+            glVertex3f(face->v0.x, face->v0.y, face->v0.z);
+            glVertex3f(face->v1.x, face->v1.y, face->v1.z);
+            glVertex3f(face->v2.x, face->v2.y, face->v2.z);
+            glEnd();
+        }
+    }
+}
diff --git a/samples/opengl/penguin/dxfrenderer.h b/samples/opengl/penguin/dxfrenderer.h
new file mode 100644 (file)
index 0000000..0e803e6
--- /dev/null
@@ -0,0 +1,79 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        dxfrenderer.h
+// Purpose:     DXF reader and renderer
+// Author:      Sandro Sigala
+// Modified by:
+// Created:     2005-11-10
+// RCS-ID:      $Id$
+// Copyright:   (c) Sandro Sigala
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef _DXFRENDERER_H_
+#define _DXFRENDERER_H_
+
+struct DXFVector
+{
+    DXFVector() { x = y = z = 0.0f; }
+    DXFVector(float _x, float _y, float _z) { x = _x; y = _y; z = _z; }
+    float x, y, z;
+};
+
+struct DXFEntity
+{
+    enum Type { Line, Face } type;
+    int colour;
+};
+
+struct DXFLine: public DXFEntity
+{
+    DXFLine() { type = Line; }
+    DXFVector v0;
+    DXFVector v1;
+};
+
+struct DXFFace: public DXFEntity
+{
+    DXFFace() { type = Face; }
+    void CalculateNormal();
+    DXFVector v0;
+    DXFVector v1;
+    DXFVector v2;
+    DXFVector v3;
+    DXFVector n;       // normal
+};
+
+struct DXFLayer
+{
+    DXFLayer() { colour = -1; }
+    wxString name;
+    int colour;
+};
+
+WX_DECLARE_LIST(DXFEntity, DXFEntityList);
+WX_DECLARE_LIST(DXFLayer, DXFLayerList);
+
+class DXFRenderer
+{
+public:
+    DXFRenderer();
+    ~DXFRenderer();
+
+    void Clear();
+    bool Load(wxInputStream& stream);
+    bool IsOk() const { return m_loaded; }
+    void Render() const;
+
+private:
+    bool ParseHeader(wxInputStream& stream);
+    bool ParseTables(wxInputStream& stream);
+    bool ParseEntities(wxInputStream& stream);
+    int GetLayerColour(const wxString& layer) const;
+    void NormalizeEntities();
+
+    bool m_loaded;
+    DXFLayerList m_layers;
+    DXFEntityList m_entities;
+};
+
+#endif // !_DXFRENDERER_H_
diff --git a/samples/opengl/penguin/lw.cpp b/samples/opengl/penguin/lw.cpp
deleted file mode 100644 (file)
index 9b22020..0000000
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 1998 Janne Löf <jlof@mail.student.oulu.fi>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-// For compilers that support precompilation, includes "wx.h".
-#include "wx/wxprec.h"
-
-#ifdef __BORLANDC__
-#pragma hdrstop
-#endif
-
-#ifndef WX_PRECOMP
-#include "wx/wx.h"
-#endif
-
-#ifdef __WXMSW__
-#include <windows.h>
-#endif
-
-#include "lw.h"
-#include <stdlib.h>
-#include <stdio.h>
-
-#if wxUSE_GLCANVAS
-
-#define MK_ID(a,b,c,d) ((((wxUint32)(a))<<24)| \
-            (((wxUint32)(b))<<16)| \
-            (((wxUint32)(c))<< 8)| \
-            (((wxUint32)(d))    ))
-
-#define ID_FORM MK_ID('F','O','R','M')
-#define ID_LWOB MK_ID('L','W','O','B')
-#define ID_PNTS MK_ID('P','N','T','S')
-#define ID_SRFS MK_ID('S','R','F','S')
-#define ID_SURF MK_ID('S','U','R','F')
-#define ID_POLS MK_ID('P','O','L','S')
-#define ID_COLR MK_ID('C','O','L','R')
-
-static wxInt32 read_char(FILE *f)
-{
-  int c = fgetc(f);
-  return c;
-}
-
-static wxInt32 read_short(FILE *f)
-{
-    // the execution path was not always correct
-    // when using the direct evaluation in the return statement
-    wxInt32 first = read_char(f) ;
-    wxInt32 second = read_char(f) ;
-
-  return (first<<8) | second ;
-}
-
-static wxInt32 read_long(FILE *f)
-{
-    // the execution path was not always correct
-    // when using the direct evaluation in the return statement
-    wxInt32 first = read_char(f) ;
-    wxInt32 second = read_char(f) ;
-    wxInt32 third = read_char(f) ;
-    wxInt32 fourth = read_char(f) ;
-  return (first<<24) | (second<<16) | (third<<8) | fourth ;
-}
-
-static GLfloat read_float(FILE *f)
-{
-  wxInt32 x = read_long(f);
-  return *(GLfloat*)&x;
-}
-
-static int read_string(FILE *f, char *s)
-{
-  int c;
-  int cnt = 0;
-  do {
-    c = read_char(f);
-    if (cnt < LW_MAX_NAME_LEN)
-      s[cnt] = (char)c;
-    else
-      s[LW_MAX_NAME_LEN-1] = 0;
-    cnt++;
-  } while (c != 0);
-  /* if length of string (including \0) is odd skip another byte */
-  if (cnt%2) {
-    read_char(f);
-    cnt++;
-  }
-  return cnt;
-}
-
-static void read_srfs(FILE *f, int nbytes, lwObject *lwo)
-{
-  int guess_cnt = lwo->material_cnt;
-
-  while (nbytes > 0) {
-    lwMaterial *material;
-
-    /* allocate more memory for materials if needed */
-    if (guess_cnt <= lwo->material_cnt) {
-      guess_cnt += guess_cnt/2 + 4;
-      lwo->material = (lwMaterial*) realloc(lwo->material, sizeof(lwMaterial)*guess_cnt);
-    }
-    material = lwo->material + lwo->material_cnt++;
-
-    /* read name */
-    nbytes -= read_string(f,material->name);
-
-    /* defaults */
-    material->r = 0.7f;
-    material->g = 0.7f;
-    material->b = 0.7f;
-  }
-  lwo->material = (lwMaterial*) realloc(lwo->material, sizeof(lwMaterial)*lwo->material_cnt);
-}
-
-
-static void read_surf(FILE *f, int nbytes, lwObject *lwo)
-{
-  int i;
-  char name[LW_MAX_NAME_LEN];
-  lwMaterial *material = NULL;
-
-  /* read surface name */
-  nbytes -= read_string(f,name);
-
-  /* find material */
-  for (i=0; i< lwo->material_cnt; i++) {
-    if (strcmp(lwo->material[i].name,name) == 0) {
-      material = &lwo->material[i];
-      break;
-    }
-  }
-
-  /* read values */
-  while (nbytes > 0) {
-    int id = read_long(f);
-    int len = read_short(f);
-    nbytes -= 6 + len + (len%2);
-
-    switch (id) {
-    case ID_COLR:
-      material->r = read_char(f) / 255.0;
-      material->g = read_char(f) / 255.0;
-      material->b = read_char(f) / 255.0;
-      read_char(f); /* dummy */
-      break;
-    default:
-      fseek(f, len+(len%2), SEEK_CUR);
-    }
-  }
-}
-
-
-static void read_pols(FILE *f, int nbytes, lwObject *lwo)
-{
-  int guess_cnt = lwo->face_cnt;
-
-  while (nbytes > 0) {
-    lwFace *face;
-    int i;
-
-    /* allocate more memory for polygons if necessary */
-    if (guess_cnt <= lwo->face_cnt) {
-      guess_cnt += guess_cnt + 4;
-      lwo->face = (lwFace*) realloc((void*) lwo->face, sizeof(lwFace)*guess_cnt);
-    }
-    face = lwo->face + lwo->face_cnt++;
-
-    /* number of points in this face */
-    face->index_cnt = read_short(f);
-    nbytes -= 2;
-
-    /* allocate space for points */
-    face->index = (int*) calloc(sizeof(int)*face->index_cnt,1);
-
-    /* read points in */
-    for (i=0; i<face->index_cnt; i++) {
-      face->index[i] = read_short(f);
-      nbytes -= 2;
-    }
-
-    /* read surface material */
-    face->material = read_short(f);
-    nbytes -= 2;
-
-    /* skip over detail  polygons */
-    if (face->material < 0) {
-      int det_cnt;
-      face->material = -face->material;
-      det_cnt = read_short(f);
-      nbytes -= 2;
-      while (det_cnt-- > 0) {
-    int cnt = read_short(f);
-    fseek(f, cnt*2+2, SEEK_CUR);
-    nbytes -= cnt*2+2;
-      }
-    }
-    face->material -= 1;
-  }
-  /* readjust to true size */
-  lwo->face = (lwFace*) realloc(lwo->face, sizeof(lwFace)*lwo->face_cnt);
-}
-
-
-
-static void read_pnts(FILE *f, int nbytes, lwObject *lwo)
-{
-  int i;
-  lwo->vertex_cnt = nbytes / 12;
-  lwo->vertex = (float*) calloc(sizeof(GLfloat)*lwo->vertex_cnt*3, 1);
-  for (i=0; i<lwo->vertex_cnt; i++) {
-    lwo->vertex[i*3+0] = read_float(f);
-    lwo->vertex[i*3+1] = read_float(f);
-    lwo->vertex[i*3+2] = read_float(f);
-  }
-}
-
-
-
-
-
-
-bool lw_is_lwobject(const char *lw_file)
-{
-  FILE *f = fopen(lw_file, "rb");
-  if (f) {
-    wxInt32 form = read_long(f);
-    wxInt32 nlen = read_long(f);
-    wxInt32 lwob = read_long(f);
-    fclose(f);
-    if (form == ID_FORM && nlen != 0 && lwob == ID_LWOB)
-      return true;
-  }
-  return false;
-}
-
-
-lwObject *lw_object_read(const char *lw_file)
-{
-
-  /* open file */
-  FILE *f = fopen(lw_file, "rb");
-  if (f == NULL) {
-    return NULL;
-  }
-
-  /* check for headers */
-  if (read_long(f) != ID_FORM) {
-    fclose(f);
-    return NULL;
-  }
-
-  wxInt32 read_bytes = 0;
-
-  wxInt32 form_bytes = read_long(f);
-  read_bytes += 4;
-
-  if (read_long(f) != ID_LWOB) {
-    fclose(f);
-    return NULL;
-  }
-
-  /* create new lwObject */
-  lwObject *lw_object = (lwObject*) calloc(sizeof(lwObject),1);
-
-  /* read chunks */
-  while (read_bytes < form_bytes) {
-    wxInt32  id     = read_long(f);
-    wxInt32  nbytes = read_long(f);
-    read_bytes += 8 + nbytes + (nbytes%2);
-
-    switch (id) {
-    case ID_PNTS:
-      read_pnts(f, nbytes, lw_object);
-      break;
-    case ID_POLS:
-      read_pols(f, nbytes, lw_object);
-      break;
-    case ID_SRFS:
-      read_srfs(f, nbytes, lw_object);
-      break;
-    case ID_SURF:
-      read_surf(f, nbytes, lw_object);
-      break;
-    default:
-      fseek(f, nbytes + (nbytes%2), SEEK_CUR);
-    }
-  }
-
-  fclose(f);
-  return lw_object;
-}
-
-
-
-void lw_object_free(lwObject *lw_object)
-{
-  if (lw_object->face) {
-    int i;
-    for (i=0; i<lw_object->face_cnt; i++)
-      free(lw_object->face[i].index);
-    free(lw_object->face);
-  }
-  free(lw_object->material);
-  free(lw_object->vertex);
-  free(lw_object);
-}
-
-
-
-
-
-#define PX(i) (lw_object->vertex[face->index[i]*3+0])
-#define PY(i) (lw_object->vertex[face->index[i]*3+1])
-#define PZ(i) (lw_object->vertex[face->index[i]*3+2])
-void lw_object_show(const lwObject *lw_object)
-{
-  int i,j;
-  int prev_index_cnt = -1;
-  int prev_material  = -1;
-  GLfloat prev_nx = 0;
-  GLfloat prev_ny = 0;
-  GLfloat prev_nz = 0;
-
-  for (i=0; i<lw_object->face_cnt; i++) {
-    GLfloat ax,ay,az,bx,by,bz,nx,ny,nz,r;
-    const lwFace *face = lw_object->face+i;
-
-    /* ignore faces with less than 3 points */
-    if (face->index_cnt < 3)
-      continue;
-
-    /* calculate normal */
-    ax = PX(1) - PX(0);
-    ay = PY(1) - PY(0);
-    az = PZ(1) - PZ(0);
-
-    bx = PX(face->index_cnt-1) - PX(0);
-    by = PY(face->index_cnt-1) - PY(0);
-    bz = PZ(face->index_cnt-1) - PZ(0);
-
-    nx = ay * bz - az * by;
-    ny = az * bx - ax * bz;
-    nz = ax * by - ay * bx;
-
-    r = sqrt(nx*nx + ny*ny + nz*nz);
-    if (r < 0.000001) /* avoid division by zero */
-      continue;
-    nx /= r;
-    ny /= r;
-    nz /= r;
-
-    /* glBegin/glEnd */
-    if (prev_index_cnt != face->index_cnt || prev_index_cnt > 4) {
-      if (prev_index_cnt > 0) glEnd();
-      prev_index_cnt = face->index_cnt;
-      switch (face->index_cnt) {
-      case 3:
-    glBegin(GL_TRIANGLES);
-    break;
-      case 4:
-    glBegin(GL_QUADS);
-    break;
-      default:
-    glBegin(GL_POLYGON);
-      }
-    }
-
-    /* update material if necessary */
-    if (prev_material != face->material) {
-      prev_material = face->material;
-      glColor3f(lw_object->material[face->material].r,
-        lw_object->material[face->material].g,
-        lw_object->material[face->material].b);
-    }
-
-    /* update normal if necessary */
-    if (nx != prev_nx || ny != prev_ny || nz != prev_nz) {
-      prev_nx = nx;
-      prev_ny = ny;
-      prev_nz = nz;
-      glNormal3f(nx,ny,nz);
-    }
-
-    /* draw polygon/triangle/quad */
-    for (j=0; j<face->index_cnt; j++)
-      glVertex3f(PX(j),PY(j),PZ(j));
-
-  }
-
-  /* if glBegin was called call glEnd */
-  if (prev_index_cnt > 0)
-    glEnd();
-}
-
-
-GLfloat lw_object_radius(const lwObject *lwo)
-{
-  int i;
-  double max_radius = 0.0;
-
-  for (i=0; i<lwo->vertex_cnt; i++) {
-    GLfloat *v = &lwo->vertex[i*3];
-    double r = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
-    if (r > max_radius)
-      max_radius = r;
-  }
-  return sqrt(max_radius);
-}
-
-void lw_object_scale(lwObject *lwo, GLfloat scale)
-{
-  int i;
-
-  for (i=0; i<lwo->vertex_cnt; i++) {
-    lwo->vertex[i*3+0] *= scale;
-    lwo->vertex[i*3+1] *= scale;
-    lwo->vertex[i*3+2] *= scale;
-  }
-}
-
-#endif
-
diff --git a/samples/opengl/penguin/lw.h b/samples/opengl/penguin/lw.h
deleted file mode 100644 (file)
index 0a4ca38..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 1998 Janne Löf <jlof@mail.student.oulu.fi>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-#ifndef LW_H
-#define LW_H
-
-#ifdef __WXMAC__
-#  ifdef __DARWIN__
-#    include <OpenGL/glu.h>
-#  else
-#    include <glu.h>
-#  endif
-#else
-#  include <GL/glu.h>
-#endif
-
-#define LW_MAX_POINTS   200
-#define LW_MAX_NAME_LEN 500
-
-typedef struct {
-  char name[LW_MAX_NAME_LEN];
-  GLfloat r,g,b;
-} lwMaterial;
-
-typedef struct {
-  int material;         /* material of this face */
-  int index_cnt;        /* number of vertices */
-  int *index;           /* index to vertex */
-  float *texcoord;      /* u,v texture coordinates */
-} lwFace;
-
-typedef struct {
-  int face_cnt;
-  lwFace *face;
-
-  int material_cnt;
-  lwMaterial *material;
-
-  int vertex_cnt;
-  GLfloat *vertex;
-
-} lwObject;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if wxUSE_GLCANVAS
-bool       lw_is_lwobject(const char     *lw_file);
-lwObject *lw_object_read(const char     *lw_file);
-void      lw_object_free(      lwObject *lw_object);
-void      lw_object_show(const lwObject *lw_object);
-
-GLfloat   lw_object_radius(const lwObject *lw_object);
-void      lw_object_scale (lwObject *lw_object, GLfloat scale);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LW_H */
-
index d7ef2b8dced20f9098321757e4bd502214c759c5..f2c02cf4fc6603a54d0af4b8f7122b409d2fd62c 100644 (file)
@@ -41,7 +41,7 @@ PENGUIN_CXXFLAGS = $(__RUNTIME_LIBS_7) -I$(BCCDIR)\include $(__DEBUGINFO) \
        -DNOPCH $(CPPFLAGS) $(CXXFLAGS)
 PENGUIN_OBJECTS =  \
        $(OBJS)\penguin_penguin.obj \
-       $(OBJS)\penguin_lw.obj \
+       $(OBJS)\penguin_dxfrenderer.obj \
        $(OBJS)\penguin_trackball.obj
 
 ### Conditionally set variables: ###
@@ -232,12 +232,12 @@ $(OBJS)\penguin.exe: $(PENGUIN_OBJECTS)  $(OBJS)\penguin_penguin.res
 
 data: 
        if not exist $(OBJS) mkdir $(OBJS)
-       for %f in (penguin.lwo) do if not exist $(OBJS)\%f copy .\%f $(OBJS)
+       for %f in (penguin.dxf.gz) do if not exist $(OBJS)\%f copy .\%f $(OBJS)
 
 $(OBJS)\penguin_penguin.obj: .\penguin.cpp
        $(CXX) -q -c -P -o$@ $(PENGUIN_CXXFLAGS) $**
 
-$(OBJS)\penguin_lw.obj: .\lw.cpp
+$(OBJS)\penguin_dxfrenderer.obj: .\dxfrenderer.cpp
        $(CXX) -q -c -P -o$@ $(PENGUIN_CXXFLAGS) $**
 
 $(OBJS)\penguin_trackball.obj: .\trackball.c
index 679422d256e656e7f6c5ee9c8276f4ce1d860ab9..b7cec871bab6ad886c387d74b3c719b18b9872cb 100644 (file)
@@ -34,7 +34,7 @@ PENGUIN_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZEFLAG_2) $(__THREADSFLAG) \
        -Wno-ctor-dtor-privacy $(CPPFLAGS) $(CXXFLAGS)
 PENGUIN_OBJECTS =  \
        $(OBJS)\penguin_penguin.o \
-       $(OBJS)\penguin_lw.o \
+       $(OBJS)\penguin_dxfrenderer.o \
        $(OBJS)\penguin_trackball.o \
        $(OBJS)\penguin_penguin_rc.o
 
@@ -225,12 +225,12 @@ endif
 
 data: 
        if not exist $(OBJS) mkdir $(OBJS)
-       for %%f in (penguin.lwo) do if not exist $(OBJS)\%%f copy .\%%f $(OBJS)
+       for %%f in (penguin.dxf.gz) do if not exist $(OBJS)\%%f copy .\%%f $(OBJS)
 
 $(OBJS)\penguin_penguin.o: ./penguin.cpp
        $(CXX) -c -o $@ $(PENGUIN_CXXFLAGS) $(CPPDEPS) $<
 
-$(OBJS)\penguin_lw.o: ./lw.cpp
+$(OBJS)\penguin_dxfrenderer.o: ./dxfrenderer.cpp
        $(CXX) -c -o $@ $(PENGUIN_CXXFLAGS) $(CPPDEPS) $<
 
 $(OBJS)\penguin_trackball.o: ./trackball.c
index a0f51e19da59947387bb1898475ea6685b51212e..ee2bdd60399deb1dea1ad0eba52b9c45d57f8822 100644 (file)
@@ -35,7 +35,7 @@ PENGUIN_CXXFLAGS = /M$(__RUNTIME_LIBS_8)$(__DEBUGRUNTIME_3) /DWIN32 \
        $(CPPFLAGS) $(CXXFLAGS)
 PENGUIN_OBJECTS =  \
        $(OBJS)\penguin_penguin.obj \
-       $(OBJS)\penguin_lw.obj \
+       $(OBJS)\penguin_dxfrenderer.obj \
        $(OBJS)\penguin_trackball.obj \
        $(OBJS)\penguin_penguin.res
 
@@ -302,12 +302,12 @@ $(OBJS)\penguin.exe: $(PENGUIN_OBJECTS) $(OBJS)\penguin_penguin.res
 
 data: 
        if not exist $(OBJS) mkdir $(OBJS)
-       for %f in (penguin.lwo) do if not exist $(OBJS)\%f copy .\%f $(OBJS)
+       for %f in (penguin.dxf.gz) do if not exist $(OBJS)\%f copy .\%f $(OBJS)
 
 $(OBJS)\penguin_penguin.obj: .\penguin.cpp
        $(CXX) /c /nologo /TP /Fo$@ $(PENGUIN_CXXFLAGS) $**
 
-$(OBJS)\penguin_lw.obj: .\lw.cpp
+$(OBJS)\penguin_dxfrenderer.obj: .\dxfrenderer.cpp
        $(CXX) /c /nologo /TP /Fo$@ $(PENGUIN_CXXFLAGS) $**
 
 $(OBJS)\penguin_trackball.obj: .\trackball.c
index b2794d940888e1dd2bdcad73b53ccf340fe7821b..32f0074fbc818632b4ed50cf5d7b1d9661890354 100644 (file)
@@ -225,7 +225,7 @@ PENGUIN_CXXFLAGS = $(__DEBUGINFO_0) $(__OPTIMIZEFLAG_2) $(__THREADSFLAG_5) &
        $(__RTTIFLAG_7) $(__EXCEPTIONSFLAG_8) $(CPPFLAGS) $(CXXFLAGS)
 PENGUIN_OBJECTS =  &
        $(OBJS)\penguin_penguin.obj &
-       $(OBJS)\penguin_lw.obj &
+       $(OBJS)\penguin_dxfrenderer.obj &
        $(OBJS)\penguin_trackball.obj
 
 
@@ -260,16 +260,16 @@ $(OBJS)\penguin.exe :  $(PENGUIN_OBJECTS) $(OBJS)\penguin_penguin.res
 
 data : .SYMBOLIC 
        if not exist $(OBJS) mkdir $(OBJS)
-       for %f in (penguin.lwo) do if not exist $(OBJS)\%f copy .\%f $(OBJS)
+       for %f in (penguin.dxf.gz) do if not exist $(OBJS)\%f copy .\%f $(OBJS)
 
 $(OBJS)\penguin_penguin.obj :  .AUTODEPEND .\penguin.cpp
-       $(CXX) -bt=nt -zq -fo=$^@ $(PENGUIN_CXXFLAGS) $<
+       $(CXX) -zq -fo=$^@ $(PENGUIN_CXXFLAGS) $<
 
-$(OBJS)\penguin_lw.obj :  .AUTODEPEND .\lw.cpp
-       $(CXX) -bt=nt -zq -fo=$^@ $(PENGUIN_CXXFLAGS) $<
+$(OBJS)\penguin_dxfrenderer.obj :  .AUTODEPEND .\dxfrenderer.cpp
+       $(CXX) -zq -fo=$^@ $(PENGUIN_CXXFLAGS) $<
 
 $(OBJS)\penguin_trackball.obj :  .AUTODEPEND .\trackball.c
-       $(CC) -bt=nt -zq -fo=$^@ $(PENGUIN_CFLAGS) $<
+       $(CC) -zq -fo=$^@ $(PENGUIN_CFLAGS) $<
 
 $(OBJS)\penguin_penguin.res :  .AUTODEPEND .\penguin.rc
        wrc -q -ad -bt=nt -r -fo=$^@   -d__WXMSW__ $(__WXUNIV_DEFINE_p) $(__DEBUG_DEFINE_p) $(__EXCEPTIONS_DEFINE_p) $(__RTTI_DEFINE_p) $(__THREAD_DEFINE_p) $(__UNICODE_DEFINE_p)  -i=.\..\..\..\include -i=$(SETUPHDIR) -i=. $(__DLLFLAG_p) -i=.\..\..\..\samples -dNOPCH $<
index 880e4e9fd40ee00899520feb15645702491ad8df..28b64c2bae138bae443156571f779b0a4049bb01 100644 (file)
@@ -8,7 +8,7 @@
     <exe id="penguin" template="wx_sample" template_append="wx_append" cond="USE_OPENGL=='1'">
         <sources>
             penguin.cpp
-            lw.cpp
+            dxfrenderer.cpp
             trackball.c
         </sources>
         <wx-lib>gl</wx-lib>
@@ -19,7 +19,7 @@
 
     <wx-data id="data">
         <files>
-            penguin.lwo
+            penguin.dxf.gz
         </files>
     </wx-data>
 
index 93634a40600fc63c9595d17ba7dc2370ade3a32d..f753b518bc45cc4904bc1cc16292ed9d127a194c 100644 (file)
@@ -2,7 +2,7 @@
 // Name:        penguin.cpp
 // Purpose:     wxGLCanvas demo program
 // Author:      Robert Roebling
-// Modified by:
+// Modified by: Sandro Sigala
 // Created:     04/01/98
 // RCS-ID:      $Id$
 // Copyright:   (c) Robert Roebling
 
 #include "../../sample.xpm"
 
-#define VIEW_ASPECT 1.3
+// ---------------------------------------------------------------------------
+// MyApp
+// ---------------------------------------------------------------------------
 
 // `Main program' equivalent, creating windows and returning main app frame
 bool MyApp::OnInit()
 {
     // Create the main frame window
-    MyFrame *frame = new MyFrame(NULL, wxT("wxWidgets OpenGL Penguin Sample"),
+    MyFrame *frame = new MyFrame(NULL, wxT("wxWidgets Penguin Sample"),
         wxDefaultPosition, wxDefaultSize);
 
-    /* Make a menubar */
-    wxMenu *fileMenu = new wxMenu;
-
-    fileMenu->Append(wxID_EXIT, wxT("E&xit"));
-    wxMenuBar *menuBar = new wxMenuBar;
-    menuBar->Append(fileMenu, wxT("&File"));
-    frame->SetMenuBar(menuBar);
-
-    frame->SetCanvas( new TestGLCanvas(frame, wxID_ANY, wxDefaultPosition,
-        wxSize(200, 200), wxSUNKEN_BORDER) );
-
-    /* Load file wiht mesh data */
-    frame->GetCanvas()->LoadLWO( wxT("penguin.lwo") );
+#if wxUSE_ZLIB
+    if (wxFileExists(wxT("penguin.dxf.gz")))
+        frame->GetCanvas()->LoadDXF(wxT("penguin.dxf.gz"));
+#else
+    if (wxFileExists(wxT("penguin.dxf")))
+        frame->GetCanvas()->LoadDXF(wxT("penguin.dxf"));
+#endif
 
     /* Show the frame */
     frame->Show(true);
@@ -68,26 +64,75 @@ bool MyApp::OnInit()
 
 IMPLEMENT_APP(MyApp)
 
+// ---------------------------------------------------------------------------
+// MyFrame
+// ---------------------------------------------------------------------------
+
 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
-    EVT_MENU(wxID_EXIT, MyFrame::OnExit)
+    EVT_MENU(wxID_OPEN, MyFrame::OnMenuFileOpen)
+    EVT_MENU(wxID_EXIT, MyFrame::OnMenuFileExit)
+    EVT_MENU(wxID_HELP, MyFrame::OnMenuHelpAbout)
 END_EVENT_TABLE()
 
-/* My frame constructor */
+// MyFrame constructor
 MyFrame::MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
     const wxSize& size, long style)
     : wxFrame(frame, wxID_ANY, title, pos, size, style)
 {
-    m_canvas = NULL;
     SetIcon(wxIcon(sample_xpm));
+
+    // Make the "File" menu
+    wxMenu *fileMenu = new wxMenu;
+    fileMenu->Append(wxID_OPEN, wxT("&Open..."));
+    fileMenu->AppendSeparator();
+    fileMenu->Append(wxID_EXIT, wxT("E&xit\tALT-X"));
+    // Make the "Help" menu
+    wxMenu *helpMenu = new wxMenu;
+    helpMenu->Append(wxID_HELP, wxT("&About..."));
+
+    wxMenuBar *menuBar = new wxMenuBar;
+    menuBar->Append(fileMenu, wxT("&File"));
+    menuBar->Append(helpMenu, wxT("&Help"));
+    SetMenuBar(menuBar);
+
+    m_canvas = new TestGLCanvas(this, wxID_ANY, wxDefaultPosition,
+        wxSize(300, 300), wxSUNKEN_BORDER);
 }
 
-/* Intercept menu commands */
-void MyFrame::OnExit( wxCommandEvent& WXUNUSED(event) )
+// File|Open... command
+void MyFrame::OnMenuFileOpen( wxCommandEvent& WXUNUSED(event) )
+{
+    wxString filename = wxFileSelector(wxT("Choose DXF Model"), wxT(""), wxT(""), wxT(""),
+#if wxUSE_ZLIB
+        wxT("DXF Drawing (*.dxf;*.dxf.gz)|*.dxf;*.dxf.gz|All files (*.*)|*.*"),
+#else
+        wxT("DXF Drawing (*.dxf)|*.dxf)|All files (*.*)|*.*"),
+#endif
+        wxOPEN);
+    if (!filename.IsEmpty())
+    {
+        m_canvas->LoadDXF(filename);
+        m_canvas->Refresh(false);
+    }
+}
+
+// File|Exit command
+void MyFrame::OnMenuFileExit( wxCommandEvent& WXUNUSED(event) )
 {
     // true is to force the frame to close
     Close(true);
 }
 
+// Help|About... command
+void MyFrame::OnMenuHelpAbout( wxCommandEvent& WXUNUSED(event) )
+{
+    wxMessageBox(wxT("OpenGL Penguin Sample (c) Robert Roebling, Sandro Sigala et al"));
+}
+
+// ---------------------------------------------------------------------------
+// TestGLCanvas
+// ---------------------------------------------------------------------------
+
 BEGIN_EVENT_TABLE(TestGLCanvas, wxGLCanvas)
     EVT_SIZE(TestGLCanvas::OnSize)
     EVT_PAINT(TestGLCanvas::OnPaint)
@@ -99,18 +144,22 @@ TestGLCanvas::TestGLCanvas(wxWindow *parent, wxWindowID id,
     const wxPoint& pos, const wxSize& size, long style, const wxString& name)
     : wxGLCanvas(parent, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE, name)
 {
-    block = false;
+    m_gldata.initialized = false;
+
+    // initialize view matrix
+    m_gldata.beginx = 0.0f;
+    m_gldata.beginy = 0.0f;
+    m_gldata.zoom   = 45.0f;
+    trackball(m_gldata.quat, 0.0f, 0.0f, 0.0f, 0.0f);
 }
 
 TestGLCanvas::~TestGLCanvas()
 {
-    /* destroy mesh */
-    lw_object_free(info.lwobject);
 }
 
 void TestGLCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
 {
-    /* must always be here */
+    // must always be here
     wxPaintDC dc(this);
 
 #ifndef __WXMOTIF__
@@ -120,31 +169,25 @@ void TestGLCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
     SetCurrent();
 
     // Initialize OpenGL
-    if (info.do_init)
+    if (!m_gldata.initialized)
     {
         InitGL();
-        info.do_init = false;
+        ResetProjectionMode();
+        m_gldata.initialized = true;
     }
 
-    // View
-    glMatrixMode( GL_PROJECTION );
-    glLoadIdentity();
-    gluPerspective( info.zoom, VIEW_ASPECT, 1.0, 100.0 );
-    glMatrixMode( GL_MODELVIEW );
-
     // Clear
     glClearColor( 0.3f, 0.4f, 0.6f, 1.0f );
     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
     // Transformations
-    GLfloat m[4][4];
     glLoadIdentity();
-    glTranslatef( 0.0f, 0.0f, -30.0f );
-    build_rotmatrix( m,info.quat );
+    glTranslatef( 0.0f, 0.0f, -20.0f );
+    GLfloat m[4][4];
+    build_rotmatrix( m, m_gldata.quat );
     glMultMatrixf( &m[0][0] );
 
-    // Draw object
-    lw_object_show( info.lwobject );
+    m_renderer.Render();
 
     // Flush
     glFlush();
@@ -157,67 +200,61 @@ void TestGLCanvas::OnSize(wxSizeEvent& event)
 {
     // this is also necessary to update the context on some platforms
     wxGLCanvas::OnSize(event);
-
-    // set GL viewport (not called by wxGLCanvas::OnSize on all platforms...)
-    int w, h;
-    GetClientSize(&w, &h);
-#ifndef __WXMOTIF__
-    if ( GetContext() )
-#endif
-    {
-        SetCurrent();
-        glViewport(0, 0, (GLint) w, (GLint) h);
-    }
+    // Reset the OpenGL view aspect
+    ResetProjectionMode();
 }
 
 void TestGLCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
 {
-    /* Do nothing, to avoid flashing on MSW */
+    // Do nothing, to avoid flashing on MSW
 }
 
-void TestGLCanvas::LoadLWO(const wxString &filename)
+// Load the DXF file.  If the zlib support is compiled in wxWidgets,
+// supports also the ".dxf.gz" gzip compressed files.
+void TestGLCanvas::LoadDXF(const wxString& filename)
 {
-    /* test if lightwave object */
-    if (!lw_is_lwobject(filename.mb_str())) return;
-
-    /* read lightwave object */
-    lwObject *lwobject = lw_object_read(filename.mb_str());
-
-    /* scale */
-    lw_object_scale(lwobject, 10.0 / lw_object_radius(lwobject));
-
-    /* set up mesh info */
-    info.do_init = true;
-    info.lwobject = lwobject;
-    info.beginx = 0.0f;
-    info.beginy = 0.0f;
-    info.zoom   = 45.0f;
-    trackball( info.quat, 0.0f, 0.0f, 0.0f, 0.0f );
+    wxFileInputStream stream(filename);
+    if (stream.Ok())
+#if wxUSE_ZLIB
+    {
+        if (filename.Right(3).Lower() == wxT(".gz"))
+        {
+            wxZlibInputStream zstream(stream);
+            m_renderer.Load(zstream);
+        } else
+        {
+            m_renderer.Load(stream);
+        }
+    }
+#else
+    {
+        m_renderer.Load(stream);
+    }
+#endif
 }
 
-void TestGLCanvas::OnMouse( wxMouseEvent& event )
+void TestGLCanvas::OnMouse(wxMouseEvent& event)
 {
-
-    if ( event.Dragging() )
+    if (event.Dragging())
     {
-        wxSize sz( GetClientSize() );
+        wxSize sz(GetClientSize());
 
         /* drag in progress, simulate trackball */
         float spin_quat[4];
         trackball(spin_quat,
-            (2.0*info.beginx -       sz.x) / sz.x,
-            (     sz.y - 2.0*info.beginy) / sz.y,
-            (     2.0*event.GetX() - sz.x) / sz.x,
-            (    sz.y - 2.0*event.GetY()) / sz.y);
+            (2.0*m_gldata.beginx - sz.x) / sz.x,
+            (sz.y - 2.0*m_gldata.beginy) / sz.y,
+            (2.0*event.GetX() - sz.x)    / sz.x,
+            (sz.y - 2.0*event.GetY())    / sz.y);
 
-        add_quats( spin_quat, info.quat, info.quat );
+        add_quats(spin_quat, m_gldata.quat, m_gldata.quat);
 
         /* orientation has changed, redraw mesh */
         Refresh(false);
     }
 
-    info.beginx = event.GetX();
-    info.beginy = event.GetY();
+    m_gldata.beginx = event.GetX();
+    m_gldata.beginy = event.GetY();
 }
 
 void TestGLCanvas::InitGL()
@@ -255,3 +292,20 @@ void TestGLCanvas::InitGL()
     glEnable(GL_COLOR_MATERIAL);
 }
 
+void TestGLCanvas::ResetProjectionMode()
+{
+    int w, h;
+    GetClientSize(&w, &h);
+#ifndef __WXMOTIF__
+    if ( GetContext() )
+#endif
+    {
+        SetCurrent();
+        glViewport(0, 0, (GLint) w, (GLint) h);
+        glMatrixMode(GL_PROJECTION);
+        glLoadIdentity();
+        gluPerspective(45.0f, (GLfloat)w/h, 1.0, 100.0);
+        glMatrixMode(GL_MODELVIEW);
+        glLoadIdentity();
+    }
+}
index 85e23d5f2737b861c90f3fc518516543ebd88b5a..250346abb35595e93dd58e2a58d94b2892b8a8bd 100644 (file)
@@ -468,7 +468,7 @@ LINK32=link.exe
 # PROP Default_Filter ""
 # Begin Source File
 
-SOURCE=.\lw.cpp
+SOURCE=.\dxfrenderer.cpp
 # End Source File
 # Begin Source File
 
diff --git a/samples/opengl/penguin/penguin.dxf.gz b/samples/opengl/penguin/penguin.dxf.gz
new file mode 100644 (file)
index 0000000..9a20f6e
Binary files /dev/null and b/samples/opengl/penguin/penguin.dxf.gz differ
index dae7ca35e95afd4f4857b5418983d840e86fcd0c..63efc497f44d62567d2203fa6588366566f1f638 100644 (file)
 #include "wx/app.h"
 #include "wx/menu.h"
 #include "wx/dcclient.h"
+#include "wx/wfstream.h"
+#if wxUSE_ZLIB
+#include "wx/zstream.h"
+#endif
 
 #include "wx/glcanvas.h"
 
 extern "C"
 {
-#include "lw.h"
 #include "trackball.h"
 }
 
-/* information needed to display lightwave mesh */
-typedef struct
-{
-//  gint do_init;         /* true if initgl not yet called */
-    bool do_init;
-    lwObject *lwobject;   /* lightwave object mesh */
-    float beginx,beginy;  /* position of mouse */
-    float quat[4];        /* orientation of object */
-    float zoom;           /* field of view in degrees */
-} mesh_info;
+#include "dxfrenderer.h"
 
+// OpenGL view data
+struct GLData
+{
+    bool initialized;           // have OpenGL been initialized?
+    float beginx, beginy;       // position of mouse
+    float quat[4];              // orientation of object
+    float zoom;                 // field of view in degrees
+};
 
-/* Define a new application type */
+// Define a new application type
 class MyApp: public wxApp
 {
 public:
     bool OnInit();
 };
 
-/* Define a new frame type */
+// Define a new frame type
 class TestGLCanvas;
 
 class MyFrame: public wxFrame
@@ -54,7 +56,9 @@ public:
     MyFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
         const wxSize& size, long style = wxDEFAULT_FRAME_STYLE);
 
-    void OnExit(wxCommandEvent& event);
+    void OnMenuFileOpen(wxCommandEvent& event);
+    void OnMenuFileExit(wxCommandEvent& event);
+    void OnMenuHelpAbout(wxCommandEvent& event);
 
 #if wxUSE_GLCANVAS
     void SetCanvas( TestGLCanvas *canvas ) { m_canvas = canvas; }
@@ -79,17 +83,21 @@ public:
 
     ~TestGLCanvas();
 
+    void LoadDXF(const wxString& filename);
+
+protected:
     void OnPaint(wxPaintEvent& event);
     void OnSize(wxSizeEvent& event);
     void OnEraseBackground(wxEraseEvent& event);
-    void LoadLWO( const wxString &filename);
-    void OnMouse( wxMouseEvent& event );
+    void OnMouse(wxMouseEvent& event);
+
+private:
     void InitGL();
+    void ResetProjectionMode();
 
-    mesh_info  info;
-    bool       block;
+    GLData m_gldata;
+    DXFRenderer m_renderer;
 
-private:
     DECLARE_EVENT_TABLE()
 };
 
diff --git a/samples/opengl/penguin/penguin.lwo b/samples/opengl/penguin/penguin.lwo
deleted file mode 100644 (file)
index 3f5122d..0000000
Binary files a/samples/opengl/penguin/penguin.lwo and /dev/null differ