]> icculus.org git repositories - divverent/nexuiz.git/blob - misc/gtkradiant/singlepatches/gtkradiant-bp2texdeffix.diff
add brush primitives fixes
[divverent/nexuiz.git] / misc / gtkradiant / singlepatches / gtkradiant-bp2texdeffix.diff
1 Index: radiant/brush_primit.cpp
2 ===================================================================
3 --- radiant/brush_primit.cpp    (revision 297)
4 +++ radiant/brush_primit.cpp    (working copy)
5 @@ -388,8 +388,9 @@
6  //     ConvertTexMatWithQTexture( &f->brushprimit_texdef, NULL, &f->brushprimit_texdef, f->d_texture );
7  }
8  
9 -void BrushPrimitFaceToFace(face_t *face)
10 +void BrushPrimitFaceToFace(face_t *f)
11  {
12 +  /*
13    // we have parsed brush primitives and need conversion back to standard format
14    // NOTE: converting back is a quick hack, there's some information lost and we can't do anything about it
15    // FIXME: if we normalize the texture matrix to a standard 2x2 size, we end up with wrong scaling
16 @@ -399,6 +400,28 @@
17    TexMatToFakeTexCoords( aux.coords, face->texdef.shift, &face->texdef.rotate, face->texdef.scale );
18    face->texdef.scale[0]/=2.0;
19    face->texdef.scale[1]/=2.0;
20 +  */
21 +    vec3_t texX,texY;
22 +    vec3_t proj;
23 +    vec_t ST[3][5];
24 +
25 +    ComputeAxisBase(f->plane.normal,texX,texY);
26 +    VectorCopy(f->plane.normal,proj);
27 +    VectorScale(proj,f->plane.dist,proj);
28 +    VectorCopy(proj,ST[0]);
29 +    VectorCopy(texX,ST[1]);
30 +    VectorAdd(ST[1],proj,ST[1]);
31 +    VectorCopy(texY,ST[2]);
32 +    VectorAdd(ST[2],proj,ST[2]);
33 +
34 +       ST[0][3] = f->brushprimit_texdef.coords[0][2];
35 +       ST[0][4] = f->brushprimit_texdef.coords[1][2];
36 +       ST[1][3] = f->brushprimit_texdef.coords[0][0] + ST[0][3];
37 +       ST[1][4] = f->brushprimit_texdef.coords[1][0] + ST[0][4];
38 +       ST[2][3] = f->brushprimit_texdef.coords[0][1] + ST[0][3];
39 +       ST[2][4] = f->brushprimit_texdef.coords[1][1] + ST[0][4];
40 +
41 +       Face_TexdefFromTextureCoordinates(ST[0], ST[1], ST[2], f->d_texture, f);
42  }
43  
44  // TEXTURE LOCKING -----------------------------------------------------------------------------------------------------
45 Index: radiant/brush.cpp
46 ===================================================================
47 --- radiant/brush.cpp   (revision 297)
48 +++ radiant/brush.cpp   (working copy)
49 @@ -423,7 +423,93 @@
50         }
51  }
52  
53 +long double HighestImpactSign(long double a, long double b)
54 +{
55 +       // returns the sign of the value with larger abs
56 +       if(a+b > 0)
57 +               return +1;
58 +       else
59 +               return -1;
60 +}
61 +
62 +void Face_TexdefFromTextureVectors (face_t *f, long double STfromXYZ[2][4], vec3_t pvecs[2], int sv, int tv)
63 +{
64 +       texdef_t *td;
65 +       qtexture_t *q;
66 +       int j;
67 +       long double ang;
68 +
69 +    td = &f->texdef;
70 +    q = f->d_texture;
71 +
72 +       // undo the texture transform
73 +    for (j=0 ; j<4 ; j++) {
74 +        STfromXYZ[0][j] *= q->width;
75 +        STfromXYZ[1][j] *= q->height;
76 +    }
77 +
78 +    // shift
79 +    td->shift[0] = STfromXYZ[0][3];
80 +    td->shift[1] = STfromXYZ[1][3];
81 +
82  /*
83 +       SOLVE:
84 +               STfromXYZ[0][sv] = (cosv * pvecs[0][sv] - sinv * pvecs[0][tv]) / td->scale[0];
85 +               STfromXYZ[0][tv] = (sinv * pvecs[0][sv] + cosv * pvecs[0][tv]) / td->scale[0];
86 +               STfromXYZ[1][sv] = (cosv * pvecs[1][sv] - sinv * pvecs[1][tv]) / td->scale[1];
87 +               STfromXYZ[1][tv] = (sinv * pvecs[1][sv] + cosv * pvecs[1][tv]) / td->scale[1];
88 +       FOR:
89 +               sinv, cosv, td->scale[0], td->scale[1]
90 +       WE KNOW:
91 +               sinv^2 + cosv^2 = 1
92 +               pvecs[0][sv] is +/-1
93 +               pvecs[0][tv] is 0
94 +               pvecs[1][sv] is 0
95 +               pvecs[1][tv] is +/-1
96 +       THUS:
97 +               STfromXYZ[0][sv] = +cosv * pvecs[0][sv] / td->scale[0];
98 +               STfromXYZ[0][tv] = +sinv * pvecs[0][sv] / td->scale[0];
99 +               STfromXYZ[1][sv] = -sinv * pvecs[1][tv] / td->scale[1];
100 +               STfromXYZ[1][tv] = +cosv * pvecs[1][tv] / td->scale[1];
101 +*/
102 +
103 +       td->scale[0] = sqrt(STfromXYZ[0][sv]*STfromXYZ[0][sv] + STfromXYZ[0][tv]*STfromXYZ[0][tv]);
104 +       td->scale[1] = sqrt(STfromXYZ[1][sv]*STfromXYZ[1][sv] + STfromXYZ[1][tv]*STfromXYZ[1][tv]);
105 +
106 +       if(td->scale[0]) td->scale[0] = 1 / td->scale[0]; // avoid NaNs
107 +       if(td->scale[1]) td->scale[1] = 1 / td->scale[1];
108 +
109 +       long double sign0tv = (STfromXYZ[0][tv] > 0) ? +1 : -1;
110 +       ang = atan2( sign0tv * STfromXYZ[0][tv], sign0tv * STfromXYZ[0][sv]); // atan2(y, x) with y positive is in [0, PI[
111 +
112 +       // STOP
113 +       // We have until now ignored the fact that td->scale[0] or td->scale[1] may
114 +       // have either sign (+ or -). Due to roundoff errors, our choice of
115 +       // sign0tv may even have been wrong in a sense. 
116 +       // sign0tv may NOT indicate the appropriate sign for td->scale[0] (namely,
117 +       // if cosv is near zero)!
118 +       // let's look at the signs again
119 +       //   sign0sv =  signcosv * pvecs[0][sv] / td->scale[0]sign
120 +       //   sign0tv =             pvecs[0][sv] / td->scale[0]sign
121 +       //   sign1sv = -1        * pvecs[1][tv] / td->scale[1]sign
122 +       //   sign1tv =  signcosv * pvecs[1][tv] / td->scale[1]sign
123 +       // -->
124 +       //   td->scale[1]sign =  sign1tv * signcosv * pvecs[1][tv]
125 +       //   td->scale[1]sign = -sign1sv * signsinv * pvecs[1][tv]
126 +       //   td->scale[0]sign =  sign0tv * signsinv * pvecs[0][sv]
127 +       //   td->scale[0]sign =  sign0sv * signcosv * pvecs[0][sv]
128 +       // which to choose?
129 +       // the one with the larger impact on the original texcoords, of course
130 +       // to minimize the effect of roundoff errors that may flip the signs!
131 +       
132 +       td->scale[0] *= HighestImpactSign(STfromXYZ[0][tv] * +sin(ang), STfromXYZ[0][sv] * cos(ang)) * pvecs[0][sv];
133 +       td->scale[1] *= HighestImpactSign(STfromXYZ[1][sv] * -sin(ang), STfromXYZ[1][tv] * cos(ang)) * pvecs[1][tv];
134 +
135 +       td->rotate = ang * 180 / Q_PI; // FIXME possibly snap this to 0/90/180 (270 can't happen)?
136 +}
137 +
138 +
139 +/*
140  ================
141  Face_MakePlane
142  ================
143 @@ -462,6 +548,135 @@
144         xyzst[4] = DotProduct (xyzst, STfromXYZ[1]) + STfromXYZ[1][3];
145  }
146  
147 +long double SarrusDetScalar(long double a1, long double b1, long double c1, long double a2, long double b2, long double c2, long double a3, long double b3, long double c3)
148 +{
149 +       return a1 * b2 * c3 + a2 * b3 * c1 + a3 * b1 * c2
150 +            - a1 * c2 * b3 - a2 * c3 * b1 - a3 * c1 * b2;
151 +}
152 +
153 +void SarrusSolve(long double a1, long double b1, long double c1, long double d1, long double a2, long double b2, long double c2, long double d2, long double a3, long double b3, long double c3, long double d3, long double *a, long double *b, long double *c)
154 +{
155 +       long double det;
156 +       det = SarrusDetScalar(a1, b1, c1,
157 +                             a2, b2, c2,
158 +                                                 a3, b3, c3);
159 +       *a =  SarrusDetScalar(d1, b1, c1,
160 +                             d2, b2, c2,
161 +                                                 d3, b3, c3) / det;
162 +       *b =  SarrusDetScalar(a1, d1, c1,
163 +                             a2, d2, c2,
164 +                                                 a3, d3, c3) / det;
165 +       *c =  SarrusDetScalar(a1, b1, d1,
166 +                             a2, b2, d2,
167 +                                                 a3, b3, d3) / det;
168 +}
169 +
170 +void Face_TexdefFromTextureCoordinates ( float *xyzst1, float *xyzst2, float *xyzst3, qtexture_t *q, face_t *f)
171 +{
172 +       vec3_t          pvecs[2];
173 +       int sv, tv, uv;
174 +
175 +    long double   STfromXYZ[2][4];
176 +
177 +    // get natural texture axis
178 +    TextureAxisFromPlane(&f->plane, pvecs[0], pvecs[1]);
179 +
180 +    if (pvecs[0][0])
181 +        sv = 0;
182 +    else if (pvecs[0][1])
183 +        sv = 1;
184 +    else
185 +        sv = 2;
186 +
187 +    if (pvecs[1][0])
188 +        tv = 0;
189 +    else if (pvecs[1][1])
190 +        tv = 1;
191 +    else
192 +        tv = 2;
193 +
194 +       uv = 3 - sv - tv; // the "other one"
195 +
196 +    // find the STfromXYZ 4-vectors
197 +       /*
198 +       SARRUS-SOLVE:
199 +               xyzst1[3] == xyzst1[sv] * STfromXYZ[0][sv] + xyzst1[tv] * STfromXYZ[0][tv] + STfromXYZ[0][3];
200 +               xyzst2[3] == xyzst2[sv] * STfromXYZ[0][sv] + xyzst2[tv] * STfromXYZ[0][tv] + STfromXYZ[0][3];
201 +               xyzst3[3] == xyzst3[sv] * STfromXYZ[0][sv] + xyzst3[tv] * STfromXYZ[0][tv] + STfromXYZ[0][3];
202 +       FOR: STfromXYZ[0]
203 +       GIVEN: one coord of them (uv) is empty (see Face_TextureVectors)
204 +       SARRUS-SOLVE:
205 +               xyzst1[4] == xyzst1[sv] * STfromXYZ[1][sv] + xyzst1[tv] * STfromXYZ[1][tv] + STfromXYZ[1][3];
206 +               xyzst2[4] == xyzst2[sv] * STfromXYZ[1][sv] + xyzst2[tv] * STfromXYZ[1][tv] + STfromXYZ[1][3];
207 +               xyzst3[4] == xyzst3[sv] * STfromXYZ[1][sv] + xyzst3[tv] * STfromXYZ[1][tv] + STfromXYZ[1][3];
208 +       FOR: STfromXYZ[1]
209 +       GIVEN: one coord of them (uv) is empty (see Face_TextureVectors)
210 +       */
211 +
212 +       STfromXYZ[0][uv] = 0;
213 +       SarrusSolve(
214 +               xyzst1[sv],        xyzst1[tv],        1,               xyzst1[3],
215 +               xyzst2[sv],        xyzst2[tv],        1,               xyzst2[3],
216 +               xyzst3[sv],        xyzst3[tv],        1,               xyzst3[3],
217 +               &STfromXYZ[0][sv], &STfromXYZ[0][tv], &STfromXYZ[0][3]
218 +       );
219 +
220 +       STfromXYZ[1][uv] = 0;
221 +       SarrusSolve(
222 +               xyzst1[sv],        xyzst1[tv],        1,               xyzst1[4],
223 +               xyzst2[sv],        xyzst2[tv],        1,               xyzst2[4],
224 +               xyzst3[sv],        xyzst3[tv],        1,               xyzst3[4],
225 +               &STfromXYZ[1][sv], &STfromXYZ[1][tv], &STfromXYZ[1][3]
226 +       );
227 +
228 +       /*
229 +       printf("%s\n", q->name);
230 +
231 +       printf("%f == %Lf\n", xyzst1[3], DotProduct (xyzst1, STfromXYZ[0]) + STfromXYZ[0][3]);
232 +       printf("%f == %Lf\n", xyzst2[3], DotProduct (xyzst2, STfromXYZ[0]) + STfromXYZ[0][3]);
233 +       printf("%f == %Lf\n", xyzst3[3], DotProduct (xyzst3, STfromXYZ[0]) + STfromXYZ[0][3]);
234 +       printf("%f == %Lf\n", xyzst1[4], DotProduct (xyzst1, STfromXYZ[1]) + STfromXYZ[1][3]);
235 +       printf("%f == %Lf\n", xyzst2[4], DotProduct (xyzst2, STfromXYZ[1]) + STfromXYZ[1][3]);
236 +       printf("%f == %Lf\n", xyzst3[4], DotProduct (xyzst3, STfromXYZ[1]) + STfromXYZ[1][3]);
237 +
238 +    float   newSTfromXYZ[2][4];
239 +
240 +       printf("old: %Lf,%Lf,%Lf,%Lf %Lf,%Lf,%Lf,%Lf\n",
241 +               STfromXYZ[0][0], STfromXYZ[0][1], STfromXYZ[0][2], STfromXYZ[0][3],
242 +               STfromXYZ[1][0], STfromXYZ[1][1], STfromXYZ[1][2], STfromXYZ[1][3]);
243 +       */
244 +
245 +       Face_TexdefFromTextureVectors (f,  STfromXYZ, pvecs, sv, tv);
246 +
247 +       /*
248 +       Face_TextureVectors(f, newSTfromXYZ);
249 +
250 +       printf("new: %f,%f,%f,%f %f,%f,%f,%f\n",
251 +               newSTfromXYZ[0][0], newSTfromXYZ[0][1], newSTfromXYZ[0][2], newSTfromXYZ[0][3],
252 +               newSTfromXYZ[1][0], newSTfromXYZ[1][1], newSTfromXYZ[1][2], newSTfromXYZ[1][3]);
253 +
254 +       float newxyzst1[5];
255 +       float newxyzst2[5];
256 +       float newxyzst3[5];
257 +       VectorCopy(xyzst1, newxyzst1);
258 +       VectorCopy(xyzst2, newxyzst2);
259 +       VectorCopy(xyzst3, newxyzst3);
260 +       EmitTextureCoordinates (newxyzst1, q, f);
261 +       EmitTextureCoordinates (newxyzst2, q, f);
262 +       EmitTextureCoordinates (newxyzst3, q, f);
263 +       printf("Face_TexdefFromTextureCoordinates: %f,%f %f,%f %f,%f -> %f,%f %f,%f %f,%f\n",
264 +               xyzst1[3], xyzst1[4],
265 +               xyzst2[3], xyzst2[4],
266 +               xyzst3[3], xyzst3[4],
267 +               newxyzst1[3], newxyzst1[4],
268 +               newxyzst2[3], newxyzst2[4],
269 +               newxyzst3[3], newxyzst3[4]);
270 +       // TODO why do these differ, but not the previous ones? this makes no sense whatsoever
271 +       */
272 +}
273 +
274 +
275 +
276  //==========================================================================
277  
278  /*
279 Index: radiant/qe3.h
280 ===================================================================
281 --- radiant/qe3.h       (revision 297)
282 +++ radiant/qe3.h       (working copy)
283 @@ -535,6 +535,7 @@
284  void EmitBrushPrimitTextureCoordinates(face_t *, winding_t *);
285  // EmitTextureCoordinates, is old code used for brush to brush primitive conversion
286  void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f);
287 +void Face_TexdefFromTextureCoordinates ( float *xyzst1, float *xyzst2, float *xyzst3, qtexture_t *q, face_t *f);
288  //void BrushPrimit_Parse(brush_t *);
289  // compute a fake shift scale rot representation from the texture matrix
290  void TexMatToFakeTexCoords( vec_t texMat[2][3], float shift[2], float *rot, float scale[2] );