安装Blender并使用
前言
该系列记录了如何用Blenderpro来构建自己的场景数据集,从环境搭建到后期构建数据集的整个流程
本文章是第一部分,BlenderPrc2的安装以及环境配置
部分参考https://blog.csdn.net/weixin_49521551/article/details/121573334
官方文档https://dlr-rm.github.io/BlenderProc/
一、Blenderpro是什么?
一个用于真实感渲染的程序性 Blender pipeline。
二、使用步骤
1.创建虚拟环境
为了方便日后的环境管理,我们在anaconda新建一个虚拟环境进行Blenderproc的安装,anaconda安装过程略,新环境命令如下:
conda create -n blender python=3.7 # blender处为你的虚拟环境名称
conda activate blender
2.安装Blenderproc(这一步直接按github官方教程走)
blenderproc的安装有两种方式,第一种是通过github安装,第二种是使用使用更简便的pip方式
via pip
在虚拟环境下直接执行
代码如下:
pip install Blenderproc
via github
但是不建议这样安装,还是使用作者在github上的Readme.md安装步骤更为合适
具体步骤为
git clone https://github.com/DLR-RM/BlenderProc
cd BlenderProc
pip install -e .
之后终端执行命令:
blenderproc run quickstart.py
如果环境没有问题,则会直接生成output文件夹,里面会生成输出的0.hdf5
但是一般环境都是不全的,所以下面介绍环境安装细节
三.配置环境
1.bug1
当运行代码时,发现会出现问题,如:
第一次运行blenderproc run quickstart.py
时,会自动在blender官网下载blender软件的安装包,这个过程报错:urllib.error.HTTPError:HTTP Error 403:Forbidden
意味着需要在官网下载blender并安装,但是由于网路问题没有下载成功,给出解决办法:
手动下载安装包,并安装在路径/home/usename/下即可
2.bug2
当运行代码时,发现会出现问题,如:
[BUG]: Error: ModuleNotFoundError: No module named 'skimage'
意味着当前环境代码找不到scikit-image包,当然也能是找不到其他的包,比如imageio、opencv等都有可能。那么就需要安装这个包,最直接的方法当然是
pip install scikit-image
但是这个是错误的,因为blenderproc是一个单独的环境,自己是看不到的,实在想找其实是在blener的安装路径下的python/site-package下,那么解决方法就是使用指令
blenderproc pip install scikit-image
如果没有解决,可以尝试先卸载,再安装,并加上参数
blenderproc pip uninstall scikit-image
blenderproc pip install scikit-image --not-use-custom-package-path
这会将 scikit-image安装到 blenders 站点包文件夹中,而不是我们的自定义文件夹。
现在,脚本应该可以正常运行。
参考链接:https://github.com/DLR-RM/BlenderProc/issues/855
3.bug3
当运行代码时,发现会出现问题,如:
【错误记录/Blender】python中使用bpy模块
那还不简单,直接
pip install bpy
但是不行,会出现不知名问题,解决办法是下载离线包,再手动安装
地址如下:Releases · TylerGubala/blenderpy
然后再运行指令,即可安装成功
pip install bpy-2.91a0-cp37-cp37m-manylinux2014_x86_64.whl && bpy_post_install
这样在pip list里就可以找到bpy了
参考链接:https://blog.csdn.net/qq_33446100/article/details/117591371
4.bug4
当运行代码时,发现会出现问题,如:
【错误记录/mathutils】python中使用mathutils模块
使用blenderproc的时候,需要安装mathutils,但是直接pip会出现问题
官方安装方法
这里是mathutils的库,里面写了安装方式:
mathutils 3.3.0 on PyPI - Libraries.io
git clone https://gitlab.com/ideasman42/blender-mathutils.git
cd blender-mathutils
# To build you can choose between pythons distutils or CMake.
# distutils:
python setup.py build
sudo python setup.py install
# CMake:
cmake .
make
sudo make install
# 非root模式可以去掉sudo
但是如果python版本在3.8及其以下,会在install时报错,原因在于PyModule_AddType无法解析,这里参考了其他帖子中评论的方法已解决该问题。
解决方式:
①把src/mathutils/mathutils.c中的PyModule_AddType改成PyModule_AddObject,
②把参数改成三个,中间设置一个参数接收moudle名称,要记得在前面先初始化
char *mod_name;
#### 略
/* each type has its own new() function */
PyModule_AddObject(mod, mod_name, &vector_Type);
PyModule_AddObject(mod, mod_name, &matrix_Type);
PyModule_AddObject(mod, mod_name, &euler_Type);
PyModule_AddObject(mod, mod_name, &quaternion_Type);
PyModule_AddObject(mod, mod_name, &color_Type);
③把 y = _Py_HashDouble(NULL, (double)(array[i++]))
中的NULL删掉
以上步骤执行完成后,按照官方安装方法继续执行即可。
src/mathutils/mathutils.c修改后的完整代码:
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup pymathutils
*/
#include <Python.h>
#include "mathutils.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "../generic/py_capi_utils.h"
#include "../generic/python_utildefines.h"
#ifndef MATH_STANDALONE
# include "BLI_dynstr.h"
#endif
PyDoc_STRVAR(
M_Mathutils_doc,
"This module provides access to math operations.\n"
"\n"
".. note::\n"
"\n"
" Classes, methods and attributes that accept vectors also accept other numeric sequences,\n"
" such as tuples, lists.\n"
"\n"
"The :mod:`mathutils` module provides the following classes:\n"
"\n"
"- :class:`Color`,\n"
"- :class:`Euler`,\n"
"- :class:`Matrix`,\n"
"- :class:`Quaternion`,\n"
"- :class:`Vector`,\n");
static int mathutils_array_parse_fast(float *array,
int size,
PyObject *value_fast,
const char *error_prefix)
{
PyObject *item;
PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
int i;
i = size;
do {
i--;
if (((array[i] = PyFloat_AsDouble((item = value_fast_items[i]))) == -1.0f) &&
PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError,
"%.200s: sequence index %d expected a number, "
"found '%.200s' type, ",
error_prefix,
i,
Py_TYPE(item)->tp_name);
size = -1;
break;
}
} while (i);
return size;
}
Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
{
int i;
Py_uhash_t x; /* Unsigned for defined overflow behavior. */
Py_hash_t y;
Py_uhash_t mult;
Py_ssize_t len;
mult = _PyHASH_MULTIPLIER;
len = array_len;
x = 0x345678UL;
i = 0;
while (--len >= 0) {
y = _Py_HashDouble((double)(array[i++]));
if (y == -1) {
return -1;
}
x = (x ^ y) * mult;
/* the cast might truncate len; that doesn't change hash stability */
mult += (Py_hash_t)(82520UL + len + len);
}
x += 97531UL;
if (x == (Py_uhash_t)-1) {
x = -2;
}
return x;
}
int mathutils_array_parse(
float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
{
const uint flag = array_num_max;
int num;
array_num_max &= ~MU_ARRAY_FLAGS;
#if 1 /* approx 6x speedup for mathutils types */
if ((num = VectorObject_Check(value) ? ((VectorObject *)value)->vec_num : 0) ||
(num = EulerObject_Check(value) ? 3 : 0) || (num = QuaternionObject_Check(value) ? 4 : 0) ||
(num = ColorObject_Check(value) ? 3 : 0)) {
if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
if (flag & MU_ARRAY_SPILL) {
CLAMP_MAX(num, array_num_max);
}
if (num > array_num_max || num < array_num_min) {
if (array_num_max == array_num_min) {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence length is %d, expected %d",
error_prefix,
num,
array_num_max);
}
else {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence length is %d, expected [%d - %d]",
error_prefix,
num,
array_num_min,
array_num_max);
}
return -1;
}
memcpy(array, ((const BaseMathObject *)value)->data, num * sizeof(float));
}
else
#endif
{
PyObject *value_fast = NULL;
/* non list/tuple cases */
if (!(value_fast = PySequence_Fast(value, error_prefix))) {
/* PySequence_Fast sets the error */
return -1;
}
num = PySequence_Fast_GET_SIZE(value_fast);
if (flag & MU_ARRAY_SPILL) {
CLAMP_MAX(num, array_num_max);
}
if (num > array_num_max || num < array_num_min) {
if (array_num_max == array_num_min) {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence length is %d, expected %d",
error_prefix,
num,
array_num_max);
}
else {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence length is %d, expected [%d - %d]",
error_prefix,
num,
array_num_min,
array_num_max);
}
Py_DECREF(value_fast);
return -1;
}
num = mathutils_array_parse_fast(array, num, value_fast, error_prefix);
Py_DECREF(value_fast);
}
if (num != -1) {
if (flag & MU_ARRAY_ZERO) {
const int array_num_left = array_num_max - num;
if (array_num_left) {
memset(&array[num], 0, sizeof(float) * array_num_left);
}
}
}
return num;
}
int mathutils_array_parse_alloc(float **array,
int array_num,
PyObject *value,
const char *error_prefix)
{
int num;
#if 1 /* approx 6x speedup for mathutils types */
if ((num = VectorObject_Check(value) ? ((VectorObject *)value)->vec_num : 0) ||
(num = EulerObject_Check(value) ? 3 : 0) || (num = QuaternionObject_Check(value) ? 4 : 0) ||
(num = ColorObject_Check(value) ? 3 : 0)) {
if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
if (num < array_num) {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected > %d",
error_prefix,
num,
array_num);
return -1;
}
*array = PyMem_Malloc(num * sizeof(float));
memcpy(*array, ((const BaseMathObject *)value)->data, num * sizeof(float));
return num;
}
#endif
PyObject *value_fast = NULL;
// *array = NULL;
int ret;
/* non list/tuple cases */
if (!(value_fast = PySequence_Fast(value, error_prefix))) {
/* PySequence_Fast sets the error */
return -1;
}
num = PySequence_Fast_GET_SIZE(value_fast);
if (num < array_num) {
Py_DECREF(value_fast);
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected > %d",
error_prefix,
num,
array_num);
return -1;
}
*array = PyMem_Malloc(num * sizeof(float));
ret = mathutils_array_parse_fast(*array, num, value_fast, error_prefix);
Py_DECREF(value_fast);
if (ret == -1) {
PyMem_Free(*array);
}
return ret;
}
int mathutils_array_parse_alloc_v(float **array,
int array_dim,
PyObject *value,
const char *error_prefix)
{
PyObject *value_fast;
const int array_dim_flag = array_dim;
int i, num;
/* non list/tuple cases */
if (!(value_fast = PySequence_Fast(value, error_prefix))) {
/* PySequence_Fast sets the error */
return -1;
}
num = PySequence_Fast_GET_SIZE(value_fast);
if (num != 0) {
PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
float *fp;
array_dim &= ~MU_ARRAY_FLAGS;
fp = *array = PyMem_Malloc(num * array_dim * sizeof(float));
for (i = 0; i < num; i++, fp += array_dim) {
PyObject *item = value_fast_items[i];
if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) {
PyMem_Free(*array);
*array = NULL;
num = -1;
break;
}
}
}
Py_DECREF(value_fast);
return num;
}
int mathutils_int_array_parse(int *array, int array_dim, PyObject *value, const char *error_prefix)
{
int size, i;
PyObject *value_fast, **value_fast_items, *item;
if (!(value_fast = PySequence_Fast(value, error_prefix))) {
/* PySequence_Fast sets the error */
return -1;
}
if ((size = PySequence_Fast_GET_SIZE(value_fast)) != array_dim) {
PyErr_Format(PyExc_ValueError,
"%.200s: sequence size is %d, expected %d",
error_prefix,
size,
array_dim);
Py_DECREF(value_fast);
return -1;
}
value_fast_items = PySequence_Fast_ITEMS(value_fast);
i = size;
while (i > 0) {
i--;
if (((array[i] = PyC_Long_AsI32((item = value_fast_items[i]))) == -1) && PyErr_Occurred()) {
PyErr_Format(PyExc_TypeError, "%.200s: sequence index %d expected an int", error_prefix, i);
size = -1;
break;
}
}
Py_DECREF(value_fast);
return size;
}
int mathutils_array_parse_alloc_vi(int **array,
int array_dim,
PyObject *value,
const char *error_prefix)
{
PyObject *value_fast;
int i, size;
if (!(value_fast = PySequence_Fast(value, error_prefix))) {
/* PySequence_Fast sets the error */
return -1;
}
size = PySequence_Fast_GET_SIZE(value_fast);
if (size != 0) {
PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
int *ip;
ip = *array = PyMem_Malloc(size * array_dim * sizeof(int));
for (i = 0; i < size; i++, ip += array_dim) {
PyObject *item = value_fast_items[i];
if (mathutils_int_array_parse(ip, array_dim, item, error_prefix) == -1) {
PyMem_Free(*array);
*array = NULL;
size = -1;
break;
}
}
}
Py_DECREF(value_fast);
return size;
}
int mathutils_array_parse_alloc_viseq(
int **array, int **start_table, int **len_table, PyObject *value, const char *error_prefix)
{
PyObject *value_fast, *subseq;
int i, size, start, subseq_len;
int *ip;
*array = NULL;
*start_table = NULL;
*len_table = NULL;
if (!(value_fast = PySequence_Fast(value, error_prefix))) {
/* PySequence_Fast sets the error */
return -1;
}
size = PySequence_Fast_GET_SIZE(value_fast);
if (size != 0) {
PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast);
*start_table = PyMem_Malloc(size * sizeof(int));
*len_table = PyMem_Malloc(size * sizeof(int));
/* First pass to set starts and len, and calculate size of array needed */
start = 0;
for (i = 0; i < size; i++) {
subseq = value_fast_items[i];
if ((subseq_len = (int)PySequence_Size(subseq)) == -1) {
PyErr_Format(
PyExc_ValueError, "%.200s: sequence expected to have subsequences", error_prefix);
PyMem_Free(*start_table);
PyMem_Free(*len_table);
Py_DECREF(value_fast);
*start_table = NULL;
*len_table = NULL;
return -1;
}
(*start_table)[i] = start;
(*len_table)[i] = subseq_len;
start += subseq_len;
}
ip = *array = PyMem_Malloc(start * sizeof(int));
/* Second pass to parse the subsequences into array */
for (i = 0; i < size; i++) {
subseq = value_fast_items[i];
subseq_len = (*len_table)[i];
if (mathutils_int_array_parse(ip, subseq_len, subseq, error_prefix) == -1) {
PyMem_Free(*array);
PyMem_Free(*start_table);
PyMem_Free(*len_table);
*array = NULL;
*len_table = NULL;
*start_table = NULL;
size = -1;
break;
}
ip += subseq_len;
}
}
Py_DECREF(value_fast);
return size;
}
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
{
if (EulerObject_Check(value)) {
if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
eulO_to_mat3(rmat, ((const EulerObject *)value)->eul, ((const EulerObject *)value)->order);
return 0;
}
if (QuaternionObject_Check(value)) {
if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
float tquat[4];
normalize_qt_qt(tquat, ((const QuaternionObject *)value)->quat);
quat_to_mat3(rmat, tquat);
return 0;
}
if (MatrixObject_Check(value)) {
if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
return -1;
}
if (((MatrixObject *)value)->row_num < 3 || ((MatrixObject *)value)->col_num < 3) {
PyErr_Format(
PyExc_ValueError, "%.200s: matrix must have minimum 3x3 dimensions", error_prefix);
return -1;
}
matrix_as_3x3(rmat, (MatrixObject *)value);
normalize_m3(rmat);
return 0;
}
PyErr_Format(PyExc_TypeError,
"%.200s: expected a Euler, Quaternion or Matrix type, "
"found %.200s",
error_prefix,
Py_TYPE(value)->tp_name);
return -1;
}
/* ----------------------------------MATRIX FUNCTIONS-------------------- */
/* Utility functions */
/* LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon */
/* XXX We may want to use 'safer' BLI's compare_ff_relative ultimately?
* LomontRRDCompare4() is an optimized version of Dawson's AlmostEqual2sComplement()
* (see [1] and [2]).
* Dawson himself now claims this is not a 'safe' thing to do
* (pushing ULP method beyond its limits),
* an recommends using work from [3] instead, which is done in BLI func...
*
* [1] http://www.randydillon.org/Papers/2007/everfast.htm
* [2] http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
* [3] https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
* instead.
*/
#define SIGNMASK(i) (-(int)(((uint)(i)) >> 31))
int EXPP_FloatsAreEqual(float af, float bf, int maxDiff)
{
/* solid, fast routine across all platforms
* with constant time behavior */
const int ai = *(const int *)(&af);
const int bi = *(const int *)(&bf);
const int test = SIGNMASK(ai ^ bi);
int diff, v1, v2;
BLI_assert((0 == test) || (0xFFFFFFFF == test));
diff = (ai ^ (test & 0x7fffffff)) - bi;
v1 = maxDiff + diff;
v2 = maxDiff - diff;
return (v1 | v2) >= 0;
}
/*---------------------- EXPP_VectorsAreEqual -------------------------
* Builds on EXPP_FloatsAreEqual to test vectors */
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
{
int x;
for (x = 0; x < size; x++) {
if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0) {
return 0;
}
}
return 1;
}
#ifndef MATH_STANDALONE
PyObject *mathutils_dynstr_to_py(struct DynStr *ds)
{
const int ds_len = BLI_dynstr_get_len(ds); /* space for \0 */
char *ds_buf = PyMem_Malloc(ds_len + 1);
PyObject *ret;
BLI_dynstr_get_cstring_ex(ds, ds_buf);
BLI_dynstr_free(ds);
ret = PyUnicode_FromStringAndSize(ds_buf, ds_len);
PyMem_Free(ds_buf);
return ret;
}
#endif
/* Mathutils Callbacks */
/* For mathutils internal use only,
* eventually should re-alloc but to start with we only have a few users. */
#define MATHUTILS_TOT_CB 17
static Mathutils_Callback *mathutils_callbacks[MATHUTILS_TOT_CB] = {NULL};
uchar Mathutils_RegisterCallback(Mathutils_Callback *cb)
{
uchar i;
/* find the first free slot */
for (i = 0; mathutils_callbacks[i]; i++) {
if (mathutils_callbacks[i] == cb) {
/* already registered? */
return i;
}
}
BLI_assert(i + 1 < MATHUTILS_TOT_CB);
mathutils_callbacks[i] = cb;
return i;
}
int _BaseMathObject_CheckCallback(BaseMathObject *self)
{
Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
if (LIKELY(cb->check(self) != -1)) {
return 0;
}
return -1;
}
/* use macros to check for NULL */
int _BaseMathObject_ReadCallback(BaseMathObject *self)
{
Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
if (LIKELY(cb->get(self, self->cb_subtype) != -1)) {
return 0;
}
if (!PyErr_Occurred()) {
PyErr_Format(PyExc_RuntimeError, "%s read, user has become invalid", Py_TYPE(self)->tp_name);
}
return -1;
}
int _BaseMathObject_WriteCallback(BaseMathObject *self)
{
Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
if (LIKELY(cb->set(self, self->cb_subtype) != -1)) {
return 0;
}
if (!PyErr_Occurred()) {
PyErr_Format(PyExc_RuntimeError, "%s write, user has become invalid", Py_TYPE(self)->tp_name);
}
return -1;
}
int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index)
{
Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
if (LIKELY(cb->get_index(self, self->cb_subtype, index) != -1)) {
return 0;
}
if (!PyErr_Occurred()) {
PyErr_Format(
PyExc_RuntimeError, "%s read index, user has become invalid", Py_TYPE(self)->tp_name);
}
return -1;
}
int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
{
Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
if (LIKELY(cb->set_index(self, self->cb_subtype, index) != -1)) {
return 0;
}
if (!PyErr_Occurred()) {
PyErr_Format(
PyExc_RuntimeError, "%s write index, user has become invalid", Py_TYPE(self)->tp_name);
}
return -1;
}
void _BaseMathObject_RaiseFrozenExc(const BaseMathObject *self)
{
PyErr_Format(PyExc_TypeError, "%s is frozen (immutable)", Py_TYPE(self)->tp_name);
}
void _BaseMathObject_RaiseNotFrozenExc(const BaseMathObject *self)
{
PyErr_Format(
PyExc_TypeError, "%s is not frozen (mutable), call freeze first", Py_TYPE(self)->tp_name);
}
/* BaseMathObject generic functions for all mathutils types */
char BaseMathObject_owner_doc[] = "The item this is wrapping or None (read-only).";
PyObject *BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure))
{
PyObject *ret = self->cb_user ? self->cb_user : Py_None;
return Py_INCREF_RET(ret);
}
char BaseMathObject_is_wrapped_doc[] =
"True when this object wraps external data (read-only).\n\n:type: boolean";
PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closure))
{
return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_WRAP) != 0);
}
char BaseMathObject_is_frozen_doc[] =
"True when this object has been frozen (read-only).\n\n:type: boolean";
PyObject *BaseMathObject_is_frozen_get(BaseMathObject *self, void *UNUSED(closure))
{
return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_FROZEN) != 0);
}
char BaseMathObject_is_valid_doc[] =
"True when the owner of this data is valid.\n\n:type: boolean";
PyObject *BaseMathObject_is_valid_get(BaseMathObject *self, void *UNUSED(closure))
{
return PyBool_FromLong(BaseMath_CheckCallback(self) == 0);
}
char BaseMathObject_freeze_doc[] =
".. function:: freeze()\n"
"\n"
" Make this object immutable.\n"
"\n"
" After this the object can be hashed, used in dictionaries & sets.\n"
"\n"
" :return: An instance of this object.\n";
PyObject *BaseMathObject_freeze(BaseMathObject *self)
{
if ((self->flag & BASE_MATH_FLAG_IS_WRAP) || (self->cb_user != NULL)) {
PyErr_SetString(PyExc_TypeError, "Cannot freeze wrapped/owned data");
return NULL;
}
self->flag |= BASE_MATH_FLAG_IS_FROZEN;
return Py_INCREF_RET((PyObject *)self);
}
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
{
Py_VISIT(self->cb_user);
return 0;
}
int BaseMathObject_clear(BaseMathObject *self)
{
Py_CLEAR(self->cb_user);
return 0;
}
void BaseMathObject_dealloc(BaseMathObject *self)
{
/* only free non wrapped */
if ((self->flag & BASE_MATH_FLAG_IS_WRAP) == 0) {
PyMem_Free(self->data);
}
if (self->cb_user) {
PyObject_GC_UnTrack(self);
BaseMathObject_clear(self);
}
Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); /* breaks sub-types. */
}
/*----------------------------MODULE INIT-------------------------*/
static struct PyMethodDef M_Mathutils_methods[] = {
{NULL, NULL, 0, NULL},
};
static struct PyModuleDef M_Mathutils_module_def = {
PyModuleDef_HEAD_INIT,
"mathutils", /* m_name */
M_Mathutils_doc, /* m_doc */
0, /* m_size */
M_Mathutils_methods, /* m_methods */
NULL, /* m_slots */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
/* submodules only */
#include "mathutils_geometry.h"
#include "mathutils_interpolate.h"
#ifndef MATH_STANDALONE
# include "mathutils_bvhtree.h"
# include "mathutils_kdtree.h"
# include "mathutils_noise.h"
#endif
PyMODINIT_FUNC PyInit_mathutils(void)
{
PyObject *mod;
PyObject *submodule;
PyObject *sys_modules = PyImport_GetModuleDict();
char *mod_name;
if (PyType_Ready(&vector_Type) < 0) {
return NULL;
}
if (PyType_Ready(&matrix_Type) < 0) {
return NULL;
}
if (PyType_Ready(&matrix_access_Type) < 0) {
return NULL;
}
if (PyType_Ready(&euler_Type) < 0) {
return NULL;
}
if (PyType_Ready(&quaternion_Type) < 0) {
return NULL;
}
if (PyType_Ready(&color_Type) < 0) {
return NULL;
}
mod = PyModule_Create(&M_Mathutils_module_def);
/* each type has its own new() function */
PyModule_AddObject(mod, mod_name, &vector_Type);
PyModule_AddObject(mod, mod_name, &matrix_Type);
PyModule_AddObject(mod, mod_name, &euler_Type);
PyModule_AddObject(mod, mod_name, &quaternion_Type);
PyModule_AddObject(mod, mod_name, &color_Type);
/* submodule */
PyModule_AddObject(mod, "geometry", (submodule = PyInit_mathutils_geometry()));
/* XXX, python doesn't do imports with this usefully yet
* 'from mathutils.geometry import PolyFill'
* ...fails without this. */
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
PyModule_AddObject(mod, "interpolate", (submodule = PyInit_mathutils_interpolate()));
/* XXX, python doesn't do imports with this usefully yet
* 'from mathutils.geometry import PolyFill'
* ...fails without this. */
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
#ifndef MATH_STANDALONE
/* Noise submodule */
PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
/* BVHTree submodule */
PyModule_AddObject(mod, "bvhtree", (submodule = PyInit_mathutils_bvhtree()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
/* KDTree_3d submodule */
PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree()));
PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
#endif
mathutils_matrix_row_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_row_cb);
mathutils_matrix_col_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_col_cb);
mathutils_matrix_translation_cb_index = Mathutils_RegisterCallback(
&mathutils_matrix_translation_cb);
return mod;
}
到这里,mathutils也安装完成
参考链接:https://blog.csdn.net/Q_pril/article/details/137771478
5.bug5
当运行代码时,发现会出现问题,如:
No module named 'bop_toolkit_lib'
意味着找不到模块bop_toolkit_lib,需要安装,首先想到的是使用指令
blenderproc pip install bop_toolkit_lib
但是在pip里是没有这个包的,因此不会安装成功,所以这里直接先在github上下载,即运行指令
git clone https://github.com/thodan/bop_toolkit
cd bop_toolkit
pip install -r requirements.txt -e .
安装完之后,还是不会找到模块,因此,解决办法是
blenderproc pip install "git+https://github.com/thodan/bop_toolkit"
参考链接:https://github.com/DLR-RM/BlenderProc/issues/559
四.运行
终端执行命令
blenderproc run quickstart.py
运行之后在目录下会有0.dhf5的文件生成,此时运行
blenderproc vis hdf5 output/0.hdf5
即可将结果进行可视化,结果如图:
到这一步,blenderproc的环境安装配置也就完成了,更多的基础示例可以下载github项目工程并参照示例进行。