1 /*******************************************************************************
2 Copyright (c) 2012, Jonathan Hiller
3 
4 This file is part of the AMF Tools suite. http://amf.wikispaces.com/
5 AMF Tools is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
6 AMF Tools 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 Lesser General Public License for more details.
7 See <http://www.opensource.org/licenses/lgpl-3.0.html> for license details.
8 *******************************************************************************/
9 
10 #ifndef MESH_H
11 #define MESH_H
12 
13 #include <vector>
14 #include <string>
15 #include "Vec3D.h"
16 
17 #include "XmlStream.h"
18 
19 //basic RGB color container
20 struct CColor { //copied from GL_Utils.h
CColorCColor21 	CColor(){r=-1; g=-1; b=-1;a=-1;};
CColorCColor22 	CColor (const CColor& C) {*this = C;}
CColorCColor23 	CColor(double rIn, double gIn, double bIn){r=rIn; g=gIn; b=bIn; a=1.0;}
CColorCColor24 	CColor(double rIn, double gIn, double bIn, double aIn){r=rIn; g=gIn; b=bIn; a=aIn;}
25 	inline CColor& operator=(const CColor& C) {r = C.r; g = C.g; b = C.b; a = C.a; return *this; }; //overload equals
26 
27 	double r, g, b, a;
isValidCColor28 	bool isValid(void) const {if(r>=0.0 && r <=1.0 && g>=0.0 && g <=1.0 && b>=0.0 && b <=1.0 && a>=0.0 && a <=1.0) return true; else return false;};
29 };
30 
31 //structure to hold each vertex
32 struct CVertex {
CVertexCVertex33 	CVertex() {Clear();}
CVertexCVertex34 	CVertex(const Vec3D& av) {Clear(); v = av;}
CVertexCVertex35 	CVertex(const Vec3D& an, const Vec3D& av) {Clear(); n = an; HasNormal=true; v = av;}
CVertexCVertex36 	CVertex(const Vec3D& av, const CColor& ac) {Clear(); v = av; HasColor = true; VColor = ac;}
37 	inline CVertex& operator=(const CVertex& V) {v=V.v; HasNormal=V.HasNormal; n=V.n;HasColor=V.HasColor; VColor = V.VColor; /*DrawOffset = V.DrawOffset;*/ return *this;}; //overload equals
CVertexCVertex38 	CVertex(const CVertex& V) {*this = V;} // DrawAxis = V.DrawAxis; DrawAngle = V.DrawAngle;}
ClearCVertex39 	inline void Clear(){v = Vec3D(0,0,0); HasNormal = false; n = Vec3D(0,0,0); HasColor = false; VColor = CColor(1,1,1,1); /*DrawOffset = Vec3D(0,0,0);*/}
40 
41 	void WriteXML(CXmlStreamWrite* pXML);
42 	bool ReadXML(CXmlStreamRead* pXML);
43 
44 	Vec3D v; //Vertex location
45 	bool HasNormal;
46 	Vec3D n; //normal
47 	bool HasColor;
48 	CColor VColor;
49 };
50 
51 struct TexMap {
TexMapTexMap52 	TexMap() {};
53 //	TexMap(const double U1In, const double U2In, const double U3In, const double V1In, const double V2In, const double V3In, const bool TexTileIn = false) {uc[0]=U1In;	uc[1]=U2In;	uc[2]=U3In; vc[0]=V1In; vc[1]=V2In; vc[2]=V3In; TexTile=TexTileIn;}
54 	TexMap(const int TexIndexIn, const double U1In, const double U2In, const double U3In, const double V1In, const double V2In, const double V3In, const bool TexTileIn = false) {TexIndex=TexIndexIn; uc[0]=U1In;	uc[1]=U2In;	uc[2]=U3In; vc[0]=V1In; vc[1]=V2In; vc[2]=V3In; TexTile=TexTileIn;}
55 //	inline TexMap& operator=(const TexMap& t) {uc[0]=t.uc[0]; uc[1]=t.uc[1]; uc[2]=t.uc[2]; vc[0]=t.vc[0]; vc[1]=t.vc[1]; vc[2]=t.vc[2]; TexTile = t.TexTile; return *this;}; //overload equals
56 	inline TexMap& operator=(const TexMap& t) {TexIndex=t.TexIndex; uc[0]=t.uc[0]; uc[1]=t.uc[1]; uc[2]=t.uc[2]; vc[0]=t.vc[0]; vc[1]=t.vc[1]; vc[2]=t.vc[2]; TexTile = t.TexTile; return *this;}; //overload equals
TexMapTexMap57 	TexMap(const TexMap& t) {*this = t;}
58 
59 	int TexIndex;
60 	double uc[3]; //u texture coordinates
61 	double vc[3]; //v texture coordinates
62 	bool TexTile;
63 };
64 
65 //structure to hold each facet
66 struct CFacet {
CFacetCFacet67 	CFacet() {Clear();}
CFacetCFacet68 	CFacet(const int& av1, const int& av2, const int& av3) {Clear(); vi[0] = av1; vi[1] = av2; vi[2] = av3;}
CFacetCFacet69 	CFacet(const Vec3D& an, const int& av1, const int& av2, const int& av3) {Clear(); n = an; vi[0] = av1; vi[1] = av2; vi[2] = av3;}
CFacetCFacet70 	CFacet(const Vec3D& an, const int& av1, const int& av2, const int& av3, const int& NIn) {Clear(); n = an; vi[0] = av1; vi[1] = av2; vi[2] = av3; Name = NIn;}
CFacetCFacet71 	CFacet(const Vec3D& an, const int& av1, const int& av2, const int& av3, const CColor& ac) {Clear(); n = an; vi[0] = av1; vi[1] = av2; vi[2] = av3; FColor = ac;}
72 	inline CFacet& operator=(const CFacet& p) { vi[0]=p.vi[0]; vi[1]=p.vi[1]; vi[2]=p.vi[2]; n=p.n; FColor = p.FColor; HasEdge[0]=p.HasEdge[0]; HasEdge[1]=p.HasEdge[1]; HasEdge[2]=p.HasEdge[2]; ei[0]=p.ei[0]; ei[1]=p.ei[1]; ei[2]=p.ei[2]; HasName=p.HasName; Name = p.Name; HasTexture = p.HasTexture; Map = p.Map; return *this;}; //overload equals
CFacetCFacet73 	CFacet(const CFacet& p) {*this = p;}
ClearCFacet74 	void Clear() {n=Vec3D(0,0,0); FColor = CColor(1,1,1,1); vi[0] = 0; vi[1] = 0; vi[2] = 0; HasEdge[0] = false; HasEdge[1] = false; HasEdge[2] = false; ei[0]=0; ei[1]=0; ei[2]=0; HasTexture = false; HasName = false; Name = -1;}
75 
76 	int vi[3]; //vertex indices
77 	bool HasEdge[3]; //correspond to indices in ei[]
78 	int ei[3]; //edge indices ei[0] = vi[0] -> vi[1], ei[1] = vi[1] -> vi[2], ei[2] = vi[2] -> vi[0]
79 	bool HasName;
80 	int Name; //my name (for GL picking)
81 	bool HasTexture; //do we want to draw a texture instead of a color for this facet?
82 	TexMap Map; //mapping to a texture
83 	bool HasColor;
84 	CColor FColor;
85 
86 	Vec3D n; //normal (computed from vertex locations
87 
88 };
89 
90 struct CLine {
CLineCLine91 	CLine() {Clear();}
CLineCLine92 	CLine(const int& av1, const int& av2) {Clear(); vi[0] = av1; vi[1] = av2;}
CLineCLine93 	CLine(const int& av1, const int& av2, Vec3D vt1, Vec3D vt2) {Clear(); vi[0] = av1; vi[1] = av2; vt[0]=vt1; vt[1]=vt2; HasTangent[0]=true; HasTangent[1]=true;}
94 	inline CLine& operator=(const CLine& l) { vi[0]=l.vi[0]; vi[1]=l.vi[1]; HasTangent[0]=l.HasTangent[0]; HasTangent[1]=l.HasTangent[1]; vt[0]=l.vt[0]; vt[1]=l.vt[1]; return *this;}; //overload equals
CLineCLine95 	CLine(const CLine& l) {*this = l;}
96 	friend bool operator<(const CLine& L1, const CLine& L2) { if (L1.vi[0] == L2.vi[0]) return L1.vi[1] < L2.vi[1]; else return L1.vi[0] < L2.vi[0];} //for sorting
97 	friend bool operator==(const CLine& L1, const CLine& L2) {return ((L1.vi[0]==L2.vi[0] && L1.vi[1]==L2.vi[1]));} // || (vi[0]==O.vi[1] && vi[1]==O.vi[0]));} //Is equal
ClearCLine98 	void Clear(void) {vi[0]=-1; vi[1]=-1; HasTangent[0]=false; HasTangent[1]=false; vt[0]=Vec3D(0,0,0); vt[1]=Vec3D(0,0,0);}
99 
100 	int vi[2]; //vertex indices
101 	bool HasTangent[2]; //is this edge curved or not? (if so vt is ignored)
102 	Vec3D vt[2]; //vertex tangents - always must go ccw (same direction as vertices!))
103 
104 
105 };
106 
107 
108 
109 class CTexture {
110 	public:
CTexture()111 	CTexture() {Clear();}
~CTexture()112 	~CTexture() {}
113 	CTexture& operator=(const CTexture& t) {Width = t.Width; Height = t.Height; RGBAImage = t.RGBAImage; Tiled = t.Tiled; GlTexInitialized=t.GlTexInitialized; GlTexName=t.GlTexName; return *this;}; //overload equals
CTexture(const CTexture & t)114 	CTexture(const CTexture& t) {*this = t;}
Clear()115 	void Clear(){Tiled=false; Width=0; Height=0; GlTexInitialized=false; GlTexName=-1;}
116 
117 	bool Tiled; //show tiled or transparent past edges?
118 	int Width, Height; //, ActWidth, ActHeight;
119 //	double XScale, YScale;
120 	void LoadData(int WidthIn, int HeightIn, unsigned char* RGBAdata, bool TiledIn = true);
121 	void LoadData(int WidthIn, int HeightIn, unsigned char* Rdata, unsigned char* Gdata, unsigned char* Bdata, unsigned char* Adata, bool TiledIn = true);
122 	void LoadData(int WidthIn, int HeightIn, unsigned char* Rdata, unsigned char* Gdata, unsigned char* Bdata, bool TiledIn = true);
123 
124 
125 	std::vector<unsigned char> RGBAImage;
126 
127 	bool GlTexInitialized;
128 	unsigned int GlTexName;
129 	unsigned int TexName(void); //returns the openGL texture name, or initializes it in ogl if it hasn't already
130 	bool SetGlBorderColor(float r, float g, float b, float a);
131 
132 //private:
133 //	void ResizeToMult2(void); //resizes the internal image to a multiple of 2, stores the factors.
134 
135 };
136 
137 class CMesh
138 {
139 public:
140 	CMesh(void);
141 	~CMesh(void);
142 
143 	CMesh(CMesh& s);
144 	CMesh& operator=(const CMesh& s);
145 	void Clear();
146 
147 	void WriteXML(CXmlStreamWrite* pXML, bool MeshOnly = false); //meshonly only store stl-equiavalent info (no color, normals, etc...)
148 	bool ReadXML(CXmlStreamRead* pXML);
149 
Exists(void)150 	bool Exists(void) {if (Facets.size() != 0) return true; else return false;}
SetBBColor(double r,double g,double b)151 	void SetBBColor(double r, double g, double b){BoundBoxColor = CColor(r, g, b);}
152 
GetpFacet(int FacetIndex)153 	const CFacet* GetpFacet(int FacetIndex) const {return &Facets[FacetIndex];}
GetpVertex(int VertexIndex)154 	const CVertex* GetpVertex(int VertexIndex) const {return &Vertices[VertexIndex];}
GetpLine(int LineIndex)155 	const CLine* GetpLine(int LineIndex) const {return &Lines[LineIndex];}
GetpFacet(int FacetIndex)156 	CFacet* GetpFacet(int FacetIndex) {return &Facets[FacetIndex];}
GetpVertex(int VertexIndex)157 	CVertex* GetpVertex(int VertexIndex) {return &Vertices[VertexIndex];}
GetpLine(int LineIndex)158 	CLine* GetpLine(int LineIndex) {return &Lines[LineIndex];}
159 
160 
GetFacetCount()161 	int GetFacetCount(){return (int)Facets.size();}
GetVertexCount()162 	int GetVertexCount(){return (int)Vertices.size();}
GetLineCount()163 	int GetLineCount(){return (int)Lines.size();}
164 
165 
166 	// file i/o
167 	bool LoadSTL(std::string filename);
168 	bool SaveSTL(std::string filename, bool Binary = true) const;
169 
170 	void CalcFaceNormals(); //called to update the face normals...
171 	void CalcVertNormals(); //called once for each new geometry (or after deformed...) (depends on face normals!!!)
172 
173 
174 	//bool TexturesChanged;
175 #ifdef USE_OPEN_GL
176 	void Draw(bool DrawBoundingBox = false); //requires OpenGL libs
177 #endif
178 
MeshChanged(void)179 	virtual void MeshChanged(void) {};
180 
181 	//add a facet
182 	CFacet* AddFacet(const Vec3D& v1, const Vec3D& v2, const Vec3D& v3, bool QuickAdd = false); //adds a facet, checks vertex list for existing vertices... (should be called with vertices in CCW for proper normal calculation!
183 	CFacet* AddFacet(const Vec3D& v1, const Vec3D& v2, const Vec3D& v3, const CColor& Col1, const CColor& Col2, const CColor& Col3, bool QuickAdd = false); //adds a facet... with color info
184 	CFacet* AddFacet(const Vec3D& v1, const Vec3D& v2, const Vec3D& v3, const TexMap& MapIn); //adds a facet... with color info
185 
186 	CFacet* AddFacet(const CVertex& v1, const CVertex& v2, const CVertex& v3);
187 	CFacet* AddFacet(const CVertex& v1, const CVertex& v2, const CVertex& v3, const TexMap& MapIn); //adds a facet... with texture map
188 
AddQuadFacet(const Vec3D & v1,const Vec3D & v2,const Vec3D & v3,const Vec3D & v4)189 	void AddQuadFacet(const Vec3D& v1, const Vec3D& v2, const Vec3D& v3, const Vec3D& v4) {AddFacet(v1, v2, v3); AddFacet(v3, v4, v1);}; //Vertices should be CCW from outside
190 
AddLine(const CLine & l1)191 	CLine* AddLine(const CLine& l1){Lines.push_back(l1); return &Lines.back();}
192 
193 	//Add a texture
AddTexture(const CTexture & t1)194 	CTexture* AddTexture(const CTexture& t1){Textures.push_back(t1); return &Textures.back();}
GetTextureCount(void)195 	int GetTextureCount(void) {return Textures.size();}
196 
197 
GetBBMin(void)198 	Vec3D GetBBMin(void) {if (NeedBBCalc) UpdateBoundingBox(); return _CurBBMin;}
GetBBMax(void)199 	Vec3D GetBBMax(void) {if (NeedBBCalc) UpdateBoundingBox(); return _CurBBMax;}
GetBBSize(void)200 	Vec3D GetBBSize(void) {if (NeedBBCalc) UpdateBoundingBox(); return _CurBBMax - _CurBBMin;}
201 
202 
203 	//manipulation...
204 	void Scale(Vec3D d);
205 	void Translate(Vec3D d);
206 	void Rotate(Vec3D ax, double a);
207 	void Rotate(CQuat QRot); //rotation by quaternion
208 	void RotX(double a);
209 	void RotY(double a);
210 	void RotZ(double a);
211 
212 
213 	void WeldClose(float Distance); //welds vertices that are nearby (within Distance). Removes deleted triangles...
214 	void RemoveDupLines(void);
215 
216 	std::vector<int> GlNameIndexStack; //for OpenGL picking
217 
218 	void SubdivideMe(void); //tmp
219 
220 
221 protected:
222 	bool NeedBBCalc;
223 //	void ComputeBoundingBox(Vec3D& pmin, Vec3D& pmax);
224 	void UpdateBoundingBox(void);
225 
226 
227 	bool LoadBinarySTL(std::string filename);
228 	bool LoadAsciiSTL(std::string filename);
229 
230 
231 	bool DrawNormals, DrawTextures, DrawEdges, DrawShaded, DrawSmooth, IgnoreNames;
232 	CColor BodyColor; //base color to use in absence of face/vertex colors
233 	CColor BoundBoxColor; //color when drawing bounding box
234 
235 	std::vector<CFacet> Facets;
236 	std::vector<CVertex> Vertices;
237 	std::vector<CLine> Lines;
238 	std::vector<CTexture> Textures;
239 
240 	Vec3D _CurBBMin, _CurBBMax; //cached bounding box values... (UpdateBoundingBox to update())
241 
242 
243 //curved triangle stuff:
244 
245 	void HermiteInterpolation(Vec3D v0, Vec3D n0, Vec3D t0, Vec3D v1, Vec3D n1, Vec3D t1, double s, Vec3D& vs, Vec3D& ts, Vec3D& ns);
246 
247 
248 };
249 #endif
250