static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyObject *args) { VectorObject *line_a, *line_b, *sphere_co; float sphere_radius; int clip = TRUE; float isect_a[3]; float isect_b[3]; if (!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere_2d", &vector_Type, &line_a, &vector_Type, &line_b, &vector_Type, &sphere_co, &sphere_radius, &clip)) { return NULL; } if (BaseMath_ReadCallback(line_a) == -1 || BaseMath_ReadCallback(line_b) == -1 || BaseMath_ReadCallback(sphere_co) == -1) { return NULL; } else { short use_a = TRUE; short use_b = TRUE; float lambda; PyObject *ret = PyTuple_New(2); switch (isect_line_sphere_v2(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) { case 1: if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = FALSE; use_b = FALSE; break; case 2: if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = FALSE; if (!(!clip || (((lambda = line_point_factor_v2(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b = FALSE; break; default: use_a = FALSE; use_b = FALSE; } if (use_a) { PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(isect_a, 2, Py_NEW, NULL)); } else { PyTuple_SET_ITEM(ret, 0, Py_None); Py_INCREF(Py_None); } if (use_b) { PyTuple_SET_ITEM(ret, 1, Vector_CreatePyObject(isect_b, 2, Py_NEW, NULL)); } else { PyTuple_SET_ITEM(ret, 1, Py_None); Py_INCREF(Py_None); } return ret; } }
static PyObject *M_Geometry_intersect_line_line_2d(PyObject *UNUSED(self), PyObject *args) { VectorObject *line_a1, *line_a2, *line_b1, *line_b2; float vi[2]; if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_line_line_2d", &vector_Type, &line_a1, &vector_Type, &line_a2, &vector_Type, &line_b1, &vector_Type, &line_b2)) { return NULL; } if (BaseMath_ReadCallback(line_a1) == -1 || BaseMath_ReadCallback(line_a2) == -1 || BaseMath_ReadCallback(line_b1) == -1 || BaseMath_ReadCallback(line_b2) == -1) { return NULL; } if (isect_seg_seg_v2_point(line_a1->vec, line_a2->vec, line_b1->vec, line_b2->vec, vi) == 1) { return Vector_CreatePyObject(vi, 2, Py_NEW, NULL); } else { Py_RETURN_NONE; } }
static PyObject *Freestyle_blendRamp(PyObject *self, PyObject *args) { PyObject *obj1, *obj2; char *s; int type; float a[3], fac, b[3]; if (!PyArg_ParseTuple(args, "sOfO", &s, &obj1, &fac, &obj2)) return NULL; type = ramp_blend_type(s); if (type < 0) { PyErr_SetString(PyExc_TypeError, "argument 1 is an unknown ramp blend type"); return NULL; } if (!float_array_from_PyObject(obj1, a, 3)) { PyErr_SetString(PyExc_TypeError, "argument 2 must be a 3D vector (either a tuple/list of 3 elements or Vector)"); return NULL; } if (!float_array_from_PyObject(obj2, b, 3)) { PyErr_SetString(PyExc_TypeError, "argument 4 must be a 3D vector (either a tuple/list of 3 elements or Vector)"); return NULL; } ramp_blend(type, a, fac, b); return Vector_CreatePyObject(a, 3, Py_NEW, NULL); }
PyObject *Vector_from_Vec2f(Vec2f& vec) { float vec_data[2]; // because vec->_coord is protected vec_data[0] = vec.x(); vec_data[1] = vec.y(); return Vector_CreatePyObject(vec_data, 2, Py_NEW, NULL); }
PyObject *Vector_from_Vec3r(Vec3r& vec) { float vec_data[3]; // because vec->_coord is protected vec_data[0] = vec.x(); vec_data[1] = vec.y(); vec_data[2] = vec.z(); return Vector_CreatePyObject(vec_data, 3, NULL); }
static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject *args) { VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2; int resolu; int dims; int i; float *coord_array, *fp; PyObject *list; float k1[4] = {0.0, 0.0, 0.0, 0.0}; float h1[4] = {0.0, 0.0, 0.0, 0.0}; float k2[4] = {0.0, 0.0, 0.0, 0.0}; float h2[4] = {0.0, 0.0, 0.0, 0.0}; if (!PyArg_ParseTuple(args, "O!O!O!O!i:interpolate_bezier", &vector_Type, &vec_k1, &vector_Type, &vec_h1, &vector_Type, &vec_h2, &vector_Type, &vec_k2, &resolu)) { return NULL; } if (resolu <= 1) { PyErr_SetString(PyExc_ValueError, "resolution must be 2 or over"); return NULL; } if (BaseMath_ReadCallback(vec_k1) == -1 || BaseMath_ReadCallback(vec_h1) == -1 || BaseMath_ReadCallback(vec_k2) == -1 || BaseMath_ReadCallback(vec_h2) == -1) { return NULL; } dims = MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size); for (i = 0; i < vec_k1->size; i++) k1[i] = vec_k1->vec[i]; for (i = 0; i < vec_h1->size; i++) h1[i] = vec_h1->vec[i]; for (i = 0; i < vec_k2->size; i++) k2[i] = vec_k2->vec[i]; for (i = 0; i < vec_h2->size; i++) h2[i] = vec_h2->vec[i]; coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "interpolate_bezier"); for (i = 0; i < dims; i++) { BKE_curve_forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array + i, resolu - 1, sizeof(float) * dims); } list = PyList_New(resolu); fp = coord_array; for (i = 0; i < resolu; i++, fp = fp + dims) { PyList_SET_ITEM(list, i, Vector_CreatePyObject(fp, dims, Py_NEW, NULL)); } MEM_freeN(coord_array); return list; }
static void kdtree_nearest_to_py_tuple(const KDTreeNearest *nearest, PyObject *py_retval) { BLI_assert(nearest->index >= 0); BLI_assert(PyTuple_GET_SIZE(py_retval) == 3); PyTuple_SET_ITEM(py_retval, 0, Vector_CreatePyObject((float *)nearest->co, 3, Py_NEW, NULL)); PyTuple_SET_ITEM(py_retval, 1, PyLong_FromLong(nearest->index)); PyTuple_SET_ITEM(py_retval, 2, PyFloat_FromDouble(nearest->dist)); }
static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObject *args) { PyObject *ret; VectorObject *plane_a_co, *plane_a_no, *plane_b_co, *plane_b_no; float isect_co[3]; float isect_no[3]; if (!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_plane_plane", &vector_Type, &plane_a_co, &vector_Type, &plane_a_no, &vector_Type, &plane_b_co, &vector_Type, &plane_b_no)) { return NULL; } if (BaseMath_ReadCallback(plane_a_co) == -1 || BaseMath_ReadCallback(plane_a_no) == -1 || BaseMath_ReadCallback(plane_b_co) == -1 || BaseMath_ReadCallback(plane_b_no) == -1) { return NULL; } if (ELEM4(2, plane_a_co->size, plane_a_no->size, plane_b_co->size, plane_b_no->size)) { PyErr_SetString(PyExc_ValueError, "geometry.intersect_plane_plane(...): " " can't use 2D Vectors"); return NULL; } isect_plane_plane_v3(isect_co, isect_no, plane_a_co->vec, plane_a_no->vec, plane_b_co->vec, plane_b_no->vec); normalize_v3(isect_no); ret = PyTuple_New(2); PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(isect_co, 3, Py_NEW, NULL)); PyTuple_SET_ITEM(ret, 1, Vector_CreatePyObject(isect_no, 3, Py_NEW, NULL)); return ret; }
PyObject *PyObjectFrom(const MT_Tuple2 &vec) { #ifdef USE_MATHUTILS float fvec[2]; vec.getValue(fvec); return Vector_CreatePyObject(fvec, 2, NULL); #else PyObject *list = PyList_New(2); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1])); return list; #endif }
static PyObject *Quaternion_axis_vector_get(QuaternionObject *self, void *UNUSED(closure)) { float tquat[4]; float axis[3]; float angle_dummy; if (BaseMath_ReadCallback(self) == -1) return NULL; normalize_qt_qt(tquat, self->quat); quat_to_axis_angle(axis, &angle_dummy, tquat); quat__axis_angle_sanitize(axis, NULL); return Vector_CreatePyObject(axis, 3, Py_NEW, NULL); }
static PyObject *Freestyle_evaluateColorRamp(PyObject *self, PyObject *args) { BPy_StructRNA *py_srna; ColorBand *coba; float in, out[4]; if (!(PyArg_ParseTuple(args, "O!f", &pyrna_struct_Type, &py_srna, &in))) return NULL; if (!RNA_struct_is_a(py_srna->ptr.type, &RNA_ColorRamp)) { PyErr_SetString(PyExc_TypeError, "1st argument is not a ColorRamp object"); return NULL; } coba = (ColorBand *)py_srna->ptr.data; if (!do_colorband(coba, in, out)) { PyErr_SetString(PyExc_ValueError, "failed to evaluate the color ramp"); return NULL; } return Vector_CreatePyObject(out, 4, Py_NEW, NULL); }
static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObject *args) { VectorObject *pt, *line_1, *line_2; float pt_in[3], pt_out[3], l1[3], l2[3]; float lambda; PyObject *ret; if (!PyArg_ParseTuple(args, "O!O!O!:intersect_point_line", &vector_Type, &pt, &vector_Type, &line_1, &vector_Type, &line_2)) { return NULL; } if (BaseMath_ReadCallback(pt) == -1 || BaseMath_ReadCallback(line_1) == -1 || BaseMath_ReadCallback(line_2) == -1) { return NULL; } /* accept 2d verts */ if (pt->size == 3) { copy_v3_v3(pt_in, pt->vec); } else { pt_in[2] = 0.0f; copy_v2_v2(pt_in, pt->vec); } if (line_1->size == 3) { copy_v3_v3(l1, line_1->vec); } else { l1[2] = 0.0f; copy_v2_v2(l1, line_1->vec); } if (line_2->size == 3) { copy_v3_v3(l2, line_2->vec); } else { l2[2] = 0.0f; copy_v2_v2(l2, line_2->vec); } /* do the calculation */ lambda = closest_to_line_v3(pt_out, pt_in, l1, l2); ret = PyTuple_New(2); PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(pt_out, 3, Py_NEW, NULL)); PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(lambda)); return ret; }
static PyObject *Quaternion_to_axis_angle(QuaternionObject *self) { PyObject *ret; float tquat[4]; float axis[3]; float angle; if (BaseMath_ReadCallback(self) == -1) return NULL; normalize_qt_qt(tquat, self->quat); quat_to_axis_angle(axis, &angle, tquat); quat__axis_angle_sanitize(axis, &angle); ret = PyTuple_New(2); PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(axis, 3, Py_NEW, NULL)); PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(angle)); return ret; }
static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObject *args) { VectorObject *vec_pt; VectorObject *vec_t1_tar, *vec_t2_tar, *vec_t3_tar; VectorObject *vec_t1_src, *vec_t2_src, *vec_t3_src; float vec[3]; if (!PyArg_ParseTuple(args, "O!O!O!O!O!O!O!:barycentric_transform", &vector_Type, &vec_pt, &vector_Type, &vec_t1_src, &vector_Type, &vec_t2_src, &vector_Type, &vec_t3_src, &vector_Type, &vec_t1_tar, &vector_Type, &vec_t2_tar, &vector_Type, &vec_t3_tar)) { return NULL; } if (vec_pt->size != 3 || vec_t1_src->size != 3 || vec_t2_src->size != 3 || vec_t3_src->size != 3 || vec_t1_tar->size != 3 || vec_t2_tar->size != 3 || vec_t3_tar->size != 3) { PyErr_SetString(PyExc_ValueError, "One of more of the vector arguments wasn't a 3D vector"); return NULL; } barycentric_transform(vec, vec_pt->vec, vec_t1_tar->vec, vec_t2_tar->vec, vec_t3_tar->vec, vec_t1_src->vec, vec_t2_src->vec, vec_t3_src->vec); return Vector_CreatePyObject(vec, 3, Py_NEW, NULL); }
static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObject *args) { VectorObject *line_a, *line_b, *plane_co, *plane_no; int no_flip = 0; float isect[3]; if (!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_line_plane", &vector_Type, &line_a, &vector_Type, &line_b, &vector_Type, &plane_co, &vector_Type, &plane_no, &no_flip)) { return NULL; } if (BaseMath_ReadCallback(line_a) == -1 || BaseMath_ReadCallback(line_b) == -1 || BaseMath_ReadCallback(plane_co) == -1 || BaseMath_ReadCallback(plane_no) == -1) { return NULL; } if (ELEM4(2, line_a->size, line_b->size, plane_co->size, plane_no->size)) { PyErr_SetString(PyExc_ValueError, "geometry.intersect_line_plane(...): " " can't use 2D Vectors"); return NULL; } if (isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec, no_flip) == 1) { return Vector_CreatePyObject(isect, 3, Py_NEW, NULL); } else { Py_RETURN_NONE; } }
static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject *args) { VectorObject *vec1, *vec2, *vec3, *vec4; float n[3]; if (PyTuple_GET_SIZE(args) == 3) { if (!PyArg_ParseTuple(args, "O!O!O!:normal", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3)) { return NULL; } if (vec1->size != vec2->size || vec1->size != vec3->size) { PyErr_SetString(PyExc_ValueError, "vectors must be of the same size"); return NULL; } if (vec1->size < 3) { PyErr_SetString(PyExc_ValueError, "2D vectors unsupported"); return NULL; } if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1) { return NULL; } normal_tri_v3(n, vec1->vec, vec2->vec, vec3->vec); } else { if (!PyArg_ParseTuple(args, "O!O!O!O!:normal", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4)) { return NULL; } if (vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) { PyErr_SetString(PyExc_ValueError, "vectors must be of the same size"); return NULL; } if (vec1->size < 3) { PyErr_SetString(PyExc_ValueError, "2D vectors unsupported"); return NULL; } if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1 || BaseMath_ReadCallback(vec4) == -1) { return NULL; } normal_quad_v3(n, vec1->vec, vec2->vec, vec3->vec, vec4->vec); } return Vector_CreatePyObject(n, 3, Py_NEW, NULL); }
/* note, this is called as a python 'getset, where the PyAttributeDef is the closure */ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef *attrdef) { PyObjectPlus *ref= (BGE_PROXY_REF(self_py)); char* ptr = (attrdef->m_usePtr) ? (char*)BGE_PROXY_PTR(self_py) : (char*)ref; if (ptr == NULL || (BGE_PROXY_PYREF(self_py) && (ref==NULL || !ref->py_is_valid()))) { if (attrdef == BGE_PY_ATTR_INVALID) Py_RETURN_TRUE; // don't bother running the function PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); return NULL; } if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY) { // fake attribute, ignore return NULL; } if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION) { // the attribute has no field correspondence, handover processing to function. if (attrdef->m_getFunction == NULL) return NULL; return (*attrdef->m_getFunction)(ptr, attrdef); } ptr += attrdef->m_offset; if (attrdef->m_length > 1) { PyObject *resultlist = PyList_New(attrdef->m_length); for (unsigned int i=0; i<attrdef->m_length; i++) { switch (attrdef->m_type) { case KX_PYATTRIBUTE_TYPE_BOOL: { bool *val = reinterpret_cast<bool*>(ptr); ptr += sizeof(bool); PyList_SET_ITEM(resultlist, i, PyBool_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_SHORT: { short int *val = reinterpret_cast<short int*>(ptr); ptr += sizeof(short int); PyList_SET_ITEM(resultlist, i, PyLong_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_ENUM: // enum are like int, just make sure the field size is the same if (sizeof(int) != attrdef->m_size) { Py_DECREF(resultlist); return NULL; } // walkthrough case KX_PYATTRIBUTE_TYPE_INT: { int *val = reinterpret_cast<int*>(ptr); ptr += sizeof(int); PyList_SET_ITEM(resultlist, i, PyLong_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_FLOAT: { float *val = reinterpret_cast<float*>(ptr); ptr += sizeof(float); PyList_SET_ITEM(resultlist, i, PyFloat_FromDouble(*val)); break; } default: // no support for array of complex data Py_DECREF(resultlist); return NULL; } } return resultlist; } else { switch (attrdef->m_type) { case KX_PYATTRIBUTE_TYPE_FLAG: { bool bval; switch (attrdef->m_size) { case 1: { unsigned char *val = reinterpret_cast<unsigned char*>(ptr); bval = (*val & attrdef->m_imin); break; } case 2: { unsigned short *val = reinterpret_cast<unsigned short*>(ptr); bval = (*val & attrdef->m_imin); break; } case 4: { unsigned int *val = reinterpret_cast<unsigned int*>(ptr); bval = (*val & attrdef->m_imin); break; } default: return NULL; } if (attrdef->m_imax) bval = !bval; return PyBool_FromLong(bval); } case KX_PYATTRIBUTE_TYPE_BOOL: { bool *val = reinterpret_cast<bool*>(ptr); return PyBool_FromLong(*val); } case KX_PYATTRIBUTE_TYPE_SHORT: { short int *val = reinterpret_cast<short int*>(ptr); return PyLong_FromLong(*val); } case KX_PYATTRIBUTE_TYPE_ENUM: // enum are like int, just make sure the field size is the same if (sizeof(int) != attrdef->m_size) { return NULL; } // walkthrough case KX_PYATTRIBUTE_TYPE_INT: { int *val = reinterpret_cast<int*>(ptr); return PyLong_FromLong(*val); } case KX_PYATTRIBUTE_TYPE_FLOAT: { float *val = reinterpret_cast<float*>(ptr); if (attrdef->m_imin == 0) { if (attrdef->m_imax == 0) { return PyFloat_FromDouble(*val); } else { // vector, verify size if (attrdef->m_size != attrdef->m_imax*sizeof(float)) { return NULL; } #ifdef USE_MATHUTILS return Vector_CreatePyObject(val, attrdef->m_imax, NULL); #else PyObject *resultlist = PyList_New(attrdef->m_imax); for (unsigned int i=0; i<attrdef->m_imax; i++) { PyList_SET_ITEM(resultlist, i, PyFloat_FromDouble(val[i])); } return resultlist; #endif } } else { // matrix case if (attrdef->m_size != attrdef->m_imax*attrdef->m_imin*sizeof(float)) { return NULL; } #ifdef USE_MATHUTILS return Matrix_CreatePyObject_wrap(val, attrdef->m_imin, attrdef->m_imax, NULL); #else PyObject *collist = PyList_New(attrdef->m_imin); for (unsigned int i=0; i<attrdef->m_imin; i++) { PyObject *col = PyList_New(attrdef->m_imax); for (unsigned int j=0; j<attrdef->m_imax; j++) { PyList_SET_ITEM(col, j, PyFloat_FromDouble(val[j])); } PyList_SET_ITEM(collist, i, col); val += attrdef->m_imax; } return collist; #endif } } case KX_PYATTRIBUTE_TYPE_VECTOR: { MT_Vector3 *val = reinterpret_cast<MT_Vector3*>(ptr); #ifdef USE_MATHUTILS float fval[3]; val->getValue(fval); return Vector_CreatePyObject(fval, 3, NULL); #else PyObject *resultlist = PyList_New(3); for (unsigned int i=0; i<3; i++) { PyList_SET_ITEM(resultlist, i, PyFloat_FromDouble((*val)[i])); } return resultlist; #endif } case KX_PYATTRIBUTE_TYPE_STRING: { STR_String *val = reinterpret_cast<STR_String*>(ptr); return PyUnicode_From_STR_String(*val); } case KX_PYATTRIBUTE_TYPE_CHAR: { return PyUnicode_FromString(ptr); } default: return NULL; } } }
PyObject* BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef) { bPoseChannel* pchan = static_cast<bPoseChannel*>(self_v); // decompose the pose matrix in euler rotation float rest_mat[3][3]; float pose_mat[3][3]; float joint_mat[3][3]; float joints[3]; float norm; double sa, ca; // get rotation in armature space copy_m3_m4(pose_mat, pchan->pose_mat); normalize_m3(pose_mat); if (pchan->parent) { // bone has a parent, compute the rest pose of the bone taking actual pose of parent mult_m3_m3m4(rest_mat, pchan->parent->pose_mat, pchan->bone->bone_mat); normalize_m3(rest_mat); } else { // otherwise, the bone matrix in armature space is the rest pose copy_m3_m4(rest_mat, pchan->bone->arm_mat); } // remove the rest pose to get the joint movement transpose_m3(rest_mat); mul_m3_m3m3(joint_mat, rest_mat, pose_mat); joints[0] = joints[1] = joints[2] = 0.f; // returns a 3 element list that gives corresponding joint int flag = 0; if (!(pchan->ikflag & BONE_IK_NO_XDOF)) flag |= 1; if (!(pchan->ikflag & BONE_IK_NO_YDOF)) flag |= 2; if (!(pchan->ikflag & BONE_IK_NO_ZDOF)) flag |= 4; switch (flag) { case 0: // fixed joint break; case 1: // X only mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); joints[1] = joints[2] = 0.f; break; case 2: // Y only mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); joints[0] = joints[2] = 0.f; break; case 3: // X+Y mat3_to_eulO( joints, EULER_ORDER_ZYX,joint_mat); joints[2] = 0.f; break; case 4: // Z only mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); joints[0] = joints[1] = 0.f; break; case 5: // X+Z // decompose this as an equivalent rotation vector in X/Z plane joints[0] = joint_mat[1][2]; joints[2] = -joint_mat[1][0]; norm = normalize_v3(joints); if (norm < FLT_EPSILON) { norm = (joint_mat[1][1] < 0.f) ? M_PI : 0.f; } else { norm = acos(joint_mat[1][1]); } mul_v3_fl(joints, norm); break; case 6: // Y+Z mat3_to_eulO( joints, EULER_ORDER_XYZ,joint_mat); joints[0] = 0.f; break; case 7: // X+Y+Z // equivalent axis joints[0] = (joint_mat[1][2]-joint_mat[2][1])*0.5f; joints[1] = (joint_mat[2][0]-joint_mat[0][2])*0.5f; joints[2] = (joint_mat[0][1]-joint_mat[1][0])*0.5f; sa = len_v3(joints); ca = (joint_mat[0][0]+joint_mat[1][1]+joint_mat[1][1]-1.0f)*0.5f; if (sa > FLT_EPSILON) { norm = atan2(sa,ca)/sa; } else { if (ca < 0.0) { norm = M_PI; mul_v3_fl(joints,0.f); if (joint_mat[0][0] > 0.f) { joints[0] = 1.0f; } else if (joint_mat[1][1] > 0.f) { joints[1] = 1.0f; } else { joints[2] = 1.0f; } } else { norm = 0.0; } } mul_v3_fl(joints,norm); break; } return Vector_CreatePyObject(joints, 3, Py_NEW, NULL); }
static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject *args) { VectorObject *ray, *ray_off, *vec1, *vec2, *vec3; float dir[3], orig[3], v1[3], v2[3], v3[3], e1[3], e2[3], pvec[3], tvec[3], qvec[3]; float det, inv_det, u, v, t; int clip = 1; if (!PyArg_ParseTuple(args, "O!O!O!O!O!|i:intersect_ray_tri", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &ray, &vector_Type, &ray_off, &clip)) { return NULL; } if (vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) { PyErr_SetString(PyExc_ValueError, "only 3D vectors for all parameters"); return NULL; } if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1 || BaseMath_ReadCallback(ray) == -1 || BaseMath_ReadCallback(ray_off) == -1) { return NULL; } copy_v3_v3(v1, vec1->vec); copy_v3_v3(v2, vec2->vec); copy_v3_v3(v3, vec3->vec); copy_v3_v3(dir, ray->vec); normalize_v3(dir); copy_v3_v3(orig, ray_off->vec); /* find vectors for two edges sharing v1 */ sub_v3_v3v3(e1, v2, v1); sub_v3_v3v3(e2, v3, v1); /* begin calculating determinant - also used to calculated U parameter */ cross_v3_v3v3(pvec, dir, e2); /* if determinant is near zero, ray lies in plane of triangle */ det = dot_v3v3(e1, pvec); if (det > -0.000001f && det < 0.000001f) { Py_RETURN_NONE; } inv_det = 1.0f / det; /* calculate distance from v1 to ray origin */ sub_v3_v3v3(tvec, orig, v1); /* calculate U parameter and test bounds */ u = dot_v3v3(tvec, pvec) * inv_det; if (clip && (u < 0.0f || u > 1.0f)) { Py_RETURN_NONE; } /* prepare to test the V parameter */ cross_v3_v3v3(qvec, tvec, e1); /* calculate V parameter and test bounds */ v = dot_v3v3(dir, qvec) * inv_det; if (clip && (v < 0.0f || u + v > 1.0f)) { Py_RETURN_NONE; } /* calculate t, ray intersects triangle */ t = dot_v3v3(e2, qvec) * inv_det; mul_v3_fl(dir, t); add_v3_v3v3(pvec, orig, dir); return Vector_CreatePyObject(pvec, 3, Py_NEW, NULL); }
static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject *args) { PyObject *tuple; VectorObject *vec1, *vec2, *vec3, *vec4; float v1[3], v2[3], v3[3], v4[3], i1[3], i2[3]; if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_line_line", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4)) { return NULL; } if (vec1->size != vec2->size || vec1->size != vec3->size || vec3->size != vec2->size) { PyErr_SetString(PyExc_ValueError, "vectors must be of the same size"); return NULL; } if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1 || BaseMath_ReadCallback(vec4) == -1) { return NULL; } if (vec1->size == 3 || vec1->size == 2) { int result; if (vec1->size == 3) { copy_v3_v3(v1, vec1->vec); copy_v3_v3(v2, vec2->vec); copy_v3_v3(v3, vec3->vec); copy_v3_v3(v4, vec4->vec); } else { v1[0] = vec1->vec[0]; v1[1] = vec1->vec[1]; v1[2] = 0.0f; v2[0] = vec2->vec[0]; v2[1] = vec2->vec[1]; v2[2] = 0.0f; v3[0] = vec3->vec[0]; v3[1] = vec3->vec[1]; v3[2] = 0.0f; v4[0] = vec4->vec[0]; v4[1] = vec4->vec[1]; v4[2] = 0.0f; } result = isect_line_line_v3(v1, v2, v3, v4, i1, i2); if (result == 0) { /* colinear */ Py_RETURN_NONE; } else { tuple = PyTuple_New(2); PyTuple_SET_ITEM(tuple, 0, Vector_CreatePyObject(i1, vec1->size, Py_NEW, NULL)); PyTuple_SET_ITEM(tuple, 1, Vector_CreatePyObject(i2, vec1->size, Py_NEW, NULL)); return tuple; } } else { PyErr_SetString(PyExc_ValueError, "2D/3D vectors only"); return NULL; } }
/** *\brief BMElem.__getitem__() * * assume all error checks are done, eg: * * uv = vert[uv_layer] */ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer) { void *value = bpy_bmlayeritem_ptr_get(py_ele, py_layer); PyObject *ret; if (UNLIKELY(value == NULL)) { return NULL; } switch (py_layer->type) { case CD_MDEFORMVERT: { ret = BPy_BMDeformVert_CreatePyObject(value); break; } case CD_PROP_FLT: { ret = PyFloat_FromDouble(*(float *)value); break; } case CD_PROP_INT: { ret = PyLong_FromLong(*(int *)value); break; } case CD_PROP_STR: { MStringProperty *mstring = value; ret = PyBytes_FromStringAndSize(mstring->s, mstring->s_len); break; } case CD_MTEXPOLY: { ret = BPy_BMTexPoly_CreatePyObject(value); break; } case CD_MLOOPUV: { ret = BPy_BMLoopUV_CreatePyObject(value); break; } case CD_MLOOPCOL: { ret = BPy_BMLoopColor_CreatePyObject(value); break; } case CD_SHAPEKEY: { ret = Vector_CreatePyObject((float *)value, 3, Py_WRAP, NULL); break; } case CD_BWEIGHT: { ret = PyFloat_FromDouble(*(float *)value); break; } case CD_CREASE: { ret = PyFloat_FromDouble(*(float *)value); break; } default: { ret = Py_NotImplemented; /* TODO */ Py_INCREF(ret); break; } } return ret; }
static PyObject *bpy_bmloopuv_uv_get(BPy_BMLoopUV *self, void *UNUSED(closure)) { return Vector_CreatePyObject(self->data->uv, 2, Py_WRAP, NULL); }
//------------------------obj * obj------------------------------ //mulplication static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2) { float quat[QUAT_SIZE], scalar; QuaternionObject *quat1 = NULL, *quat2 = NULL; if (QuaternionObject_Check(q1)) { quat1 = (QuaternionObject *)q1; if (BaseMath_ReadCallback(quat1) == -1) return NULL; } if (QuaternionObject_Check(q2)) { quat2 = (QuaternionObject *)q2; if (BaseMath_ReadCallback(quat2) == -1) return NULL; } if (quat1 && quat2) { /* QUAT * QUAT (cross product) */ mul_qt_qtqt(quat, quat1->quat, quat2->quat); return Quaternion_CreatePyObject(quat, Py_NEW, Py_TYPE(q1)); } /* the only case this can happen (for a supported type is "FLOAT * QUAT") */ else if (quat2) { /* FLOAT * QUAT */ if (((scalar = PyFloat_AsDouble(q1)) == -1.0f && PyErr_Occurred()) == 0) { return quat_mul_float(quat2, scalar); } } else if (quat1) { /* QUAT * VEC */ if (VectorObject_Check(q2)) { VectorObject *vec2 = (VectorObject *)q2; float tvec[3]; if (vec2->size != 3) { PyErr_SetString(PyExc_ValueError, "Vector multiplication: " "only 3D vector rotations (with quats) " "currently supported"); return NULL; } if (BaseMath_ReadCallback(vec2) == -1) { return NULL; } copy_v3_v3(tvec, vec2->vec); mul_qt_v3(quat1->quat, tvec); return Vector_CreatePyObject(tvec, 3, Py_NEW, Py_TYPE(vec2)); } /* QUAT * FLOAT */ else if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) { return quat_mul_float(quat1, scalar); } } else { BLI_assert(!"internal error"); } PyErr_Format(PyExc_TypeError, "Quaternion multiplication: " "not supported between '%.200s' and '%.200s' types", Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name); return NULL; }
/* note: this function could be optimized by some spatial structure */ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *args) { PyObject *py_planes; float (*planes)[4]; unsigned int planes_len; if (!PyArg_ParseTuple(args, "O:points_in_planes", &py_planes)) { return NULL; } if ((planes_len = mathutils_array_parse_alloc_v((float **)&planes, 4, py_planes, "points_in_planes")) == -1) { return NULL; } else { /* note, this could be refactored into plain C easy - py bits are noted */ const float eps = 0.0001f; const unsigned int len = (unsigned int)planes_len; unsigned int i, j, k, l; float n1n2[3], n2n3[3], n3n1[3]; float potentialVertex[3]; char *planes_used = MEM_callocN(sizeof(char) * len, __func__); /* python */ PyObject *py_verts = PyList_New(0); PyObject *py_plene_index = PyList_New(0); for (i = 0; i < len; i++) { const float *N1 = planes[i]; for (j = i + 1; j < len; j++) { const float *N2 = planes[j]; cross_v3_v3v3(n1n2, N1, N2); if (len_squared_v3(n1n2) > eps) { for (k = j + 1; k < len; k++) { const float *N3 = planes[k]; cross_v3_v3v3(n2n3, N2, N3); if (len_squared_v3(n2n3) > eps) { cross_v3_v3v3(n3n1, N3, N1); if (len_squared_v3(n3n1) > eps) { const float quotient = dot_v3v3(N1, n2n3); if (fabsf(quotient) > eps) { /* potentialVertex = (n2n3 * N1[3] + n3n1 * N2[3] + n1n2 * N3[3]) * (-1.0 / quotient); */ const float quotient_ninv = -1.0f / quotient; potentialVertex[0] = ((n2n3[0] * N1[3]) + (n3n1[0] * N2[3]) + (n1n2[0] * N3[3])) * quotient_ninv; potentialVertex[1] = ((n2n3[1] * N1[3]) + (n3n1[1] * N2[3]) + (n1n2[1] * N3[3])) * quotient_ninv; potentialVertex[2] = ((n2n3[2] * N1[3]) + (n3n1[2] * N2[3]) + (n1n2[2] * N3[3])) * quotient_ninv; for (l = 0; l < len; l++) { const float *NP = planes[l]; if ((dot_v3v3(NP, potentialVertex) + NP[3]) > 0.000001f) { break; } } if (l == len) { /* ok */ /* python */ PyObject *item = Vector_CreatePyObject(potentialVertex, 3, Py_NEW, NULL); PyList_Append(py_verts, item); Py_DECREF(item); planes_used[i] = planes_used[j] = planes_used[k] = TRUE; } } } } } } } } PyMem_Free(planes); /* now make a list of used planes */ for (i = 0; i < len; i++) { if (planes_used[i]) { PyObject *item = PyLong_FromLong(i); PyList_Append(py_plene_index, item); Py_DECREF(item); } } MEM_freeN(planes_used); { PyObject *ret = PyTuple_New(2); PyTuple_SET_ITEM(ret, 0, py_verts); PyTuple_SET_ITEM(ret, 1, py_plene_index); return ret; } } }