$(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
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
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
samples/richedit/*.dsp
samples/richedit/*.dsw
+samples/richtext/*.dsp
+samples/richtext/*.dsw
+
samples/rotate/rotate.dsp
samples/rotate/rotate.dsw
samples/richedit/richedit.vcp
samples/richedit/richedit.vcw
+samples/richtext/richtext.vcp
+samples/richtext/richtext.vcw
+
samples/rotate/rotate.vcp
samples/rotate/rotate.vcw
PENGUIN_OBJECTS = \
$(__penguin_os2_lib_res) \
penguin_penguin.o \
- penguin_lw.o \
+ penguin_dxfrenderer.o \
penguin_trackball.o \
$(__penguin___win32rc)
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` ; \
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
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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();
+ }
+ }
+}
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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_
+++ /dev/null
-/*
- * 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
-
+++ /dev/null
-/*
- * 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 */
-
-DNOPCH $(CPPFLAGS) $(CXXFLAGS)
PENGUIN_OBJECTS = \
$(OBJS)\penguin_penguin.obj \
- $(OBJS)\penguin_lw.obj \
+ $(OBJS)\penguin_dxfrenderer.obj \
$(OBJS)\penguin_trackball.obj
### Conditionally set variables: ###
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
-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
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
$(CPPFLAGS) $(CXXFLAGS)
PENGUIN_OBJECTS = \
$(OBJS)\penguin_penguin.obj \
- $(OBJS)\penguin_lw.obj \
+ $(OBJS)\penguin_dxfrenderer.obj \
$(OBJS)\penguin_trackball.obj \
$(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
$(__RTTIFLAG_7) $(__EXCEPTIONSFLAG_8) $(CPPFLAGS) $(CXXFLAGS)
PENGUIN_OBJECTS = &
$(OBJS)\penguin_penguin.obj &
- $(OBJS)\penguin_lw.obj &
+ $(OBJS)\penguin_dxfrenderer.obj &
$(OBJS)\penguin_trackball.obj
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 $<
<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>
<wx-data id="data">
<files>
- penguin.lwo
+ penguin.dxf.gz
</files>
</wx-data>
// 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);
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)
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__
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();
{
// 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()
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();
+ }
+}
# PROP Default_Filter ""
# Begin Source File
-SOURCE=.\lw.cpp
+SOURCE=.\dxfrenderer.cpp
# End Source File
# Begin Source 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
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; }
~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()
};