root/trunk/thune/math3d.c

Revision 550, 10.9 kB (checked in by krobillard, 7 weeks ago)

Thune:

  • 8-bit string encoding is now Latin-1.
  • Now using WELL512a generator for random numbers.
  • Added hash-map datatype. List datatype can now be disabled in config.
  • Added project-point, remap.
  • Unique & fill now handle vector!.
  • File port 'read now retuns none when end of file reached.

Thune-GL:

  • Added draw-prog! & vertex-buffer! datatypes.
  • Display now accepts /fullscreen option.
  • Added particle-sim dialect.
Line 
1/*============================================================================
2    Thune Interpreter
3    Copyright (C) 2005-2006  Karl Robillard
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18===========================================================================*/
19
20
21#include "urlan.h"
22#include "math3d.h"
23#include "os.h"
24#include "os_math.h"
25
26
27enum eMatrixIndex
28{
29    k00 = 0,
30    k01,
31    k02,
32    k03,
33    k10,
34    k11,
35    k12,
36    k13,
37    k20,
38    k21,
39    k22,
40    k23,
41    k30,
42    k31,
43    k32,
44    k33,
45
46    kX = 12,
47    kY,
48    kZ
49};
50
51
52static float _identity[16] =
53{
54    1.0f, 0.0f, 0.0f, 0.0f,
55    0.0f, 1.0f, 0.0f, 0.0f,
56    0.0f, 0.0f, 1.0f, 0.0f,
57    0.0f, 0.0f, 0.0f, 1.0f
58};
59
60
61void ur_loadIdentity( float* mat )
62{
63    memCpy( mat, _identity, 16 * sizeof(float) );
64}
65
66
67void ur_loadRotation( float* mat, const float* axis, float radians )
68{
69    float x, y, z;
70    float c, s, t;
71
72    x = axis[0];
73    y = axis[1];
74    z = axis[2];
75
76    c = mathCosineF( radians );
77    s = mathSineF( radians );
78    t = 1.0f - c;
79
80    mat[ 0 ] = t*x*x + c;
81    mat[ 1 ] = t*x*y + s*z;
82    mat[ 2 ] = t*x*z - s*y;
83    mat[ 3 ] = 0.0f;
84
85    mat[ 4 ] = t*x*y - s*z;
86    mat[ 5 ] = t*y*y + c;
87    mat[ 6 ] = t*y*z + s*x;
88    mat[ 7 ] = 0.0f;
89
90    mat[  8 ] = t*x*z + s*y;
91    mat[  9 ] = t*y*z - s*x;
92    mat[ 10 ] = t*z*z + c;
93    mat[ 11 ] = 0.0f;
94
95    mat[ 12 ] = 0.0f;
96    mat[ 13 ] = 0.0f;
97    mat[ 14 ] = 0.0f;
98    mat[ 15 ] = 1.0f;
99}
100
101
102/*
103  Result can be the same matrix as A, but not B.
104*/
105void ur_matrixMult( const float* a, const float* b, float* result )
106{
107#define A(col,row)  a[(col<<2)+row]
108#define R(col,row)  result[(col<<2)+row]
109
110    int i;
111    for( i = 0; i < 4; i++ )
112    {
113        float ai0=A(0,i), ai1=A(1,i), ai2=A(2,i), ai3=A(3,i);
114        R(0,i) = ai0 * b[k00] + ai1 * b[k01] + ai2 * b[k02] + ai3 * b[k03];
115        R(1,i) = ai0 * b[k10] + ai1 * b[k11] + ai2 * b[k12] + ai3 * b[k13];
116        R(2,i) = ai0 * b[k20] + ai1 * b[k21] + ai2 * b[k22] + ai3 * b[k23];
117        R(3,i) = ai0 * b[k30] + ai1 * b[k31] + ai2 * b[k32] + ai3 * b[k33];
118    }
119}
120
121
122void ur_transLocal( float* mat, float x, float y, float z )
123{
124    if( x )
125    {
126        mat[ kX ] += mat[ k00 ] * x;
127        mat[ kY ] += mat[ k01 ] * x;
128        mat[ kZ ] += mat[ k02 ] * x;
129    }
130    if( y )
131    {
132        mat[ kX ] += mat[ k10 ] * y;
133        mat[ kY ] += mat[ k11 ] * y;
134        mat[ kZ ] += mat[ k12 ] * y;
135    }
136    if( z )
137    {
138        mat[ kX ] += mat[ k20 ] * z;
139        mat[ kY ] += mat[ k21 ] * z;
140        mat[ kZ ] += mat[ k22 ] * z;
141    }
142}
143
144
145/**
146  Transpose 3x3 submatrix to negate rotation.
147*/
148void ur_matrixTranspose( float* mat, const float* a )
149{
150    mat[ k00 ] = a[ k00 ];
151    mat[ k01 ] = a[ k10 ];
152    mat[ k02 ] = a[ k20 ];
153    mat[ k03 ] = a[ k03 ];
154
155    mat[ k10 ] = a[ k01 ];
156    mat[ k11 ] = a[ k11 ];
157    mat[ k12 ] = a[ k21 ];
158    mat[ k13 ] = a[ k13 ];
159
160    mat[ k20 ] = a[ k02 ];
161    mat[ k21 ] = a[ k12 ];
162    mat[ k22 ] = a[ k22 ];
163    mat[ k23 ] = a[ k23 ];
164}
165
166
167/**
168  Negates rotation and translation.
169*/
170void ur_matrixInverse( float* mat, const float* a )
171{
172    ur_matrixTranspose( mat, a );
173
174    // Negate translation.
175
176    mat[ kX ] = - (a[kX] * a[k00]) - (a[kY] * a[k01]) - (a[kZ] * a[k02]);
177    mat[ kY ] = - (a[kX] * a[k10]) - (a[kY] * a[k11]) - (a[kZ] * a[k12]);
178    mat[ kZ ] = - (a[kX] * a[k20]) - (a[kY] * a[k21]) - (a[kZ] * a[k22]);
179    mat[ k33 ] = a[ k33 ];
180}
181
182
183/*--------------------------------------------------------------------------*/
184
185
186/**
187  Returns the distance from vecA to vecB.
188*/
189float ur_distance( const float* vecA, const float* vecB )
190{
191    float dx, dy, dz;
192
193    dx = vecB[0] - vecA[0];
194    dy = vecB[1] - vecA[1];
195    dz = vecB[2] - vecA[2];
196
197    return mathSqrtF( dx * dx + dy * dy + dz * dz );
198}
199
200
201/**
202  Applies the entire matrix to this point.
203*/
204void ur_transform( float* pnt, const float* mat )
205{
206    float ox, oy, oz;
207
208    ox = pnt[0];
209    oy = pnt[1];
210    oz = pnt[2];
211
212    pnt[0] = mat[ k00 ] * ox + mat[ k10 ] * oy + mat[ k20 ] * oz + mat[ k30 ];
213    pnt[1] = mat[ k01 ] * ox + mat[ k11 ] * oy + mat[ k21 ] * oz + mat[ k31 ];
214    pnt[2] = mat[ k02 ] * ox + mat[ k12 ] * oy + mat[ k22 ] * oz + mat[ k32 ];
215}
216
217
218/**
219  Applies the upper 3x3 portion of the matrix to this point.
220*/
221void ur_transform3x3( float* pnt, const float* mat )
222{
223    float ox, oy, oz;
224
225    ox = pnt[0];
226    oy = pnt[1];
227    oz = pnt[2];
228
229    pnt[0] = mat[ k00 ] * ox + mat[ k10 ] * oy + mat[ k20 ] * oz;
230    pnt[1] = mat[ k01 ] * ox + mat[ k11 ] * oy + mat[ k21 ] * oz;
231    pnt[2] = mat[ k02 ] * ox + mat[ k12 ] * oy + mat[ k22 ] * oz;
232}
233
234
235/**
236  Result can be the same as either a or b.
237*/
238void ur_reflect( const float* a, const float* b, float* result )
239{
240    float dot2 = ur_dot(a, b) * 2.0f;
241
242    result[0] = a[0] - (b[0] * dot2);
243    result[1] = a[1] - (b[1] * dot2);
244    result[2] = a[2] - (b[2] * dot2);
245}
246
247
248/**
249  Returns shortest vector from line a-b to point.
250
251  \param a    First line endpoint.
252  \param b    Second line endpoint.
253  \param pnt
254  \param vec  Vector result.  This pointer may be the same as a, b, or pnt.
255*/
256void ur_lineToPoint( const float* a, const float* b, const float* pnt,
257                     float* vec )
258{
259    float dir[3];
260    float ft;
261
262    dir[0] = b[0] - a[0];
263    dir[1] = b[1] - a[1];
264    dir[2] = b[2] - a[2];
265
266    vec[0] = pnt[0] - a[0];
267    vec[1] = pnt[1] - a[1];
268    vec[2] = pnt[2] - a[2];
269
270    ft = ur_dot( vec, dir );
271    if( ft > 0.0 )
272    {
273        float rlen = ur_lengthSq( dir );
274        if( rlen < ft )
275        {
276            vec[0] -= dir[0];
277            vec[1] -= dir[1];
278            vec[2] -= dir[2];
279        }
280        else
281        {
282            ft /= rlen;
283            vec[0] -= ft * dir[0];
284            vec[1] -= ft * dir[1];
285            vec[2] -= ft * dir[2];
286        }
287    }
288}
289
290
291void ur_normalize( float* vec )
292{
293    float x, y, z;
294    float len;
295
296    x = vec[0];
297    y = vec[1];
298    z = vec[2];
299
300    len = mathSqrtF( x * x + y * y + z * z );
301    if( len )
302    {
303        len = 1.0f / len;
304        vec[0] = x * len;
305        vec[1] = y * len;
306        vec[2] = z * len;
307    }
308}
309
310
311/*--------------------------------------------------------------------------*/
312
313
314#if 0
315/**
316  Returns zero if invalid values were found.
317*/
318int ur_loadVectorBlock( float* vec, int count, UCell* blkV )
319{
320#define VEND    if(vec == vend) break
321
322    OBlock* blk = ur_block(blkV);
323    UCell* it  = blk->ptr.cells + blkV->series.it;
324    UCell* end = blk->ptr.cells + blk->used;
325    float* vend = vec + count;
326    int ok = 1;
327
328    while( it != end )
329    {
330        if( ur_is(it, UT_INT) )
331        {
332            *vec++ = (float) ur_int(it);
333            VEND;
334        }
335        else if( ur_is(it, UT_DECIMAL) )
336        {
337            *vec++ = (float) ur_decimal(it);
338            VEND;
339        }
340#if 0
341        else if( ur_is(it, UT_VEC3) )
342        {
343            *vec++ = it->vec3.x;
344            VEND;
345            *vec++ = it->vec3.y;
346            VEND;
347            *vec++ = it->vec3.z;
348            VEND;
349        }
350#endif
351        else
352        {
353            ok = 0;
354        }
355
356        ++it;
357    }
358
359    return ok;
360}
361#endif
362
363
364static void _coordToVec3( UCell* cell )
365{
366    ur_type(cell) = UT_VEC3;
367    cell->vec3.xyz[2] = (float) cell->coord.elem[2];
368    cell->vec3.xyz[1] = (float) cell->coord.elem[1];
369    cell->vec3.xyz[0] = (float) cell->coord.elem[0];
370}
371
372
373// (va vb -- dot)
374UR_CALL( uc_dot )
375{
376    UCell* prev;
377
378    prev = ur_s_prev(tos);
379    UR_S_DROP;
380
381    if( ur_is(tos, UT_VEC3) )
382        goto checkA;
383    if( ur_is(tos, UT_COORD) )
384    {
385        _coordToVec3( tos );
386        goto checkA;
387    }
388    return;
389
390checkA:
391
392    if( ur_is(prev, UT_VEC3) )
393        goto calc;
394    if( ur_is(prev, UT_COORD) )
395    {
396        _coordToVec3( prev );
397        goto calc;
398    }
399    return;
400
401calc:
402
403    ur_initType( prev, UT_DECIMAL );
404    ur_decimal(prev) = (double) ur_dot( prev->vec3.xyz, tos->vec3.xyz );
405}
406
407
408// (va vb -- cross)
409UR_CALL( uc_cross )
410{
411    float res[3];
412    UCell* prev;
413
414    prev = ur_s_prev(tos);
415    UR_S_DROP;
416
417    if( ur_is(tos, UT_VEC3) )
418        goto checkA;
419    if( ur_is(tos, UT_COORD) )
420    {
421        _coordToVec3( tos );
422        goto checkA;
423    }
424    return;
425
426checkA:
427
428    if( ur_is(prev, UT_VEC3) )
429        goto calc;
430    if( ur_is(prev, UT_COORD) )
431    {
432        _coordToVec3( prev );
433        goto calc;
434    }
435    return;
436
437calc:
438
439    ur_cross( prev->vec3.xyz, tos->vec3.xyz, res );
440    memCpy( prev->vec3.xyz, res, 3 * sizeof(float) );
441}
442
443
444// (vec -- vec)
445UR_CALL( uc_normalize )
446{
447    UR_CALL_UNUSED_TH
448    if( ur_is(tos, UT_VEC3) )
449    {
450        ur_normalize( tos->vec3.xyz );
451    }
452    else if( ur_is(tos, UT_COORD) )
453    {
454        _coordToVec3( tos );
455        ur_normalize( tos->vec3.xyz );
456    }
457}
458
459
460// (a b pnt -- pnt)
461UR_CALL( uc_project_point )
462{
463    UCell* b = ur_s_prev(tos);
464    UCell* a = ur_s_prev(b);
465    UR_CALL_UNUSED_TH
466    if( ur_is(tos, UT_VEC3) && ur_is(b, UT_VEC3) && ur_is(a, UT_VEC3) )
467    {
468        ur_lineToPoint( a->vec3.xyz, b->vec3.xyz, tos->vec3.xyz, b->vec3.xyz );
469        a->vec3.xyz[0] = tos->vec3.xyz[0] - b->vec3.xyz[0];
470        a->vec3.xyz[1] = tos->vec3.xyz[1] - b->vec3.xyz[1];
471        a->vec3.xyz[2] = tos->vec3.xyz[2] - b->vec3.xyz[2];
472        UR_S_DROPN( 2 );
473        return;
474    }
475    ur_throwErr( UR_ERR_DATATYPE, "project-point expected vec3!" );
476}
477
478
479// (vector n -- vector)
480UR_CALL( uc_set_stride )
481{
482    UCell* prev = ur_s_prev(tos);
483    UR_CALL_UNUSED_TH
484    if( ur_is(tos, UT_INT) && ur_is(prev, UT_VECTOR) )
485    {
486        ur_vectorStride(prev) = ur_int(tos);
487        UR_S_DROP;
488        return;
489    }
490    ur_throwErr( UR_ERR_DATATYPE, "set-stride expected vector! int!" );
491}
492
493
494/*
495  (vector map -- vector)
496*/
497UR_CALL( uc_remap )
498{
499    UCell* prev = ur_s_prev(tos);
500    if( ur_is(prev, UT_VECTOR) && ur_is(tos, UT_VECTOR) )
501    {
502        int32_t* vit;
503        int32_t* vend;
504        int32_t* map;
505        int32_t* mend;
506        uint32_t mcount;
507        uint32_t n;
508
509        if( (ur_vectorDT(prev) != UT_INT) || (ur_vectorDT(tos) != UT_INT) )
510            goto bad_dt;
511
512        ur_binaryMem( ut, prev, (uint8_t**) &vit, (uint8_t**) &vend );
513        ur_binaryMem( ut, tos,  (uint8_t**) &map, (uint8_t**) &mend );
514        mcount = mend - map;
515
516        while( vit != vend )
517        {
518            n = *vit;
519            if( n < mcount )
520                *vit = map[ n ];
521            ++vit;
522        }
523
524        UR_S_DROP;
525    }
526    return;
527
528bad_dt:
529
530    ur_throwErr( UR_ERR_DATATYPE, "remap expected two integer vector!" );
531}
532
533
534/* EOF */
Note: See TracBrowser for help on using the browser.