Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2009-06-22 08:26:48 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-06-22 08:26:48 +0400
commitbce3f7e019c174947a0f98063f39533eb59ab03e (patch)
treebb66802258a156dec4a39f20c900a750fd7b6b55 /source/blender/python/generic/vector.c
parent1efffc1f564af0597512699890d7be9f41a6aee2 (diff)
PyAPI Mathutils Vector callbacks, referencing other PyObjects rather then thin wrapping vectors which is crash prone.
in short, vectors can work as if they are thin wrapped but not crash blender if the original data is removed. * RNA vector's return Mathutils vector types. * BGE vectors for GameObject's localPosition, worldPosition, localPosition, localScale, worldScale, localInertia. * Comment USE_MATHUTILS define to disable returning vectors. Example... * 2.49... * loc = gameOb.worldPosition loc[1] = 0 gameOb.worldPosition = loc * With vectors... * gameOb.worldPosition[1] = 0 * But this wont crash... * loc = gameOb.worldPosition gameOb.endObject() loc[1] = 0 # will raise an error that the objects removed. This breaks games which assume return values are lists. Will add this to eulers, matrix and quaternion types later.
Diffstat (limited to 'source/blender/python/generic/vector.c')
-rw-r--r--source/blender/python/generic/vector.c321
1 files changed, 220 insertions, 101 deletions
diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c
index 562413c6967..ce11149e311 100644
--- a/source/blender/python/generic/vector.c
+++ b/source/blender/python/generic/vector.c
@@ -39,6 +39,8 @@
#define SWIZZLE_VALID_AXIS 0x4
#define SWIZZLE_AXIS 0x3
+static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); /* utility func */
+
/*-------------------------DOC STRINGS ---------------------------*/
static char Vector_Zero_doc[] = "() - set all values in the vector to 0";
static char Vector_Normalize_doc[] = "() - normalize the vector";
@@ -60,7 +62,7 @@ static PyObject *Vector_Resize2D( VectorObject * self );
static PyObject *Vector_Resize3D( VectorObject * self );
static PyObject *Vector_Resize4D( VectorObject * self );
static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args );
-static PyObject *Vector_Reflect( VectorObject * self, PyObject * value );
+static PyObject *Vector_Reflect( VectorObject *self, VectorObject *value );
static PyObject *Vector_Cross( VectorObject * self, VectorObject * value );
static PyObject *Vector_Dot( VectorObject * self, VectorObject * value );
static PyObject *Vector_copy( VectorObject * self );
@@ -141,6 +143,8 @@ static PyObject *Vector_Zero(VectorObject * self)
for(i = 0; i < self->size; i++) {
self->vec[i] = 0.0f;
}
+
+ Vector_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
@@ -151,6 +155,9 @@ static PyObject *Vector_Normalize(VectorObject * self)
int i;
float norm = 0.0f;
+ if(!Vector_ReadCallback(self))
+ return NULL;
+
for(i = 0; i < self->size; i++) {
norm += self->vec[i] * self->vec[i];
}
@@ -158,6 +165,8 @@ static PyObject *Vector_Normalize(VectorObject * self)
for(i = 0; i < self->size; i++) {
self->vec[i] /= norm;
}
+
+ Vector_WriteCallback(self);
Py_INCREF(self);
return (PyObject*)self;
}
@@ -171,6 +180,11 @@ static PyObject *Vector_Resize2D(VectorObject * self)
PyErr_SetString(PyExc_TypeError, "vector.resize2d(): cannot resize wrapped data - only python vectors\n");
return NULL;
}
+ if(self->user) {
+ PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner");
+ return NULL;
+ }
+
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2));
if(self->vec == NULL) {
PyErr_SetString(PyExc_MemoryError, "vector.resize2d(): problem allocating pointer space\n\n");
@@ -189,6 +203,11 @@ static PyObject *Vector_Resize3D(VectorObject * self)
PyErr_SetString(PyExc_TypeError, "vector.resize3d(): cannot resize wrapped data - only python vectors\n");
return NULL;
}
+ if(self->user) {
+ PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner");
+ return NULL;
+ }
+
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3));
if(self->vec == NULL) {
PyErr_SetString(PyExc_MemoryError, "vector.resize3d(): problem allocating pointer space\n\n");
@@ -210,6 +229,11 @@ static PyObject *Vector_Resize4D(VectorObject * self)
PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize wrapped data - only python vectors");
return NULL;
}
+ if(self->user) {
+ PyErr_SetString(PyExc_TypeError, "vector.resize4d(): cannot resize a vector that has an owner");
+ return NULL;
+ }
+
self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4));
if(self->vec == NULL) {
PyErr_SetString(PyExc_MemoryError, "vector.resize4d(): problem allocating pointer space\n\n");
@@ -241,6 +265,9 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
PyErr_SetString( PyExc_TypeError, "only for 3D vectors\n" );
return NULL;
}
+
+ if(!Vector_ReadCallback(self))
+ return NULL;
if (strack) {
if (strlen(strack) == 2) {
@@ -342,9 +369,8 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
return a reflected vector on the mirror normal
((2 * DotVecs(vec, mirror)) * mirror) - vec
using arithb.c would be nice here */
-static PyObject *Vector_Reflect( VectorObject * self, PyObject * value )
+static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value )
{
- VectorObject *mirrvec;
float mirror[3];
float vec[3];
float reflect[4] = {0.0f, 0.0f, 0.0f, 0.0f};
@@ -358,11 +384,13 @@ static PyObject *Vector_Reflect( VectorObject * self, PyObject * value )
PyErr_SetString( PyExc_TypeError, "vec.reflect(value): expected a vector argument" );
return NULL;
}
- mirrvec = (VectorObject *)value;
- mirror[0] = mirrvec->vec[0];
- mirror[1] = mirrvec->vec[1];
- if (mirrvec->size > 2) mirror[2] = mirrvec->vec[2];
+ if(!Vector_ReadCallback(self) || !Vector_ReadCallback(value))
+ return NULL;
+
+ mirror[0] = value->vec[0];
+ mirror[1] = value->vec[1];
+ if (value->size > 2) mirror[2] = value->vec[2];
else mirror[2] = 0.0;
/* normalize, whos idea was it not to use arithb.c? :-/ */
@@ -403,6 +431,9 @@ static PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
return NULL;
}
+ if(!Vector_ReadCallback(self) || !Vector_ReadCallback(value))
+ return NULL;
+
vecCross = (VectorObject *)newVectorObject(NULL, 3, Py_NEW);
Crossf(vecCross->vec, self->vec, value->vec);
return (PyObject *)vecCross;
@@ -423,6 +454,9 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
return NULL;
}
+ if(!Vector_ReadCallback(self) || !Vector_ReadCallback(value))
+ return NULL;
+
for(x = 0; x < self->size; x++) {
dot += self->vec[x] * value->vec[x];
}
@@ -433,6 +467,9 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
return a copy of the vector */
static PyObject *Vector_copy(VectorObject * self)
{
+ if(!Vector_ReadCallback(self))
+ return NULL;
+
return newVectorObject(self->vec, self->size, Py_NEW);
}
@@ -444,6 +481,7 @@ static void Vector_dealloc(VectorObject * self)
if(self->wrapped != Py_WRAP){
PyMem_Free(self->vec);
}
+ Py_XDECREF(self->user);
PyObject_DEL(self);
}
@@ -454,6 +492,9 @@ static PyObject *Vector_repr(VectorObject * self)
int i;
char buffer[48], str[1024];
+ if(!Vector_ReadCallback(self))
+ return NULL;
+
BLI_strncpy(str,"[",1024);
for(i = 0; i < self->size; i++){
if(i < (self->size - 1)){
@@ -484,6 +525,9 @@ static PyObject *Vector_item(VectorObject * self, int i)
return NULL;
}
+ if(!Vector_ReadIndexCallback(self, i))
+ return NULL;
+
return PyFloat_FromDouble(self->vec[i]);
}
@@ -502,6 +546,9 @@ static int Vector_ass_item(VectorObject * self, int i, PyObject * ob)
return -1;
}
self->vec[i] = scalar;
+
+ if(!Vector_WriteIndexCallback(self, i))
+ return -1;
return 0;
}
@@ -512,6 +559,9 @@ static PyObject *Vector_slice(VectorObject * self, int begin, int end)
PyObject *list = NULL;
int count;
+ if(!Vector_ReadCallback(self))
+ return NULL;
+
CLAMP(begin, 0, self->size);
if (end<0) end= self->size+end+1;
CLAMP(end, 0, self->size);
@@ -534,6 +584,9 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end,
float vec[4], scalar;
PyObject *v;
+ if(!Vector_ReadCallback(self))
+ return -1;
+
CLAMP(begin, 0, self->size);
if (end<0) end= self->size+end+1;
CLAMP(end, 0, self->size);
@@ -566,6 +619,10 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end,
for(y = 0; y < size; y++){
self->vec[begin + y] = vec[y];
}
+
+ if(!Vector_WriteCallback(self))
+ return -1;
+
return 0;
}
/*------------------------NUMERIC PROTOCOLS----------------------
@@ -586,6 +643,10 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2)
/* make sure v1 is always the vector */
if (vec1 && vec2 ) {
+
+ if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2))
+ return NULL;
+
/*VECTOR + VECTOR*/
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation\n");
@@ -617,6 +678,10 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2)
/* make sure v1 is always the vector */
if (vec1 && vec2 ) {
+
+ if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2))
+ return NULL;
+
/*VECTOR + VECTOR*/
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation\n");
@@ -629,6 +694,7 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2)
return v1;
}
+ Vector_WriteCallback(vec1);
PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n");
return NULL;
}
@@ -648,6 +714,9 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2)
vec1 = (VectorObject*)v1;
vec2 = (VectorObject*)v2;
+ if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2))
+ return NULL;
+
if(vec1->size != vec2->size) {
PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation\n");
return NULL;
@@ -663,7 +732,7 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2)
subtraction*/
static PyObject *Vector_isub(PyObject * v1, PyObject * v2)
{
- int i, size;
+ int i;
VectorObject *vec1 = NULL, *vec2 = NULL;
if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) {
@@ -677,12 +746,15 @@ static PyObject *Vector_isub(PyObject * v1, PyObject * v2)
PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation\n");
return NULL;
}
+
+ if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2))
+ return NULL;
- size = vec1->size;
for(i = 0; i < vec1->size; i++) {
vec1->vec[i] = vec1->vec[i] - vec2->vec[i];
}
+ Vector_WriteCallback(vec1);
Py_INCREF( v1 );
return v1;
}
@@ -694,11 +766,17 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
VectorObject *vec1 = NULL, *vec2 = NULL;
float scalar;
- if VectorObject_Check(v1)
+ if VectorObject_Check(v1) {
vec1= (VectorObject *)v1;
-
- if VectorObject_Check(v2)
+ if(!Vector_ReadCallback(vec1))
+ return NULL;
+ }
+ if VectorObject_Check(v2) {
vec2= (VectorObject *)v2;
+ if(!Vector_ReadCallback(vec2))
+ return NULL;
+ }
+
/* make sure v1 is always the vector */
if (vec1 && vec2 ) {
@@ -757,6 +835,9 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
int i;
float scalar;
+ if(!Vector_ReadCallback(vec))
+ return NULL;
+
/* only support vec*=float and vec*=mat
vec*=vec result is a float so that wont work */
if (MatrixObject_Check(v2)) {
@@ -787,22 +868,21 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
}
vec->vec[i] = (float)dot;
}
- Py_INCREF( v1 );
- return v1;
}
else if (((scalar= PyFloat_AsDouble(v2)) == -1.0 && PyErr_Occurred())==0) { /* VEC*=FLOAT */
for(i = 0; i < vec->size; i++) {
vec->vec[i] *= scalar;
}
-
- Py_INCREF( v1 );
- return v1;
-
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
+ return NULL;
}
- PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation\n");
- return NULL;
+ Vector_WriteCallback(vec);
+ Py_INCREF( v1 );
+ return v1;
}
/*------------------------obj / obj------------------------------
@@ -819,6 +899,9 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2)
}
vec1 = (VectorObject*)v1; /* vector */
+ if(!Vector_ReadCallback(vec1))
+ return NULL;
+
scalar = (float)PyFloat_AsDouble(v2);
if(scalar== -1.0f && PyErr_Occurred()) { /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
@@ -842,14 +925,10 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2)
{
int i;
float scalar;
- VectorObject *vec1 = NULL;
+ VectorObject *vec1 = (VectorObject*)v1;
- /*if(!VectorObject_Check(v1)) {
- PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float\n");
- return -1;
- }*/
-
- vec1 = (VectorObject*)v1; /* vector */
+ if(!Vector_ReadCallback(vec1))
+ return NULL;
scalar = (float)PyFloat_AsDouble(v2);
if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
@@ -864,6 +943,9 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2)
for(i = 0; i < vec1->size; i++) {
vec1->vec[i] /= scalar;
}
+
+ Vector_WriteCallback(vec1);
+
Py_INCREF( v1 );
return v1;
}
@@ -874,6 +956,10 @@ static PyObject *Vector_neg(VectorObject *self)
{
int i;
float vec[4];
+
+ if(!Vector_ReadCallback(self))
+ return NULL;
+
for(i = 0; i < self->size; i++){
vec[i] = -self->vec[i];
}
@@ -919,6 +1005,9 @@ static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa
vecA = (VectorObject*)objectA;
vecB = (VectorObject*)objectB;
+ if(!Vector_ReadCallback(vecA) || !Vector_ReadCallback(vecB))
+ return NULL;
+
if (vecA->size != vecB->size){
if (comparison_type == Py_NE){
Py_RETURN_TRUE;
@@ -1045,66 +1134,12 @@ static PyNumberMethods Vector_NumMethods = {
static PyObject *Vector_getAxis( VectorObject * self, void *type )
{
- switch( (long)type ) {
- case 'X': /* these are backwards, but that how it works */
- return PyFloat_FromDouble(self->vec[0]);
- case 'Y':
- return PyFloat_FromDouble(self->vec[1]);
- case 'Z': /* these are backwards, but that how it works */
- if(self->size < 3) {
- PyErr_SetString(PyExc_AttributeError, "vector.z: error, cannot get this axis for a 2D vector\n");
- return NULL;
- }
- else {
- return PyFloat_FromDouble(self->vec[2]);
- }
- case 'W':
- if(self->size < 4) {
- PyErr_SetString(PyExc_AttributeError, "vector.w: error, cannot get this axis for a 3D vector\n");
- return NULL;
- }
-
- return PyFloat_FromDouble(self->vec[3]);
- default:
- {
- PyErr_SetString( PyExc_RuntimeError, "undefined type in Vector_getAxis" );
- return NULL;
- }
- }
+ return Vector_item(self, (int)type);
}
static int Vector_setAxis( VectorObject * self, PyObject * value, void * type )
{
- float param= (float)PyFloat_AsDouble( value );
-
- if (param==-1 && PyErr_Occurred()) {
- PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" );
- return -1;
- }
- switch( (long)type ) {
- case 'X': /* these are backwards, but that how it works */
- self->vec[0]= param;
- break;
- case 'Y':
- self->vec[1]= param;
- break;
- case 'Z': /* these are backwards, but that how it works */
- if(self->size < 3) {
- PyErr_SetString(PyExc_AttributeError, "vector.z: error, cannot get this axis for a 2D vector\n");
- return -1;
- }
- self->vec[2]= param;
- break;
- case 'W':
- if(self->size < 4) {
- PyErr_SetString(PyExc_AttributeError, "vector.w: error, cannot get this axis for a 3D vector\n");
- return -1;
- }
- self->vec[3]= param;
- break;
- }
-
- return 0;
+ return Vector_ass_item(self, (int)type, value);
}
/* vector.length */
@@ -1113,6 +1148,9 @@ static PyObject *Vector_getLength( VectorObject * self, void *type )
double dot = 0.0f;
int i;
+ if(!Vector_ReadCallback(self))
+ return NULL;
+
for(i = 0; i < self->size; i++){
dot += (self->vec[i] * self->vec[i]);
}
@@ -1124,6 +1162,9 @@ static int Vector_setLength( VectorObject * self, PyObject * value )
double dot = 0.0f, param;
int i;
+ if(!Vector_ReadCallback(self))
+ return -1;
+
param= PyFloat_AsDouble( value );
if(param==-1.0 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "length must be set to a number");
@@ -1159,6 +1200,8 @@ static int Vector_setLength( VectorObject * self, PyObject * value )
self->vec[i]= self->vec[i] / (float)dot;
}
+ Vector_WriteCallback(self); /* checked alredy */
+
return 0;
}
@@ -1170,6 +1213,16 @@ static PyObject *Vector_getWrapped( VectorObject * self, void *type )
Py_RETURN_FALSE;
}
+static PyObject *Vector_getOwner( VectorObject * self, void *type )
+{
+ if(self->user==NULL) {
+ Py_RETURN_NONE;
+ }
+ else {
+ Py_INCREF(self->user);
+ return self->user;
+ }
+}
/* Get a new Vector according to the provided swizzle. This function has little
error checking, as we are in control of the inputs: the closure is set by us
@@ -1181,6 +1234,9 @@ static PyObject *Vector_getSwizzle(VectorObject * self, void *closure)
float vec[MAX_DIMENSIONS];
unsigned int swizzleClosure;
+ if(!Vector_ReadCallback(self))
+ return NULL;
+
/* Unpack the axes from the closure into an array. */
axisA = 0;
swizzleClosure = (unsigned int) closure;
@@ -1218,6 +1274,9 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur
float vecTemp[MAX_DIMENSIONS];
+ if(!Vector_ReadCallback(self))
+ return -1;
+
/* Check that the closure can be used with this vector: even 2D vectors have
swizzles defined for axes z and w, but they would be invalid. */
swizzleClosure = (unsigned int) closure;
@@ -1247,7 +1306,7 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur
axisB++;
}
memcpy(self->vec, vecTemp, axisB * sizeof(float));
- return 0;
+ /* continue with Vector_WriteCallback at the end */
}
else if (PyList_Check(value))
{
@@ -1273,7 +1332,7 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur
axisB++;
}
memcpy(self->vec, vecTemp, axisB * sizeof(float));
- return 0;
+ /* continue with Vector_WriteCallback at the end */
}
else if (((scalarVal = (float)PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred())==0)
{
@@ -1286,13 +1345,17 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur
swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
}
- return 0;
+ /* continue with Vector_WriteCallback at the end */
}
- else
- {
+ else {
PyErr_SetString( PyExc_TypeError, "Expected a Vector, list or scalar value." );
return -1;
}
+
+ if(!Vector_WriteCallback(vecVal))
+ return -1;
+ else
+ return 0;
}
/*****************************************************************************/
@@ -1302,19 +1365,19 @@ static PyGetSetDef Vector_getseters[] = {
{"x",
(getter)Vector_getAxis, (setter)Vector_setAxis,
"Vector X axis",
- (void *)'X'},
+ (void *)0},
{"y",
(getter)Vector_getAxis, (setter)Vector_setAxis,
"Vector Y axis",
- (void *)'Y'},
+ (void *)1},
{"z",
(getter)Vector_getAxis, (setter)Vector_setAxis,
"Vector Z axis",
- (void *)'Z'},
+ (void *)2},
{"w",
(getter)Vector_getAxis, (setter)Vector_setAxis,
"Vector Z axis",
- (void *)'W'},
+ (void *)3},
{"length",
(getter)Vector_getLength, (setter)Vector_setLength,
"Vector Length",
@@ -1327,6 +1390,10 @@ static PyGetSetDef Vector_getseters[] = {
(getter)Vector_getWrapped, (setter)NULL,
"True when this wraps blenders internal data",
NULL},
+ {"__owner__",
+ (getter)Vector_getOwner, (setter)NULL,
+ "Read only owner for vectors that depend on another object",
+ NULL},
/* autogenerated swizzle attrs, see python script below */
{"xx", (getter)Vector_getSwizzle, (setter)Vector_setSwizzle, Vector_swizzle_doc, (void *)((unsigned int)((0|SWIZZLE_VALID_AXIS) | ((0|SWIZZLE_VALID_AXIS)<<SWIZZLE_BITS_PER_AXIS)))}, /* 36 */
@@ -1843,20 +1910,72 @@ PyObject *newVectorObject(float *vec, int size, int type)
return (PyObject *) self;
}
-/*
- #############################DEPRECATED################################
- #######################################################################
- ----------------------------Vector.negate() --------------------
+PyObject *newVectorObject_cb(PyObject *user, int size, int callback_type, int subtype)
+{
+ float dummy[4] = {0.0, 0.0, 0.0, 0.0}; /* the same vector is used because its set each time by the user callback, saves a little ram */
+ VectorObject *self= newVectorObject(dummy, size, Py_NEW);
+ if(self) {
+ Py_INCREF(user);
+ self->user= user;
+ self->callback_type = (unsigned char)callback_type;
+ self->subtype = (unsigned char)subtype;
+ }
+
+ return self;
+}
+
+//-----------------row_vector_multiplication (internal)-----------
+//ROW VECTOR Multiplication - Vector X Matrix
+//[x][y][z] * [1][2][3]
+// [4][5][6]
+// [7][8][9]
+//vector/matrix multiplication IS NOT COMMUTATIVE!!!!
+static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat)
+{
+ float vecNew[4], vecCopy[4];
+ double dot = 0.0f;
+ int x, y, z = 0, vec_size = vec->size;
+
+ if(mat->colSize != vec_size){
+ if(mat->rowSize == 4 && vec_size != 3){
+ PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same");
+ return NULL;
+ }else{
+ vecCopy[3] = 1.0f;
+ }
+ }
+
+ if(!Vector_ReadCallback(vec))
+ return NULL;
+
+ for(x = 0; x < vec_size; x++){
+ vecCopy[x] = vec->vec[x];
+ }
+
+ //muliplication
+ for(x = 0; x < mat->colSize; x++) {
+ for(y = 0; y < mat->rowSize; y++) {
+ dot += mat->matrix[y][x] * vecCopy[y];
+ }
+ vecNew[z++] = (float)dot;
+ dot = 0.0f;
+ }
+ return newVectorObject(vecNew, vec_size, Py_NEW);
+}
+
+/*----------------------------Vector.negate() --------------------
set the vector to it's negative -x, -y, -z */
static PyObject *Vector_Negate(VectorObject * self)
{
int i;
- for(i = 0; i < self->size; i++) {
+ if(!Vector_ReadCallback(self))
+ return NULL;
+
+ for(i = 0; i < self->size; i++)
self->vec[i] = -(self->vec[i]);
- }
- /*printf("Vector.negate(): Deprecated: use -vector instead\n");*/
+
+ Vector_WriteCallback(self); // alredy checked for error
+
Py_INCREF(self);
return (PyObject*)self;
}
-/*###################################################################
- ###########################DEPRECATED##############################*/