From 4b764db3795a5f202f379ee3b0314b2de91c15fa Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Mon, 14 Nov 2005 17:38:24 +0000 Subject: [PATCH] Applied patch [ 1355355 ] Replace GPLed code in penguin sample and add features (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 --- build/bakefiles/make_dist.mk | 2 +- distrib/msw/generic.rsp | 2 +- distrib/msw/makefile.rsp | 1 + distrib/msw/vc.rsp | 3 + distrib/msw/wince.rsp | 3 + samples/opengl/penguin/Makefile.in | 8 +- samples/opengl/penguin/dxfrenderer.cpp | 680 +++++++++++++++++++++++++ samples/opengl/penguin/dxfrenderer.h | 79 +++ samples/opengl/penguin/lw.cpp | 438 ---------------- samples/opengl/penguin/lw.h | 79 --- samples/opengl/penguin/makefile.bcc | 6 +- samples/opengl/penguin/makefile.gcc | 6 +- samples/opengl/penguin/makefile.vc | 6 +- samples/opengl/penguin/makefile.wat | 12 +- samples/opengl/penguin/penguin.bkl | 4 +- samples/opengl/penguin/penguin.cpp | 210 +++++--- samples/opengl/penguin/penguin.dsp | 2 +- samples/opengl/penguin/penguin.dxf.gz | Bin 0 -> 11835 bytes samples/opengl/penguin/penguin.h | 46 +- samples/opengl/penguin/penguin.lwo | Bin 10028 -> 0 bytes 20 files changed, 949 insertions(+), 638 deletions(-) create mode 100644 samples/opengl/penguin/dxfrenderer.cpp create mode 100644 samples/opengl/penguin/dxfrenderer.h delete mode 100644 samples/opengl/penguin/lw.cpp delete mode 100644 samples/opengl/penguin/lw.h create mode 100644 samples/opengl/penguin/penguin.dxf.gz delete mode 100644 samples/opengl/penguin/penguin.lwo diff --git a/build/bakefiles/make_dist.mk b/build/bakefiles/make_dist.mk index 2b30839093..7a2b140846 100644 --- a/build/bakefiles/make_dist.mk +++ b/build/bakefiles/make_dist.mk @@ -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 diff --git a/distrib/msw/generic.rsp b/distrib/msw/generic.rsp index 3ac61eb3f4..20771ab854 100644 --- a/distrib/msw/generic.rsp +++ b/distrib/msw/generic.rsp @@ -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 diff --git a/distrib/msw/makefile.rsp b/distrib/msw/makefile.rsp index d9206458f2..fe1e061711 100644 --- a/distrib/msw/makefile.rsp +++ b/distrib/msw/makefile.rsp @@ -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 diff --git a/distrib/msw/vc.rsp b/distrib/msw/vc.rsp index 9465a87017..9dd2531c71 100644 --- a/distrib/msw/vc.rsp +++ b/distrib/msw/vc.rsp @@ -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 diff --git a/distrib/msw/wince.rsp b/distrib/msw/wince.rsp index bb5d2dfea5..28a9bac02c 100644 --- a/distrib/msw/wince.rsp +++ b/distrib/msw/wince.rsp @@ -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 diff --git a/samples/opengl/penguin/Makefile.in b/samples/opengl/penguin/Makefile.in index b54aea2900..48f3922b7a 100644 --- a/samples/opengl/penguin/Makefile.in +++ b/samples/opengl/penguin/Makefile.in @@ -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 index 0000000000..5d18667872 --- /dev/null +++ b/samples/opengl/penguin/dxfrenderer.cpp @@ -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 +# else +# include +# endif +#else +# include +#endif + +#include "dxfrenderer.h" + +#include +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 index 0000000000..0e803e6feb --- /dev/null +++ b/samples/opengl/penguin/dxfrenderer.h @@ -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 index 9b2202000c..0000000000 --- a/samples/opengl/penguin/lw.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (C) 1998 Janne Löf - * - * 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 -#endif - -#include "lw.h" -#include -#include - -#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; iindex_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; ivertex_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; iface_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; iface_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; jindex_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; ivertex_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; ivertex_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 index 0a4ca382d9..0000000000 --- a/samples/opengl/penguin/lw.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 1998 Janne Löf - * - * 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 -# else -# include -# endif -#else -# include -#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 */ - diff --git a/samples/opengl/penguin/makefile.bcc b/samples/opengl/penguin/makefile.bcc index d7ef2b8dce..f2c02cf4fc 100644 --- a/samples/opengl/penguin/makefile.bcc +++ b/samples/opengl/penguin/makefile.bcc @@ -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 diff --git a/samples/opengl/penguin/makefile.gcc b/samples/opengl/penguin/makefile.gcc index 679422d256..b7cec871ba 100644 --- a/samples/opengl/penguin/makefile.gcc +++ b/samples/opengl/penguin/makefile.gcc @@ -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 diff --git a/samples/opengl/penguin/makefile.vc b/samples/opengl/penguin/makefile.vc index a0f51e19da..ee2bdd6039 100644 --- a/samples/opengl/penguin/makefile.vc +++ b/samples/opengl/penguin/makefile.vc @@ -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 diff --git a/samples/opengl/penguin/makefile.wat b/samples/opengl/penguin/makefile.wat index b2794d9408..32f0074fbc 100644 --- a/samples/opengl/penguin/makefile.wat +++ b/samples/opengl/penguin/makefile.wat @@ -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 $< diff --git a/samples/opengl/penguin/penguin.bkl b/samples/opengl/penguin/penguin.bkl index 880e4e9fd4..28b64c2bae 100644 --- a/samples/opengl/penguin/penguin.bkl +++ b/samples/opengl/penguin/penguin.bkl @@ -8,7 +8,7 @@ penguin.cpp - lw.cpp + dxfrenderer.cpp trackball.c gl @@ -19,7 +19,7 @@ - penguin.lwo + penguin.dxf.gz diff --git a/samples/opengl/penguin/penguin.cpp b/samples/opengl/penguin/penguin.cpp index 93634a4060..f753b518bc 100644 --- a/samples/opengl/penguin/penguin.cpp +++ b/samples/opengl/penguin/penguin.cpp @@ -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 @@ -37,28 +37,24 @@ #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(); + } +} diff --git a/samples/opengl/penguin/penguin.dsp b/samples/opengl/penguin/penguin.dsp index 85e23d5f27..250346abb3 100644 --- a/samples/opengl/penguin/penguin.dsp +++ b/samples/opengl/penguin/penguin.dsp @@ -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 index 0000000000000000000000000000000000000000..9a20f6e5e4f79011894dc09373a79d7cda1b5214 GIT binary patch literal 11835 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 LrL3}e|K9%rV-Ie- literal 0 HcmV?d00001 diff --git a/samples/opengl/penguin/penguin.h b/samples/opengl/penguin/penguin.h index dae7ca35e9..63efc497f4 100644 --- a/samples/opengl/penguin/penguin.h +++ b/samples/opengl/penguin/penguin.h @@ -17,35 +17,37 @@ #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 index 3f5122db827e09028d394b682ee6c0a1deec0ddd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10028 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 PcWrX~nY%asqw)U-TLDh; -- 2.45.2