1 """Module which contains all spells that check something in a cgf file."""
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 from itertools import izip
43 from tempfile import TemporaryFile
44
45 from pyffi.formats.cgf import CgfFormat
46 from pyffi.spells.cgf import CgfSpell
47
48 from pyffi.utils.mathutils import *
49
51 """Like the original read-write spell, but with additional file size
52 check."""
53
54 SPELLNAME = "check_readwrite"
55
56 - def dataentry(self):
57 self.toaster.msgblockbegin("writing to temporary file")
58 f_tmp = TemporaryFile()
59 try:
60 total_padding = self.data.write(f_tmp)
61
62
63
64 self.toaster.msg("comparing file sizes")
65 self.stream.seek(0, 2)
66 f_tmp.seek(0, 2)
67 if self.stream.tell() != f_tmp.tell():
68 self.toaster.msg("original size: %i" % self.stream.tell())
69 self.toaster.msg("written size: %i" % f_tmp.tell())
70 self.toaster.msg("padding: %i" % total_padding)
71 if self.stream.tell() > f_tmp.tell() or self.stream.tell() + total_padding < f_tmp.tell():
72 f_tmp.seek(0)
73 f_debug = open("debug.cgf", "wb")
74 f_debug.write(f_tmp.read(-1))
75 f_debug.close()
76 raise Exception('write check failed: file sizes differ by more than padding')
77 finally:
78 f_tmp.close()
79 self.toaster.msgblockend()
80
81
82 return False
83
85 """This spell checks the tangent space calculation.
86 Only useful for debugging.
87 """
88
89 SPELLNAME = "check_tangentspace"
90 SENSITIVITY = 0.1
91
94
97
98 - def branchentry(self, branch):
99 if not isinstance(branch, CgfFormat.MeshChunk):
100
101 return True
102
103
104 if not (branch.normals_data and branch.tangents_data):
105 return True
106
107 oldtangents = [tangent for tangent in branch.tangents_data.tangents]
108
109 self.toaster.msg("recalculating new tangent space")
110 branch.update_tangent_space()
111 newtangents = [tangent for tangent in branch.tangents_data.tangents]
112
113 self.toaster.msgblockbegin("validating and checking old with new")
114
115 for norm, oldtangent, newtangent in izip(branch.normals_data.normals,
116 oldtangents, newtangents):
117
118
119 norm = (norm.x, norm.y, norm.z)
120 tan = tuple(x / 32767.0
121 for x in (oldtangent[0].x,
122 oldtangent[0].y,
123 oldtangent[0].z))
124 bin = tuple(x / 32767.0
125 for x in (oldtangent[1].x,
126 oldtangent[1].y,
127 oldtangent[1].z))
128 if abs(vecNorm(norm) - 1) > self.SENSITIVITY:
129 self.toaster.logger.warn("normal has non-unit norm")
130 if abs(vecNorm(tan) - 1) > self.SENSITIVITY:
131 self.toaster.logger.warn("oldtangent has non-unit norm")
132 if abs(vecNorm(bin) - 1) > self.SENSITIVITY:
133 self.toaster.logger.warn("oldbinormal has non-unit norm")
134 if (oldtangent[0].w != oldtangent[1].w):
135 raise ValueError(
136 "inconsistent oldtangent w coordinate (%i != %i)"
137 % (oldtangent[0].w, oldtangent[1].w))
138 if not (oldtangent[0].w in (-32767, 32767)):
139 raise ValueError(
140 "invalid oldtangent w coordinate (%i)" % oldtangent[0].w)
141 if oldtangent[0].w > 0:
142 cross = vecCrossProduct(tan, bin)
143 else:
144 cross = vecCrossProduct(bin, tan)
145 crossnorm = vecNorm(cross)
146 if abs(crossnorm - 1) > self.SENSITIVITY:
147
148 self.toaster.logger.warn("tan and bin not orthogonal")
149 self.toaster.logger.warn("%s %s" % (tan, bin))
150 self.toaster.logger.warn("(error is %f)"
151 % abs(crossnorm - 1))
152 cross = vecscalarMul(cross, 1.0/crossnorm)
153 if vecDistance(norm, cross) > self.SENSITIVITY:
154 self.toaster.logger.warn(
155 "norm not cross product of tangent and binormal")
156
157
158
159
160 self.toaster.logger.warn(
161 "(error is %f)" % vecDistance(norm, cross))
162
163
164 if sum((abs(oldtangent[0].x - newtangent[0].x),
165 abs(oldtangent[0].y - newtangent[0].y),
166 abs(oldtangent[0].z - newtangent[0].z),
167 abs(oldtangent[0].w - newtangent[0].w),
168 abs(oldtangent[1].x - newtangent[1].x),
169 abs(oldtangent[1].y - newtangent[1].y),
170 abs(oldtangent[1].z - newtangent[1].z),
171 abs(oldtangent[1].w - newtangent[1].w))) > self.SENSITIVITY * 32767.0:
172 ntan = tuple(x / 32767.0 for x in (newtangent[0].x, newtangent[0].y, newtangent[0].z))
173 nbin = tuple(x / 32767.0 for x in (newtangent[1].x, newtangent[1].y, newtangent[1].z))
174 self.toaster.logger.warn("old and new tangents differ substantially")
175 self.toaster.logger.warn("old tangent")
176 self.toaster.logger.warn("%s %s" % (tan, bin))
177 self.toaster.logger.warn("new tangent")
178 self.toaster.logger.warn("%s %s" % (ntan, nbin))
179
180 self.toaster.msgblockend()
181
183 """This spell checks if a model has vertex colors.
184 Only useful for debugging.
185 """
186
187
188 SPELLNAME = "check_vcols"
189
192
195
196 - def branchentry(self, branch):
197 if isinstance(branch, CgfFormat.MeshChunk):
198 if branch.has_vertex_colors:
199 self.toaster.msg("has vertex colors!")
200 else:
201
202 return True
203