45ad36d0093feefd941dacad2335aac27099f8b2
[blender.git] / source / blender / python / api2_2x / vector.c
1 /*
2  * $Id: vector.c 12314 2007-10-20 20:24:09Z campbellbarton $
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * 
26  * Contributor(s): Willian P. Germano & Joseph Gilbert, Ken Hughes
27  *
28  * ***** END GPL/BL DUAL LICENSE BLOCK *****
29  */
30
31 #include "Mathutils.h"
32
33 #include "BLI_blenlib.h"
34 #include "BKE_utildefines.h"
35 #include "BLI_arithb.h"
36 #include "gen_utils.h"
37
38
39 /*-------------------------DOC STRINGS ---------------------------*/
40 char Vector_Zero_doc[] = "() - set all values in the vector to 0";
41 char Vector_Normalize_doc[] = "() - normalize the vector";
42 char Vector_Negate_doc[] = "() - changes vector to it's additive inverse";
43 char Vector_Resize2D_doc[] = "() - resize a vector to [x,y]";
44 char Vector_Resize3D_doc[] = "() - resize a vector to [x,y,z]";
45 char Vector_Resize4D_doc[] = "() - resize a vector to [x,y,z,w]";
46 char Vector_toPoint_doc[] = "() - create a new Point Object from this vector";
47 char Vector_ToTrackQuat_doc[] = "(track, up) - extract a quaternion from the vector and the track and up axis";
48 char Vector_copy_doc[] = "() - return a copy of the vector";
49 /*-----------------------METHOD DEFINITIONS ----------------------*/
50 struct PyMethodDef Vector_methods[] = {
51         {"zero", (PyCFunction) Vector_Zero, METH_NOARGS, Vector_Zero_doc},
52         {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, Vector_Normalize_doc},
53         {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, Vector_Negate_doc},
54         {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, Vector_Resize2D_doc},
55         {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize2D_doc},
56         {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize2D_doc},
57         {"toPoint", (PyCFunction) Vector_toPoint, METH_NOARGS, Vector_toPoint_doc},
58         {"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, Vector_ToTrackQuat_doc},
59         {"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc},
60         {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc},
61         {NULL, NULL, 0, NULL}
62 };
63
64 /*-----------------------------METHODS----------------------------
65   --------------------------Vector.toPoint()----------------------
66   create a new point object to represent this vector */
67 PyObject *Vector_toPoint(VectorObject * self)
68 {
69         float coord[3];
70         int i;
71
72         if(self->size < 2 || self->size > 3) {
73                 return EXPP_ReturnPyObjError(PyExc_AttributeError,
74                         "Vector.toPoint(): inappropriate vector size - expects 2d or 3d vector\n");
75         } 
76         for(i = 0; i < self->size; i++){
77                 coord[i] = self->vec[i];
78         }
79         
80         return newPointObject(coord, self->size, Py_NEW);
81 }
82 /*----------------------------Vector.zero() ----------------------
83   set the vector data to 0,0,0 */
84 PyObject *Vector_Zero(VectorObject * self)
85 {
86         int i;
87         for(i = 0; i < self->size; i++) {
88                 self->vec[i] = 0.0f;
89         }
90         return EXPP_incr_ret((PyObject*)self);
91 }
92 /*----------------------------Vector.normalize() -----------------
93   normalize the vector data to a unit vector */
94 PyObject *Vector_Normalize(VectorObject * self)
95 {
96         int i;
97         float norm = 0.0f;
98
99         for(i = 0; i < self->size; i++) {
100                 norm += self->vec[i] * self->vec[i];
101         }
102         norm = (float) sqrt(norm);
103         for(i = 0; i < self->size; i++) {
104                 self->vec[i] /= norm;
105         }
106         return EXPP_incr_ret((PyObject*)self);
107 }
108
109
110 /*----------------------------Vector.resize2D() ------------------
111   resize the vector to x,y */
112 PyObject *Vector_Resize2D(VectorObject * self)
113 {
114         if(self->wrapped==Py_WRAP)
115                 return EXPP_ReturnPyObjError(PyExc_TypeError,
116                         "vector.resize2d(): cannot resize wrapped data - only python vectors\n");
117
118         self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2));
119         if(self->vec == NULL)
120                 return EXPP_ReturnPyObjError(PyExc_MemoryError,
121                         "vector.resize2d(): problem allocating pointer space\n\n");
122         
123         self->size = 2;
124         return EXPP_incr_ret((PyObject*)self);
125 }
126 /*----------------------------Vector.resize3D() ------------------
127   resize the vector to x,y,z */
128 PyObject *Vector_Resize3D(VectorObject * self)
129 {
130         if (self->wrapped==Py_WRAP)
131                 return EXPP_ReturnPyObjError(PyExc_TypeError,
132                         "vector.resize3d(): cannot resize wrapped data - only python vectors\n");
133
134         self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3));
135         if(self->vec == NULL)
136                 return EXPP_ReturnPyObjError(PyExc_MemoryError,
137                         "vector.resize3d(): problem allocating pointer space\n\n");
138         
139         if(self->size == 2)
140                 self->vec[2] = 0.0f;
141         
142         self->size = 3;
143         return EXPP_incr_ret((PyObject*)self);
144 }
145 /*----------------------------Vector.resize4D() ------------------
146   resize the vector to x,y,z,w */
147 PyObject *Vector_Resize4D(VectorObject * self)
148 {
149         if(self->wrapped==Py_WRAP)
150                 return EXPP_ReturnPyObjError(PyExc_TypeError,
151                         "vector.resize4d(): cannot resize wrapped data - only python vectors\n");
152
153         self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4));
154         if(self->vec == NULL)
155                 return EXPP_ReturnPyObjError(PyExc_MemoryError,
156                         "vector.resize4d(): problem allocating pointer space\n\n");
157         
158         if(self->size == 2){
159                 self->vec[2] = 0.0f;
160                 self->vec[3] = 1.0f;
161         }else if(self->size == 3){
162                 self->vec[3] = 1.0f;
163         }
164         self->size = 4;
165         return EXPP_incr_ret((PyObject*)self);
166 }
167 /*----------------------------Vector.toTrackQuat(track, up) ----------------------
168   extract a quaternion from the vector and the track and up axis */
169 PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
170 {
171         float vec[3];
172         char *strack, *sup;
173         short track = 2, up = 1;
174
175         if( !PyArg_ParseTuple ( args, "|ss", &strack, &sup ) ) {
176                 return EXPP_ReturnPyObjError( PyExc_TypeError, 
177                         "expected optional two strings\n" );
178         }
179         if (self->size != 3) {
180                 return EXPP_ReturnPyObjError( PyExc_TypeError, "only for 3D vectors\n" );
181         }
182
183         if (strack) {
184                 if (strlen(strack) == 2) {
185                         if (strack[0] == '-') {
186                                 switch(strack[1]) {
187                                         case 'X':
188                                         case 'x':
189                                                 track = 3;
190                                                 break;
191                                         case 'Y':
192                                         case 'y':
193                                                 track = 4;
194                                                 break;
195                                         case 'z':
196                                         case 'Z':
197                                                 track = 5;
198                                                 break;
199                                         default:
200                                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
201                                                                                   "only X, -X, Y, -Y, Z or -Z for track axis\n" );
202                                 }
203                         }
204                         else {
205                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
206                                                                   "only X, -X, Y, -Y, Z or -Z for track axis\n" );
207                         }
208                 }
209                 else if (strlen(strack) == 1) {
210                         switch(strack[0]) {
211                         case '-':
212                         case 'X':
213                         case 'x':
214                                 track = 0;
215                                 break;
216                         case 'Y':
217                         case 'y':
218                                 track = 1;
219                                 break;
220                         case 'z':
221                         case 'Z':
222                                 track = 2;
223                                 break;
224                         default:
225                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
226                                                                   "only X, -X, Y, -Y, Z or -Z for track axis\n" );
227                         }
228                 }
229                 else {
230                         return EXPP_ReturnPyObjError( PyExc_ValueError,
231                                                           "only X, -X, Y, -Y, Z or -Z for track axis\n" );
232                 }
233         }
234
235         if (sup) {
236                 if (strlen(sup) == 1) {
237                         switch(*sup) {
238                         case 'X':
239                         case 'x':
240                                 up = 0;
241                                 break;
242                         case 'Y':
243                         case 'y':
244                                 up = 1;
245                                 break;
246                         case 'z':
247                         case 'Z':
248                                 up = 2;
249                                 break;
250                         default:
251                                 return EXPP_ReturnPyObjError( PyExc_ValueError,
252                                                                   "only X, Y or Z for up axis\n" );
253                         }
254                 }
255                 else {
256                         return EXPP_ReturnPyObjError( PyExc_ValueError,
257                                                           "only X, Y or Z for up axis\n" );
258                 }
259         }
260
261         if (track == up) {
262                         return EXPP_ReturnPyObjError( PyExc_ValueError,
263                                                       "Can't have the same axis for track and up\n" );
264         }
265
266         /*
267                 flip vector around, since vectoquat expect a vector from target to tracking object 
268                 and the python function expects the inverse (a vector to the target).
269         */
270         vec[0] = -self->vec[0];
271         vec[1] = -self->vec[1];
272         vec[2] = -self->vec[2];
273
274         return newQuaternionObject(vectoquat(vec, track, up), Py_NEW);
275 }
276
277
278
279 /*----------------------------Vector.copy() --------------------------------------
280   return a copy of the vector */
281 PyObject *Vector_copy(VectorObject * self)
282 {
283         return newVectorObject(self->vec, self->size, Py_NEW);
284 }
285
286 /*----------------------------dealloc()(internal) ----------------
287   free the py_object */
288 static void Vector_dealloc(VectorObject * self)
289 {
290         /* only free non wrapped */
291         if(self->wrapped != Py_WRAP){
292                 PyMem_Free(self->vec);
293         }
294         PyObject_DEL(self);
295 }
296
297 /*----------------------------print object (internal)-------------
298   print the object to screen */
299 static PyObject *Vector_repr(VectorObject * self)
300 {
301         int i;
302         char buffer[48], str[1024];
303
304         BLI_strncpy(str,"[",1024);
305         for(i = 0; i < self->size; i++){
306                 if(i < (self->size - 1)){
307                         sprintf(buffer, "%.6f, ", self->vec[i]);
308                         strcat(str,buffer);
309                 }else{
310                         sprintf(buffer, "%.6f", self->vec[i]);
311                         strcat(str,buffer);
312                 }
313         }
314         strcat(str, "](vector)");
315
316         return PyString_FromString(str);
317 }
318 /*---------------------SEQUENCE PROTOCOLS------------------------
319   ----------------------------len(object)------------------------
320   sequence length*/
321 static int Vector_len(VectorObject * self)
322 {
323         return self->size;
324 }
325 /*----------------------------object[]---------------------------
326   sequence accessor (get)*/
327 static PyObject *Vector_item(VectorObject * self, int i)
328 {
329         if(i < 0 || i >= self->size)
330                 return EXPP_ReturnPyObjError(PyExc_IndexError,
331                 "vector[index]: out of range\n");
332
333         return PyFloat_FromDouble(self->vec[i]);
334
335 }
336 /*----------------------------object[]-------------------------
337   sequence accessor (set)*/
338 static int Vector_ass_item(VectorObject * self, int i, PyObject * ob)
339 {
340         
341         if(!(PyNumber_Check(ob))) { /* parsed item not a number */
342                 return EXPP_ReturnIntError(PyExc_TypeError, 
343                         "vector[index] = x: index argument not a number\n");
344         }
345
346         if(i < 0 || i >= self->size){
347                 return EXPP_ReturnIntError(PyExc_IndexError,
348                         "vector[index] = x: assignment index out of range\n");
349         }
350         self->vec[i] = (float)PyFloat_AsDouble(ob);
351         return 0;
352 }
353
354 /*----------------------------object[z:y]------------------------
355   sequence slice (get) */
356 static PyObject *Vector_slice(VectorObject * self, int begin, int end)
357 {
358         PyObject *list = NULL;
359         int count;
360
361         CLAMP(begin, 0, self->size);
362         if (end<0) end= self->size+end+1;
363         CLAMP(end, 0, self->size);
364         begin = MIN2(begin,end);
365
366         list = PyList_New(end - begin);
367         for(count = begin; count < end; count++) {
368                 PyList_SetItem(list, count - begin,
369                                 PyFloat_FromDouble(self->vec[count]));
370         }
371
372         return list;
373 }
374 /*----------------------------object[z:y]------------------------
375   sequence slice (set) */
376 static int Vector_ass_slice(VectorObject * self, int begin, int end,
377                              PyObject * seq)
378 {
379         int i, y, size = 0;
380         float vec[4];
381         PyObject *v;
382
383         CLAMP(begin, 0, self->size);
384         if (end<0) end= self->size+end+1;
385         CLAMP(end, 0, self->size);
386         begin = MIN2(begin,end);
387
388         size = PySequence_Length(seq);
389         if(size != (end - begin)){
390                 return EXPP_ReturnIntError(PyExc_TypeError,
391                         "vector[begin:end] = []: size mismatch in slice assignment\n");
392         }
393
394         for (i = 0; i < size; i++) {
395                 v = PySequence_GetItem(seq, i);
396                 if (v == NULL) { /* Failed to read sequence */
397                         return EXPP_ReturnIntError(PyExc_RuntimeError, 
398                                 "vector[begin:end] = []: unable to read sequence\n");
399                 }
400                 
401                 if(!PyNumber_Check(v)) { /* parsed item not a number */
402                         Py_DECREF(v);
403                         return EXPP_ReturnIntError(PyExc_TypeError, 
404                                 "vector[begin:end] = []: sequence argument not a number\n");
405                 }
406
407                 vec[i] = (float)PyFloat_AsDouble(v);
408                 Py_DECREF(v);
409         }
410         /*parsed well - now set in vector*/
411         for(y = 0; y < size; y++){
412                 self->vec[begin + y] = vec[y];
413         }
414         return 0;
415 }
416 /*------------------------NUMERIC PROTOCOLS----------------------
417   ------------------------obj + obj------------------------------
418   addition*/
419 static PyObject *Vector_add(PyObject * v1, PyObject * v2)
420 {
421         int i;
422         float vec[4];
423
424         VectorObject *vec1 = NULL, *vec2 = NULL;
425         
426         if VectorObject_Check(v1)
427                 vec1= (VectorObject *)v1;
428         
429         if VectorObject_Check(v2)
430                 vec2= (VectorObject *)v2;
431         
432         /* make sure v1 is always the vector */
433         if (vec1 && vec2 ) {
434                 /*VECTOR + VECTOR*/
435                 if(vec1->size != vec2->size)
436                         return EXPP_ReturnPyObjError(PyExc_AttributeError,
437                         "Vector addition: vectors must have the same dimensions for this operation\n");
438                 
439                 for(i = 0; i < vec1->size; i++) {
440                         vec[i] = vec1->vec[i] + vec2->vec[i];
441                 }
442                 return newVectorObject(vec, vec1->size, Py_NEW);
443         }
444         
445         if(PointObject_Check(v2)){  /*VECTOR + POINT*/
446                 /*Point translation*/
447                 PointObject *pt = (PointObject*)v2;
448                 
449                 if(pt->size == vec1->size){
450                         for(i = 0; i < vec1->size; i++){
451                                 vec[i] = vec1->vec[i] + pt->coord[i];
452                         }
453                 }else{
454                         return EXPP_ReturnPyObjError(PyExc_AttributeError,
455                                 "Vector addition: arguments are the wrong size....\n");
456                 }
457                 return newPointObject(vec, vec1->size, Py_NEW);
458         }
459         
460         return EXPP_ReturnPyObjError(PyExc_AttributeError,
461                 "Vector addition: arguments not valid for this operation....\n");
462 }
463
464 /*  ------------------------obj += obj------------------------------
465   addition in place */
466 static PyObject *Vector_iadd(PyObject * v1, PyObject * v2)
467 {
468         int i;
469
470         VectorObject *vec1 = NULL, *vec2 = NULL;
471         
472         if VectorObject_Check(v1)
473                 vec1= (VectorObject *)v1;
474         
475         if VectorObject_Check(v2)
476                 vec2= (VectorObject *)v2;
477         
478         /* make sure v1 is always the vector */
479         if (vec1 && vec2 ) {
480                 /*VECTOR + VECTOR*/
481                 if(vec1->size != vec2->size)
482                         return EXPP_ReturnPyObjError(PyExc_AttributeError,
483                         "Vector addition: vectors must have the same dimensions for this operation\n");
484                 
485                 for(i = 0; i < vec1->size; i++) {
486                         vec1->vec[i] += vec2->vec[i];
487                 }
488                 Py_INCREF( v1 );
489                 return v1;
490         }
491         
492         if(PointObject_Check(v2)){  /*VECTOR + POINT*/
493                 /*Point translation*/
494                 PointObject *pt = (PointObject*)v2;
495                 
496                 if(pt->size == vec1->size){
497                         for(i = 0; i < vec1->size; i++){
498                                 vec1->vec[i] += pt->coord[i];
499                         }
500                 }else{
501                         return EXPP_ReturnPyObjError(PyExc_AttributeError,
502                                 "Vector addition: arguments are the wrong size....\n");
503                 }
504                 Py_INCREF( v1 );
505                 return v1;
506         }
507         
508         return EXPP_ReturnPyObjError(PyExc_AttributeError,
509                 "Vector addition: arguments not valid for this operation....\n");
510 }
511
512 /*------------------------obj - obj------------------------------
513   subtraction*/
514 static PyObject *Vector_sub(PyObject * v1, PyObject * v2)
515 {
516         int i;
517         float vec[4];
518         VectorObject *vec1 = NULL, *vec2 = NULL;
519
520         if (!VectorObject_Check(v1) || !VectorObject_Check(v2))
521                 return EXPP_ReturnPyObjError(PyExc_AttributeError,
522                         "Vector subtraction: arguments not valid for this operation....\n");
523         
524         vec1 = (VectorObject*)v1;
525         vec2 = (VectorObject*)v2;
526         
527         if(vec1->size != vec2->size)
528                 return EXPP_ReturnPyObjError(PyExc_AttributeError,
529                 "Vector subtraction: vectors must have the same dimensions for this operation\n");
530         
531         for(i = 0; i < vec1->size; i++) {
532                 vec[i] = vec1->vec[i] - vec2->vec[i];
533         }
534
535         return newVectorObject(vec, vec1->size, Py_NEW);
536 }
537
538 /*------------------------obj -= obj------------------------------
539   subtraction*/
540 static PyObject *Vector_isub(PyObject * v1, PyObject * v2)
541 {
542         int i, size;
543         VectorObject *vec1 = NULL, *vec2 = NULL;
544
545         if (!VectorObject_Check(v1) || !VectorObject_Check(v2))
546                 return EXPP_ReturnPyObjError(PyExc_AttributeError,
547                         "Vector subtraction: arguments not valid for this operation....\n");
548         
549         vec1 = (VectorObject*)v1;
550         vec2 = (VectorObject*)v2;
551         
552         if(vec1->size != vec2->size)
553                 return EXPP_ReturnPyObjError(PyExc_AttributeError,
554                 "Vector subtraction: vectors must have the same dimensions for this operation\n");
555
556         size = vec1->size;
557         for(i = 0; i < vec1->size; i++) {
558                 vec1->vec[i] = vec1->vec[i] -   vec2->vec[i];
559         }
560
561         Py_INCREF( v1 );
562         return v1;
563 }
564
565 /*------------------------obj * obj------------------------------
566   mulplication*/
567 static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
568 {
569         VectorObject *vec1 = NULL, *vec2 = NULL;
570         
571         if VectorObject_Check(v1)
572                 vec1= (VectorObject *)v1;
573         
574         if VectorObject_Check(v2)
575                 vec2= (VectorObject *)v2;
576         
577         /* make sure v1 is always the vector */
578         if (vec1 && vec2 ) {
579                 int i;
580                 double dot = 0.0f;
581                 
582                 if(vec1->size != vec2->size)
583                 return EXPP_ReturnPyObjError(PyExc_AttributeError,
584                         "Vector multiplication: vectors must have the same dimensions for this operation\n");
585                 
586                 /*dot product*/
587                 for(i = 0; i < vec1->size; i++) {
588                         dot += vec1->vec[i] * vec2->vec[i];
589                 }
590                 return PyFloat_FromDouble(dot);
591         }
592         
593         /*swap so vec1 is always the vector */
594         if (vec2) {
595                 vec1= vec2;
596                 v2= v1;
597         }
598         
599         if (PyNumber_Check(v2)) {
600                 /* VEC * NUM */
601                 int i;
602                 float vec[4];
603                 float scalar = (float)PyFloat_AsDouble( v2 );
604                 
605                 for(i = 0; i < vec1->size; i++) {
606                         vec[i] = vec1->vec[i] * scalar;
607                 }
608                 return newVectorObject(vec, vec1->size, Py_NEW);
609                 
610         } else if (MatrixObject_Check(v2)) {
611                 /* VEC * MATRIX */
612                 if (v1==v2) /* mat*vec, we have swapped the order */
613                         return column_vector_multiplication((MatrixObject*)v2, vec1);
614                 else /* vec*mat */
615                         return row_vector_multiplication(vec1, (MatrixObject*)v2);
616         } else if (QuaternionObject_Check(v2)) {
617                 QuaternionObject *quat = (QuaternionObject*)v2;
618                 if(vec1->size != 3)
619                         return EXPP_ReturnPyObjError(PyExc_TypeError, 
620                                 "Vector multiplication: only 3D vector rotations (with quats) currently supported\n");
621                 
622                 return quat_rotation((PyObject*)vec1, (PyObject*)quat);
623         }
624         
625         return EXPP_ReturnPyObjError(PyExc_TypeError,
626                 "Vector multiplication: arguments not acceptable for this operation\n");
627 }
628
629 /*------------------------obj *= obj------------------------------
630   in place mulplication */
631 static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
632 {
633         VectorObject *vec = (VectorObject *)v1;
634         int i;
635         
636         /* only support vec*=float and vec*=mat
637            vec*=vec result is a float so that wont work */
638         if (PyNumber_Check(v2)) {
639                 /* VEC * NUM */
640                 float scalar = (float)PyFloat_AsDouble( v2 );
641                 
642                 for(i = 0; i < vec->size; i++) {
643                         vec->vec[i] *=  scalar;
644                 }
645                 
646                 Py_INCREF( v1 );
647                 return v1;
648                 
649         } else if (MatrixObject_Check(v2)) {
650                 float vecCopy[4];
651                 int x,y, size = vec->size;
652                 MatrixObject *mat= (MatrixObject*)v2;
653                 
654                 if(mat->colSize != size){
655                         if(mat->rowSize == 4 && vec->size != 3){
656                                 return EXPP_ReturnPyObjError(PyExc_AttributeError, 
657                                         "vector * matrix: matrix column size and the vector size must be the same");
658                         } else {
659                                 vecCopy[3] = 1.0f;
660                         }
661                 }
662                 
663                 for(i = 0; i < size; i++){
664                         vecCopy[i] = vec->vec[i];
665                 }
666                 
667                 size = MIN2(size, mat->colSize);
668                 
669                 /*muliplication*/
670                 for(x = 0, i = 0; x < size; x++, i++) {
671                         double dot = 0.0f;
672                         for(y = 0; y < mat->rowSize; y++) {
673                                 dot += mat->matrix[y][x] * vecCopy[y];
674                         }
675                         vec->vec[i] = (float)dot;
676                 }
677                 Py_INCREF( v1 );
678                 return v1;
679         }
680         return EXPP_ReturnPyObjError(PyExc_TypeError,
681                 "Vector multiplication: arguments not acceptable for this operation\n");
682 }
683
684 /*------------------------obj / obj------------------------------
685   divide*/
686 static PyObject *Vector_div(PyObject * v1, PyObject * v2)
687 {
688         int i, size;
689         float vec[4], scalar;
690         VectorObject *vec1 = NULL;
691         
692         if(!VectorObject_Check(v1)) /* not a vector */
693                 return EXPP_ReturnPyObjError(PyExc_TypeError, 
694                         "Vector division: Vector must be divided by a float\n");
695         
696         vec1 = (VectorObject*)v1; /* vector */
697         
698         if(!PyNumber_Check(v2)) /* parsed item not a number */
699                 return EXPP_ReturnPyObjError(PyExc_TypeError, 
700                         "Vector division: Vector must be divided by a float\n");
701
702         scalar = (float)PyFloat_AsDouble(v2);
703         
704         if(scalar==0.0) /* not a vector */
705                 return EXPP_ReturnPyObjError(PyExc_ZeroDivisionError, 
706                         "Vector division: divide by zero error.\n");
707         
708         size = vec1->size;
709         for(i = 0; i < size; i++) {
710                 vec[i] = vec1->vec[i] / scalar;
711         }
712         return newVectorObject(vec, size, Py_NEW);
713 }
714
715 /*------------------------obj / obj------------------------------
716   divide*/
717 static PyObject *Vector_idiv(PyObject * v1, PyObject * v2)
718 {
719         int i, size;
720         float scalar;
721         VectorObject *vec1 = NULL;
722         
723         /*if(!VectorObject_Check(v1))
724                 return EXPP_ReturnIntError(PyExc_TypeError, 
725                         "Vector division: Vector must be divided by a float\n");*/
726         
727         vec1 = (VectorObject*)v1; /* vector */
728         
729         if(!PyNumber_Check(v2)) /* parsed item not a number */
730                 return EXPP_ReturnPyObjError(PyExc_TypeError, 
731                         "Vector division: Vector must be divided by a float\n");
732
733         scalar = (float)PyFloat_AsDouble(v2);
734         
735         if(scalar==0.0) /* not a vector */
736                 return EXPP_ReturnPyObjError(PyExc_ZeroDivisionError, 
737                         "Vector division: divide by zero error.\n");
738         
739         size = vec1->size;
740         for(i = 0; i < size; i++) {
741                 vec1->vec[i] /= scalar;
742         }
743         Py_INCREF( v1 );
744         return v1;
745 }
746
747 /*-------------------------- -obj -------------------------------
748   returns the negative of this object*/
749 static PyObject *Vector_neg(VectorObject *self)
750 {
751         int i;
752         float vec[4];
753         for(i = 0; i < self->size; i++){
754                 vec[i] = -self->vec[i];
755         }
756
757         return newVectorObject(vec, self->size, Py_NEW);
758 }
759 /*------------------------coerce(obj, obj)-----------------------
760   coercion of unknown types to type VectorObject for numeric protocols
761   Coercion() is called whenever a math operation has 2 operands that
762  it doesn't understand how to evaluate. 2+Matrix for example. We want to 
763  evaluate some of these operations like: (vector * 2), however, for math
764  to proceed, the unknown operand must be cast to a type that python math will
765  understand. (e.g. in the case above case, 2 must be cast to a vector and 
766  then call vector.multiply(vector, scalar_cast_as_vector)*/
767
768
769 static int Vector_coerce(PyObject ** v1, PyObject ** v2)
770 {
771         /* Just incref, each functon must raise errors for bad types */
772         Py_INCREF (*v1);
773         Py_INCREF (*v2);
774         return 0;
775 }
776
777
778 /*------------------------tp_doc*/
779 static char VectorObject_doc[] = "This is a wrapper for vector objects.";
780 /*------------------------vec_magnitude_nosqrt (internal) - for comparing only */
781 static double vec_magnitude_nosqrt(float *data, int size)
782 {
783         double dot = 0.0f;
784         int i;
785
786         for(i=0; i<size; i++){
787                 dot += data[i];
788         }
789         /*return (double)sqrt(dot);*/
790         /* warning, line above removed because we are not using the length,
791            rather the comparing the sizes and for this we do not need the sqrt
792            for the actual length, the dot must be sqrt'd */
793         return (double)dot;
794 }
795
796
797 /*------------------------tp_richcmpr
798   returns -1 execption, 0 false, 1 true */
799 PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
800 {
801         VectorObject *vecA = NULL, *vecB = NULL;
802         int result = 0;
803         float epsilon = .000001f;
804         double lenA,lenB;
805
806         if (!VectorObject_Check(objectA) || !VectorObject_Check(objectB)){
807                 if (comparison_type == Py_NE){
808                         return EXPP_incr_ret(Py_True); 
809                 }else{
810                         return EXPP_incr_ret(Py_False);
811                 }
812         }
813         vecA = (VectorObject*)objectA;
814         vecB = (VectorObject*)objectB;
815
816         if (vecA->size != vecB->size){
817                 if (comparison_type == Py_NE){
818                         return EXPP_incr_ret(Py_True); 
819                 }else{
820                         return EXPP_incr_ret(Py_False);
821                 }
822         }
823
824         switch (comparison_type){
825                 case Py_LT:
826                         lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
827                         lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
828                         if( lenA < lenB ){
829                                 result = 1;
830                         }
831                         break;
832                 case Py_LE:
833                         lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
834                         lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
835                         if( lenA < lenB ){
836                                 result = 1;
837                         }else{
838                                 result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
839                         }
840                         break;
841                 case Py_EQ:
842                         result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
843                         break;
844                 case Py_NE:
845                         result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
846                         if (result == 0){
847                                 result = 1;
848                         }else{
849                                 result = 0;
850                         }
851                         break;
852                 case Py_GT:
853                         lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
854                         lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
855                         if( lenA > lenB ){
856                                 result = 1;
857                         }
858                         break;
859                 case Py_GE:
860                         lenA = vec_magnitude_nosqrt(vecA->vec, vecA->size);
861                         lenB = vec_magnitude_nosqrt(vecB->vec, vecB->size);
862                         if( lenA > lenB ){
863                                 result = 1;
864                         }else{
865                                 result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
866                         }
867                         break;
868                 default:
869                         printf("The result of the comparison could not be evaluated");
870                         break;
871         }
872         if (result == 1){
873                 return EXPP_incr_ret(Py_True);
874         }else{
875                 return EXPP_incr_ret(Py_False);
876         }
877 }
878 /*-----------------PROTCOL DECLARATIONS--------------------------*/
879 static PySequenceMethods Vector_SeqMethods = {
880         (inquiry) Vector_len,                                           /* sq_length */
881         (binaryfunc) 0,                                                         /* sq_concat */
882         (intargfunc) 0,                                                         /* sq_repeat */
883         (intargfunc) Vector_item,                                       /* sq_item */
884         (intintargfunc) Vector_slice,                           /* sq_slice */
885         (intobjargproc) Vector_ass_item,                        /* sq_ass_item */
886         (intintobjargproc) Vector_ass_slice,            /* sq_ass_slice */
887 };
888
889
890 /* For numbers without flag bit Py_TPFLAGS_CHECKTYPES set, all
891    arguments are guaranteed to be of the object's type (modulo
892    coercion hacks -- i.e. if the type's coercion function
893    returns other types, then these are allowed as well).  Numbers that
894    have the Py_TPFLAGS_CHECKTYPES flag bit set should check *both*
895    arguments for proper type and implement the necessary conversions
896    in the slot functions themselves. */
897  
898 static PyNumberMethods Vector_NumMethods = {
899         (binaryfunc) Vector_add,                                        /* __add__ */
900         (binaryfunc) Vector_sub,                                        /* __sub__ */
901         (binaryfunc) Vector_mul,                                        /* __mul__ */
902         (binaryfunc) Vector_div,                                        /* __div__ */
903         (binaryfunc) NULL,                                                      /* __mod__ */
904         (binaryfunc) NULL,                                                      /* __divmod__ */
905         (ternaryfunc) NULL,                                                     /* __pow__ */
906         (unaryfunc) Vector_neg,                                         /* __neg__ */
907         (unaryfunc) NULL,                                                       /* __pos__ */
908         (unaryfunc) NULL,                                                       /* __abs__ */
909         (inquiry) NULL,                                                         /* __nonzero__ */
910         (unaryfunc) NULL,                                                       /* __invert__ */
911         (binaryfunc) NULL,                                                      /* __lshift__ */
912         (binaryfunc) NULL,                                                      /* __rshift__ */
913         (binaryfunc) NULL,                                                      /* __and__ */
914         (binaryfunc) NULL,                                                      /* __xor__ */
915         (binaryfunc) NULL,                                                      /* __or__ */
916         (coercion)  Vector_coerce,                                      /* __coerce__ */
917         (unaryfunc) NULL,                                                       /* __int__ */
918         (unaryfunc) NULL,                                                       /* __long__ */
919         (unaryfunc) NULL,                                                       /* __float__ */
920         (unaryfunc) NULL,                                                       /* __oct__ */
921         (unaryfunc) NULL,                                                       /* __hex__ */
922         
923         /* Added in release 2.0 */
924         (binaryfunc) Vector_iadd,                                       /*__iadd__*/
925         (binaryfunc) Vector_isub,                                       /*__isub__*/
926         (binaryfunc) Vector_imul,                                       /*__imul__*/
927         (binaryfunc) Vector_idiv,                                       /*__idiv__*/
928         (binaryfunc) NULL,                                                      /*__imod__*/
929         (ternaryfunc) NULL,                                                     /*__ipow__*/
930         (binaryfunc) NULL,                                                      /*__ilshift__*/
931         (binaryfunc) NULL,                                                      /*__irshift__*/
932         (binaryfunc) NULL,                                                      /*__iand__*/
933         (binaryfunc) NULL,                                                      /*__ixor__*/
934         (binaryfunc) NULL,                                                      /*__ior__*/
935  
936         /* Added in release 2.2 */
937         /* The following require the Py_TPFLAGS_HAVE_CLASS flag */
938         (binaryfunc) NULL,                                                      /*__floordiv__  __rfloordiv__*/
939         (binaryfunc) NULL,                                                      /*__truediv__ __rfloordiv__*/
940         (binaryfunc) NULL,                                                      /*__ifloordiv__*/
941         (binaryfunc) NULL,                                                      /*__itruediv__*/
942 };
943 /*------------------PY_OBECT DEFINITION--------------------------*/
944
945 /*
946  * vector axis, vector.x/y/z/w
947  */
948         
949 static PyObject *Vector_getAxis( VectorObject * self, void *type )
950 {
951         switch( (long)type ) {
952     case 'X':   /* these are backwards, but that how it works */
953                 return PyFloat_FromDouble(self->vec[0]);
954     case 'Y':
955                 return PyFloat_FromDouble(self->vec[1]);
956     case 'Z':   /* these are backwards, but that how it works */
957                 if(self->size < 3)
958                         return EXPP_ReturnPyObjError(PyExc_AttributeError,
959                                 "vector.z: error, cannot get this axis for a 2D vector\n");
960                 else
961                         return PyFloat_FromDouble(self->vec[2]);
962     case 'W':
963                 if(self->size < 4)
964                         return EXPP_ReturnPyObjError(PyExc_AttributeError,
965                                 "vector.w: error, cannot get this axis for a 3D vector\n");
966         
967                 return PyFloat_FromDouble(self->vec[3]);
968         default:
969                 {
970                         char errstr[1024];
971                         sprintf( errstr, "undefined type '%d' in Vector_getAxis",
972                                         (int)((long)type & 0xff));
973                         return EXPP_ReturnPyObjError( PyExc_RuntimeError, errstr );
974                 }
975         }
976 }
977
978 static int Vector_setAxis( VectorObject * self, PyObject * value, void * type )
979 {
980         float param;
981         
982         if (!PyNumber_Check(value))
983                 return EXPP_ReturnIntError( PyExc_TypeError,
984                         "expected a number for the vector axis" );
985         
986         param= (float)PyFloat_AsDouble( value );
987         
988         switch( (long)type ) {
989     case 'X':   /* these are backwards, but that how it works */
990                 self->vec[0]= param;
991                 break;
992     case 'Y':
993                 self->vec[1]= param;
994                 break;
995     case 'Z':   /* these are backwards, but that how it works */
996                 if(self->size < 3)
997                         return EXPP_ReturnIntError(PyExc_AttributeError,
998                                 "vector.z: error, cannot get this axis for a 2D vector\n");
999                 self->vec[2]= param;
1000                 break;
1001     case 'W':
1002                 if(self->size < 4)
1003                         return EXPP_ReturnIntError(PyExc_AttributeError,
1004                                 "vector.w: error, cannot get this axis for a 3D vector\n");
1005         
1006                 self->vec[3]= param;
1007                 break;
1008         default:
1009                 {
1010                         char errstr[1024];
1011                         sprintf( errstr, "undefined type '%d' in Vector_setAxis",
1012                                         (int)((long)type & 0xff));
1013                         return EXPP_ReturnIntError( PyExc_RuntimeError, errstr );
1014                 }
1015         }
1016
1017         return 0;
1018 }
1019
1020 /* vector.length */
1021 static PyObject *Vector_getLength( VectorObject * self, void *type )
1022 {
1023         double dot = 0.0f;
1024         int i;
1025         
1026         for(i = 0; i < self->size; i++){
1027                 dot += (self->vec[i] * self->vec[i]);
1028         }
1029         return PyFloat_FromDouble(sqrt(dot));
1030 }
1031
1032 static int Vector_setLength( VectorObject * self, PyObject * value )
1033 {
1034         double dot = 0.0f, param;
1035         int i;
1036         
1037         if (!PyNumber_Check(value))
1038                 return EXPP_ReturnIntError( PyExc_TypeError,
1039                         "expected a number for the vector axis" );
1040         
1041         param= PyFloat_AsDouble( value );
1042         
1043         if (param < 0)
1044                 return EXPP_ReturnIntError( PyExc_TypeError,
1045                         "cannot set a vectors length to a negative value" );
1046         
1047         if (param==0) {
1048                 for(i = 0; i < self->size; i++){
1049                         self->vec[i]= 0;
1050                 }
1051                 return 0;
1052         }
1053         
1054         for(i = 0; i < self->size; i++){
1055                 dot += (self->vec[i] * self->vec[i]);
1056         }
1057
1058         if (!dot) /* cant sqrt zero */
1059                 return 0;
1060         
1061         dot = sqrt(dot);
1062         
1063         if (dot==param)
1064                 return 0;
1065         
1066         dot= dot/param;
1067         
1068         for(i = 0; i < self->size; i++){
1069                 self->vec[i]= self->vec[i] / (float)dot;
1070         }
1071         
1072         return 0;
1073 }
1074
1075 static PyObject *Vector_getWrapped( VectorObject * self, void *type )
1076 {
1077         if (self->wrapped == Py_WRAP)
1078                 Py_RETURN_TRUE;
1079         else
1080                 Py_RETURN_FALSE;
1081 }
1082
1083
1084 /*****************************************************************************/
1085 /* Python attributes get/set structure:                                      */
1086 /*****************************************************************************/
1087 static PyGetSetDef Vector_getseters[] = {
1088         {"x",
1089          (getter)Vector_getAxis, (setter)Vector_setAxis,
1090          "Vector X axis",
1091          (void *)'X'},
1092         {"y",
1093          (getter)Vector_getAxis, (setter)Vector_setAxis,
1094          "Vector Y axis",
1095          (void *)'Y'},
1096         {"z",
1097          (getter)Vector_getAxis, (setter)Vector_setAxis,
1098          "Vector Z axis",
1099          (void *)'Z'},
1100         {"w",
1101          (getter)Vector_getAxis, (setter)Vector_setAxis,
1102          "Vector Z axis",
1103          (void *)'W'},
1104         {"length",
1105          (getter)Vector_getLength, (setter)Vector_setLength,
1106          "Vector Length",
1107          NULL},
1108         {"magnitude",
1109          (getter)Vector_getLength, (setter)Vector_setLength,
1110          "Vector Length",
1111          NULL},
1112         {"wrapped",
1113          (getter)Vector_getWrapped, (setter)NULL,
1114          "Vector Length",
1115          NULL},
1116         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
1117 };
1118
1119
1120
1121 /* Note
1122  Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing
1123  but this means for eg that 
1124  vec*mat and mat*vec both get sent to Vector_mul and it neesd to sort out the order
1125 */
1126
1127 PyTypeObject vector_Type = {
1128         PyObject_HEAD_INIT( NULL )  /* required py macro */
1129         0,                          /* ob_size */
1130         /*  For printing, in format "<module>.<name>" */
1131         "Blender Vector",             /* char *tp_name; */
1132         sizeof( VectorObject ),         /* int tp_basicsize; */
1133         0,                          /* tp_itemsize;  For allocation */
1134
1135         /* Methods to implement standard operations */
1136
1137         ( destructor ) Vector_dealloc,/* destructor tp_dealloc; */
1138         NULL,                       /* printfunc tp_print; */
1139         NULL,                       /* getattrfunc tp_getattr; */
1140         NULL,                       /* setattrfunc tp_setattr; */
1141         NULL,   /* cmpfunc tp_compare; */
1142         ( reprfunc ) Vector_repr,     /* reprfunc tp_repr; */
1143
1144         /* Method suites for standard classes */
1145
1146         &Vector_NumMethods,                       /* PyNumberMethods *tp_as_number; */
1147         &Vector_SeqMethods,                       /* PySequenceMethods *tp_as_sequence; */
1148         NULL,                       /* PyMappingMethods *tp_as_mapping; */
1149
1150         /* More standard operations (here for binary compatibility) */
1151
1152         NULL,                       /* hashfunc tp_hash; */
1153         NULL,                       /* ternaryfunc tp_call; */
1154         NULL,                       /* reprfunc tp_str; */
1155         NULL,                       /* getattrofunc tp_getattro; */
1156         NULL,                       /* setattrofunc tp_setattro; */
1157
1158         /* Functions to access object as input/output buffer */
1159         NULL,                       /* PyBufferProcs *tp_as_buffer; */
1160
1161   /*** Flags to define presence of optional/expanded features ***/
1162         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES,         /* long tp_flags; */
1163
1164         VectorObject_doc,                       /*  char *tp_doc;  Documentation string */
1165   /*** Assigned meaning in release 2.0 ***/
1166         /* call function for all accessible objects */
1167         NULL,                       /* traverseproc tp_traverse; */
1168
1169         /* delete references to contained objects */
1170         NULL,                       /* inquiry tp_clear; */
1171
1172   /***  Assigned meaning in release 2.1 ***/
1173   /*** rich comparisons ***/
1174         (richcmpfunc)Vector_richcmpr,                       /* richcmpfunc tp_richcompare; */
1175
1176   /***  weak reference enabler ***/
1177         0,                          /* long tp_weaklistoffset; */
1178
1179   /*** Added in release 2.2 ***/
1180         /*   Iterators */
1181         NULL,                       /* getiterfunc tp_iter; */
1182         NULL,                       /* iternextfunc tp_iternext; */
1183
1184   /*** Attribute descriptor and subclassing stuff ***/
1185         Vector_methods,           /* struct PyMethodDef *tp_methods; */
1186         NULL,                       /* struct PyMemberDef *tp_members; */
1187         Vector_getseters,         /* struct PyGetSetDef *tp_getset; */
1188         NULL,                       /* struct _typeobject *tp_base; */
1189         NULL,                       /* PyObject *tp_dict; */
1190         NULL,                       /* descrgetfunc tp_descr_get; */
1191         NULL,                       /* descrsetfunc tp_descr_set; */
1192         0,                          /* long tp_dictoffset; */
1193         NULL,                       /* initproc tp_init; */
1194         NULL,                       /* allocfunc tp_alloc; */
1195         NULL,                       /* newfunc tp_new; */
1196         /*  Low-level free-memory routine */
1197         NULL,                       /* freefunc tp_free;  */
1198         /* For PyObject_IS_GC */
1199         NULL,                       /* inquiry tp_is_gc;  */
1200         NULL,                       /* PyObject *tp_bases; */
1201         /* method resolution order */
1202         NULL,                       /* PyObject *tp_mro;  */
1203         NULL,                       /* PyObject *tp_cache; */
1204         NULL,                       /* PyObject *tp_subclasses; */
1205         NULL,                       /* PyObject *tp_weaklist; */
1206         NULL
1207 };
1208
1209
1210 /*------------------------newVectorObject (internal)-------------
1211   creates a new vector object
1212   pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
1213  (i.e. it was allocated elsewhere by MEM_mallocN())
1214   pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
1215  (i.e. it must be created here with PyMEM_malloc())*/
1216 PyObject *newVectorObject(float *vec, int size, int type)
1217 {
1218         int i;
1219         VectorObject *self = PyObject_NEW(VectorObject, &vector_Type);
1220         
1221         if(size > 4 || size < 2)
1222                 return NULL;
1223         self->size = size;
1224
1225         if(type == Py_WRAP) {
1226                 self->vec = vec;
1227                 self->wrapped = Py_WRAP;
1228         } else if (type == Py_NEW) {
1229                 self->vec = PyMem_Malloc(size * sizeof(float));
1230                 if(!vec) { /*new empty*/
1231                         for(i = 0; i < size; i++){
1232                                 self->vec[i] = 0.0f;
1233                         }
1234                         if(size == 4)  /* do the homogenous thing */
1235                                 self->vec[3] = 1.0f;
1236                 }else{
1237                         for(i = 0; i < size; i++){
1238                                 self->vec[i] = vec[i];
1239                         }
1240                 }
1241                 self->wrapped = Py_NEW;
1242         }else{ /*bad type*/
1243                 return NULL;
1244         }
1245         return (PyObject *) self;
1246 }
1247
1248 /*
1249   #############################DEPRECATED################################
1250   #######################################################################
1251   ----------------------------Vector.negate() --------------------
1252   set the vector to it's negative -x, -y, -z */
1253 PyObject *Vector_Negate(VectorObject * self)
1254 {
1255         int i;
1256         for(i = 0; i < self->size; i++) {
1257                 self->vec[i] = -(self->vec[i]);
1258         }
1259         /*printf("Vector.negate(): Deprecated: use -vector instead\n");*/
1260         return EXPP_incr_ret((PyObject*)self);
1261 }
1262 /*###################################################################
1263   ###########################DEPRECATED##############################*/
1264