1// tPolyModel.cpp 
2// 
3// This file implements tScene polygonal models. A tPolyModel contains a tMesh and a functional interface over it. 
4// 
5// Copyright (c) 2006, 2017, 2020 Tristan Grimmer. 
6// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby 
7// granted, provided that the above copyright notice and this permission notice appear in all copies. 
8// 
9// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 
10// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 
11// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
12// AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
13// PERFORMANCE OF THIS SOFTWARE. 
14 
15#include <Foundation/tFundamentals.h> 
16#include "Scene/tPolyModel.h" 
17using namespace tMath
18namespace tScene 
19
20 
21 
22void tPolyModel::Save(tChunkWriter& chunk) const 
23
24 chunk.Begin(tChunkID::Scene_PolyModel); 
25
26 tObject::Save(chunk); 
27 
28 chunk.Begin(tChunkID::Core_Bool); 
29
30 chunk.Write(IsLodGroupMember); 
31
32 chunk.End(); 
33 
34 Mesh.Save(chunk); 
35
36 chunk.End(); 
37
38 
39 
40void tPolyModel::Load(const tChunk& modelChunk
41
42 tAssert(modelChunk.ID() == tChunkID::Scene_PolyModel); 
43 Clear(); 
44 
45 for (tChunk chunk = modelChunk.First(); chunk.Valid(); chunk = chunk.Next()) 
46
47 switch (chunk.ID()) 
48
49 case tChunkID::Scene_Object
50 tObject::Load(chunk); 
51 break
52 
53 case tChunkID::Core_Bool
54 chunk.GetItem(IsLodGroupMember); 
55 break
56 
57 case tChunkID::Scene_Mesh
58 Mesh.Load(chunk); 
59 break
60
61
62
63 
64 
65float tPolyModel::ComputeBoundingRadius() const 
66
67 float maxRadiusSq = 0.0f
68 for (int v = 0; v < Mesh.NumVertPositions; v++) 
69
70 float distSq = Mesh.VertTablePositions[v].LengthSq(); 
71 if (distSq > maxRadiusSq
72 maxRadiusSq = distSq
73
74 
75 return tSqrt(maxRadiusSq); 
76
77 
78 
79void tPolyModel::ComputeMinMaxRadius(float& minRadius, float& maxRadius) const 
80
81 float minRadiusSq = Infinity
82 float maxRadiusSq = 0.0f
83 for (int v = 0; v < Mesh.NumVertPositions; v++) 
84
85 float distSq = Mesh.VertTablePositions[v].LengthSq(); 
86 if (distSq > maxRadiusSq
87 maxRadiusSq = distSq
88 
89 if (distSq < minRadiusSq
90 minRadiusSq = distSq
91
92 
93 minRadius = tSqrt(minRadiusSq); 
94 maxRadius = tSqrt(maxRadiusSq); 
95
96 
97 
98tBox tPolyModel::ComputeBoundingBox() const 
99
100 tBox boundingBox
101 
102 for (int v = 0; v < Mesh.NumVertPositions; v++) 
103 boundingBox.AddPoint(Mesh.VertTablePositions[v]); 
104 
105 return boundingBox
106
107 
108 
109float tPolyModel::ComputeApproxArea() const 
110
111 // See http://mathworld.wolfram.com/TriangleArea.html and http://mathworld.wolfram.com/Circumradius.html 
112 float area = 0.0f
113 for (int f = 0; f < Mesh.NumFaces; f++) 
114
115 int start = f*3
116 tMath::tTriFace& face = Mesh.FaceTableVertPositionIndices[f]; 
117 
118 tVector3& v0 = Mesh.VertTablePositions[face.Index[0]]; 
119 tVector3& v1 = Mesh.VertTablePositions[face.Index[1]]; 
120 tVector3& v2 = Mesh.VertTablePositions[face.Index[2]]; 
121 tVector3 A = v1 - v0; float a = A.NormalizeGetLength(); 
122 tVector3 B = v2 - v0; float b = B.NormalizeGetLength(); 
123 tVector3 C = v1 - v2; float c = C.NormalizeGetLength(); 
124 
125 // The link above explains this name. 
126 float circumradius = a*b*c / tMath::tSqrt((a+b+c)*(b+c+-a)*(c+a-b)*(a+b-c)); 
127 float triArea = a*b*c / (4.0f * circumradius); 
128 area += triArea
129
130 
131 return area
132
133 
134 
135
136