Мне казалось ты разобрался http://blender-3d.ru/forum/index.php/topic,1239.0.htmlДа, то было без плюсов. Проконсультируешь?
А! То был С без ++?
... можешь хранить в массиве как тип "объект" извлекать как "объект", но сделать у класса "объект" наследуемую функцию get_type , которая возвращает у каждого потомка свой код ("меш", "кривая") ...В этом коде всё правильно?
... и далее делать приведение типа к нужному классу в зависимости от значения этой функции ...
// .h
class BlenderScene{
public:
std::map<std::string,BlenderObject*> objects;
BlenderScene();
~BlenderScene();
void addObject(std::string name,BlenderMesh* mesh);
};
class BlenderObject{
public:
int Type;
BlenderObject();
~BlenderObject();
};
class BlenderMesh : public BlenderObject{
public:
std::string name;
BlenderMesh();
~BlenderMesh();
};
// .cpp
BlenderScene::BlenderScene(){}
BlenderScene::~BlenderScene(){}
BlenderScene::BlenderObject(){}
BlenderScene::~BlenderObject(){}
BlenderScene::BlenderMesh(){}
BlenderScene::~BlenderMesh(){}
void BlenderScene::addObject(std::string name,BlenderMesh* mesh){
objects.insert ( pair<std::string,BlenderMesh*>(name,mesh) );
}
... этот код не демонстрирует твоей проблемы и не решает её ...Ну, я начал по-порядку. И, у тебя уже есть вопросы. И у меня. Это мне как раз, и не очень-то понятно.
... почему добавляя объект ты ссылаешься на меш? ...
BlenderObject *mesh = new BlenderMesh();
Класс "объект", его потомки: "меш", "кривая". Меши и кривые нужно вогнать в один массив, что ни так страшно, как потом их оттуда извлечь.Вот из-за подобной хрени меня бесят языки со статической типизацией... В питоне такой проблемы нет, и можно даже иерархии классов не строить.
Например, такПытался:КодBlenderObject *mesh = new BlenderMesh();
Пытался:Ну так и объяви name в объекте, а не в меше.
error: 'class povanim::BlenderObject' has no member named 'name'
>> и пишу его в map, как объектЗначит, я правильно тебе предоставил данные, и правильно это использовал в своей проге (а, вот addObject(name, (BlenderObject*) mesh) не катит):
... только добавлять нужно void addObject(std::string name,BlenderObject* ob) ...
BlenderMesh *mesh = new BlenderMesh();
mesh -> name = obname;
scene->addObject(name,mesh)
... если вызов addObject(name,mesh) не прокатит, пробуй addObject(name, (BlenderObject*) mesh) ...
... при этом name у тебя есть в объекте и name будет в списке? ...
... после того как получишь из списка BlenderObject* можешь сделать mesh=(BlenderMesh*) object ...
... сделай еще в BlenderObject наследуюмую функцию get_type которая возвращает код типа объекта ...
-- The C compiler identification is GNU 4.9.2
-- The CXX compiler identification is GNU 4.9.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.28")
-- Checking for one of the modules 'python3'
-- Checking for one of the modules 'fox'
-- Configuring done
-- Generating done
-- Build files have been written to: /home/leonid/workspace/programming/povanim_devel/build
Scanning dependencies of target povanim
[ 14%] Building CXX object CMakeFiles/povanim.dir/src/BlenderMesh.cpp.o
[ 28%] Building CXX object CMakeFiles/povanim.dir/src/RenderGUI.cpp.o
[ 42%] Building CXX object CMakeFiles/povanim.dir/src/main.cpp.o
[ 57%] Building CXX object CMakeFiles/povanim.dir/src/BlenderScene.cpp.o
[ 71%] Building CXX object CMakeFiles/povanim.dir/src/BlenderObject.cpp.o
[ 85%] Building CXX object CMakeFiles/povanim.dir/src/Vector.cpp.o
[100%] Linking CXX executable povanim
[100%] Built target povanim
bool BlenderScene::addBlenderObject(std::string name){
BlenderObject *bobject = objects.find(name) -> second;
if (!bobject)
return false;
switch (bobject -> type) {
case 2: {
//Mesh *mesh = new Mesh();
// reinterpret Blender mesh data to Povray mesh data
// bla-bla-bla
}
case 1: { std::cout<<"Type: "<<"CSG"<<std::endl; break; } //del
default: { std::cout<<"Type: "<<"BLOB"<<std::endl; } //del
}
return true;
}
Не конпеляется. Пиши еще :P . А если серьезно, то даже в твоем простом коде я уже ноги сломал. Объясни словами, что от чего хочешь наследовать или что там? Может и я пойму что.Уже написал. Качай, конпеляй:
Да, я всё понимаю. Сам хотел все проблемы решить питоном. Но... нам может не нравиться форма ракеты...без гравицапы можно только по горизонтали, а с гравицапой в любую точку вселенной за 5 секунд...ЦитироватьКласс "объект", его потомки: "меш", "кривая". Меши и кривые нужно вогнать в один массив, что ни так страшно, как потом их оттуда извлечь.Вот из-за подобной хрени меня бесят языки со статической типизацией... В питоне такой проблемы нет, и можно даже иерархии классов не строить.
Почему ты выбрал Fox, а не Qt например?говорит, что этот GUI быстрее... но мне до сих пор непонятно, почему он начинает свои проги с обёртки, а не с начинки...
Допустим, у меня есть данные для меша, в данном случае имя. Что мне делать? Я делаю так:
BlenderMesh *mesh = new BlenderMesh();
mesh -> name = obname;
Так как меш наследник объекта, я и пишу его в map, как объект... понимаю, что, скорее всего, это неверно, и это первый повод материться.
Как мне превратить меш в объект?
Например, такбыл формально правильным, но без разъяснений на 200 страницах абсолютно бесполезным, а времени долго отвечать особо не было, да и мозги хреново работали.
Код: [Выделить]
BlenderObject *mesh = new BlenderMesh();
mesh -> name = obname;
class BlenderObject{
...
virtual SuperFunction();
...
};
class BlenderMesh{
...
virtual SuperFunction();
...
};
mesh -> SuperFunction();
this.name = obname;
Ну так и объяви name в объекте, а не в меше.
Почему ты выбрал Fox, а не Qt например?Потому что в ЭТО моё творение в конце концов будет включён полный код Поврея, пропатченный несколькими моими заплатками. Я действую с ведома разработчика Поврея и в согласии с лицензией Поврея. Я не силён в юридических аспектах программистской деятельности, но, по-моему, с Qt будут разногласия. Может, и с Лисом будут разногласия, но, я не достучался до них. Хотя, при успешной операции, возможно, Лиса заменит GTKMM-3.
говорит, что этот GUI быстрее... но мне до сих пор непонятно, почему он начинает свои проги с обёртки, а не с начинки...Тебе тоже советую начинать с обёртки, когда твоя программа будет зависеть от разного рода команд типа: "Открыть файл", "Подгрузить сцену ", "Запустить рендер" и так далее... :)
...Ничего мне не понятно. Ладно, name, но у меша есть массив полигонов, его как мне передать объекту? Вроде как передаю компилируется, меш становится объектом, а вытащить из него ничего не получается. Что ни запросишь, ничего нет из того, что должно быть. Такое ощущение, что меш превращается в пустой объект.
Я попробую без наследников.Тогда в массиве можно будет содержать только объекты типа BlenderObject. Разнородные объекты в один класс можно загнать, но это будет неудобно. Впрочем, в построении иерархий классов тоже мало удобства...
Ладно, name, но у меша есть массив полигонов, его как мне передать объекту?А откуда тебе его надо передавать? Обычно это делают как-то так:
class BlenderMesh{
private:
float* array;
int nsize
...
public:
...
void SetArray(float* array, int nsize);
...
};
void BlenderMesh::SetArray(float* array, int nsize){
this.nsize=nsize;
this.array=array;
};
Тогда в массиве можно будет содержать только объекты типа BlenderObject. Разнородные объекты в один класс можно загнать, но это будет неудобно. Впрочем, в построении иерархий классов тоже мало удобства...Я представляю как-то так:
class object{
public:
int Type;
string Name;
Data<T> Data;
Object();
~Object();
void setData(Data<T> Data);
};
#ifndef __OBJECT_H
#define __OBJECT_H
#include <vector>
#include "IntersectData.h"
#include "Vector.h"
#include "Material.h"
#include "Ray.h"
enum IntersectType {
HIT, MISS
};
class Object {
public:
Point3 position;
Material * material;
// ObjectTransformer transformer;
// object hierarchy can have multiple children but just one parent
// each child has coordinates relative to the parent's object space axes.
std::vector<Object*> children;
Object * parent;
Object();
virtual ~Object();
virtual Vector3 getNormalAt(const Point3 &p) const = 0;
virtual IntersectType intersect(const Ray &ray, IntersectData *data) const = 0;
virtual void computeBoundingBox() = 0;
virtual void rotate(const Vector3 &axis, float radians);
};
#endif
#ifndef __MESH_H
#define __MESH_H
#include "IntersectData.h"
#include "Triangle.h"
#include "Ray.h"
#include "Vector.h"
#include <vector>
class Mesh : public Object {
public:
std::vector<Vector3*> vertices;
std::vector<Vector3*> normals;
Mesh();
Mesh(const Point3 &pos);
~Mesh();
Point3 bboxMin;
Point3 bboxMax;
void addVertex(float x, float y, float z);
void addNormal(float x, float y, float z);
virtual IntersectType intersect(const Ray &ray, IntersectData *data) const;
virtual Vector3 getNormalAt(const Point3 &p) const;
virtual void computeBoundingBox();
virtual void rotate(const Vector3 &axis, float radians);
};
#endif
void Scene::teapot() {
Color white = Color(1,1,1);
Color purple = Color(0.75, 0, 0.75);
Plane *plane = new Plane(Point3(0, -2, 0), Vector3(0, 1, 0));
plane->material->color = purple;
Mesh *mesh = new Mesh(Point3(0,0,0));
mesh->material->color = white;
Util::loadObj("meshes/teapot.obj", mesh);
calculateBbox(mesh);
//mesh->rotate(Vector3(1,0,0), 3.141592/4.0f);
//rotateX(*mesh, 3.141592/4.0f);
objects.push_back(dynamic_cast<Object*>(mesh));
objects.push_back(dynamic_cast<Object*>(plane));
m = mesh;
}
Приведение типов в C плюс плюс
Лучшая практика по приведению типов: не делать этого.
Потому что, если в программе потребовалось приведение типов,
значит в этой программе с большой долей вероятности что-то неладно.
Для довольно редких ситуаций, когда это все-таки действительно нужно,
есть четыре способа приведения типов.
Третий:
dynamic_cast
Безопасное приведение по иерархии наследования, в том числе и для виртуального наследования.
dynamic_cast<derv_class *>(base_class_ptr_expr)
Используется RTTI (Runtime Type Information), чтобы привести один указатель на объект класса к другому указателю на объект класса.
Классы должны быть полиморфными, то есть в базовом классе должна быть хотя бы одна виртуальная функция.
Если эти условие не соблюдено, ошибка возникнет на этапе компиляции.
Если приведение невозможно, то об этом станет ясно только на этапе выполнения программы и будет возвращен NULL.
dynamic_cast<derv_class &>(base_class_ref_expr)
Работа со ссылками происходит почти как с указателями, но в случае ошибки во время исполнения будет выброшено исключение bad_cast.
Тогда в массиве можно будет содержать только объекты типа BlenderObject. Разнородные объекты в один класс можно загнать, но это будет неудобно. Впрочем, в построении иерархий классов тоже мало удобства...Я представляю как-то так:Кодclass object{
public:
int Type;
string Name;
Data<T> Data;
Object();
~Object();
void setData(Data<T> Data);
};
Ну, во-первых, я хотел было попытаться уйти от виртуальных функций в рамках С++, пытаясь найти равноценное решение, но раз ты утверждаешь, что с шаблоном я заблуждаюсь, то буду курить dinamic_cast. Просто я читал, что шаблоны применяются там, где заранее неизвестно, какого типа будет содержимое, и подумал неверно. Спасибо, что растолковал! :)Тогда в массиве можно будет содержать только объекты типа BlenderObject. Разнородные объекты в один класс можно загнать, но это будет неудобно. Впрочем, в построении иерархий классов тоже мало удобства...Я представляю как-то так:Кодclass object{
public:
int Type;
string Name;
Data<T> Data;
Object();
~Object();
void setData(Data<T> Data);
};
А что такое у тебя будет <T> ? Классы с разными типами вместо <T> будут существенно разными типами, и в один массив их нельзя будет пихать. Так что если хочешь попытаться не использовать наследование и виртуальные функции (и нафига тогда С++, можно просто С), то тебе в данные-члены нужно загнать ВСЁ, что могло бы понадобиться в потомках этого Object, а потом использовать или игнорировать часть из них.
Вот, кажется нашёл в одном из накачанных примеров рейтрейсеров про наследников и то, как это делаетсяЯ тебе примерно это и толковал...
...Кодobjects.push_back(dynamic_cast<Object*>(mesh));
objects.push_back(dynamic_cast<Object*>(plane));
Кажись, нашёл. Всё очень просто в рамках рейтрейсера. Это ж виртуальные функции, содержимое которых разное, и написано оно для каждого типа отдельно. Ему, просто, не нужно знать: меш это или плоскость.ЦитироватьВот, кажется нашёл в одном из накачанных примеров рейтрейсеров про наследников и то, как это делаетсяЯ тебе примерно это и толковал...
...Кодobjects.push_back(dynamic_cast<Object*>(mesh));
objects.push_back(dynamic_cast<Object*>(plane));
Но тут мои собственные знания и заканчиваются, к сожалению. Мне непонятно, как этот рейтрейсер, работая с массивом objects понимает, где тут Mesh, где Plane, и т.д., и, самое главное, как к ним применять функции, специфичные для этих разных классов? Я представляю себе такую возможность только через собственные виртуальные функции (здесь это intersect, computeBoundingBox, getNormalAt и rotate), а вот где-то извне... Ну разве что бесконечно длинные простыни со switch-case (терпеть их не могу).
Поищи там пример такого разбора.
for (int i = 0, i < objects.size(); i ){
Object* RtObject = objects[i];
RtObject -> computeBoundingBox();}
#include "Mesh.h"
#include <iostream>
Mesh::Mesh() {
position = Point3(0,0,0);
}
Mesh::Mesh(const Point3 &pos) {
position = pos;
}
Mesh::~Mesh() {
// TODO: stub
}
void Mesh::addVertex(float x, float y, float z) {
vertices.push_back(new Vector3(x, y, z));
}
void Mesh::addNormal(float x, float y, float z) {
normals.push_back(new Vector3(x, y, z));
}
void swap(float &a, float &b) {
float temp = a;
a = b;
b = temp;
}
IntersectType intersectBbox(const Ray &r, const Mesh *m) {
float tmin = (m->bboxMin.x - r.position.x) / r.direction.x;
float tmax = (m->bboxMax.x - r.position.x) / r.direction.x;
float tymin = (m->bboxMin.y - r.position.y) / r.direction.y;
float tymax = (m->bboxMax.y - r.position.y) / r.direction.y;
float tzmin = (m->bboxMin.z - r.position.z) / r.direction.z;
float tzmax = (m->bboxMax.z - r.position.z) / r.direction.z;
if(tmin > tmax) swap(tmin, tmax);
if(tymin > tymax) swap(tymin, tymax);
if((tmin > tymax) || (tymin > tmax))
return MISS;
if(tymin > tmin)
tmin = tymin;
if(tymax < tmax)
tmax = tymax;
if(tzmin > tzmax) swap(tzmin, tzmax);
if((tmin > tzmax) || (tzmin > tmax))
return MISS;
if(tzmin > tmin) {
tmin = tzmin;
}
if(tzmax < tmax) {
tmax = tzmax;
}
return HIT;
}
IntersectType Mesh::intersect(const Ray &ray, IntersectData *data) const {
if(intersectBbox(ray, this) == MISS) {
return MISS;
}
int closestTriangleIndex = 0;
float closestDistance = data->t;
bool retval = false;
for(int i = 0; i < normals.size(); i) {
//Vector3 normal = *normals[i];
Triangle triangle(*vertices[i*3], *vertices[i*3 1], *vertices[i*3 2]);
triangle.intersect(ray, &(*data));
if(data->t < closestDistance) {
closestTriangleIndex = i;
closestDistance = data->t;
retval = true;
}
}
if(retval) {
Triangle triangle(*vertices[closestTriangleIndex*3], *vertices[closestTriangleIndex*3 1], *vertices[closestTriangleIndex*3 2]);
return triangle.intersect(ray, &(*data));
} else {
return MISS;
}
return MISS;
}
Vector3 Mesh::getNormalAt(const Point3 &p) const {
// TODO: fixme
return Vector3(0,0,0);
}
void Mesh::computeBoundingBox() {
// TODO
}
void Mesh::rotate(const Vector3 &n, const float theta) {
float a = n.x*n.x*(1 - cos(theta)) cos(theta);
float b = n.x*n.y*(1 - cos(theta)) n.z*sin(theta);
float c = n.x*n.z*(1 - cos(theta)) - n.y*sin(theta);
float d = n.x*n.y*(1 - cos(theta)) - n.z*sin(theta);
float e = n.y*n.y*(1 - cos(theta)) cos(theta);
float f = n.y*n.z*(1 - cos(theta)) n.x*sin(theta);
float g = n.x*n.z*(1 - cos(theta)) n.y*sin(theta);
float h = n.y*n.z*(1 - cos(theta)) - n.x*sin(theta);
float i = n.z*n.z*(1 - cos(theta)) cos(theta);
Matrix33 R(a,b,c,d,e,f,g,h,i);
for(int i = 0; i < vertices.size(); i ) {
Vector3 &v = *vertices[i];
*vertices[i] = v*R;
}
for(int i = 0; i < normals.size(); i ) {
Vector3 &v = *normals[i];
*normals[i] = v*R;
}
}
>> функции getData() для BlenderObject и для BlenderMesh.Ну, так я ж и использовал приведение типов для getType().
... для быстрого доступа к свойствам и методам, наверное будет уместным использовать приведение типов ...
... то есть, нужно разобраться как от BlenderMesh* перейти к BlenderObject* ...
https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%82%D0%B8%D0%BF%D0%B0
void BlenderScene::addMesh(std::string name,BlenderMesh* mesh){
BlenderObject *obj = dynamic_cast<BlenderObject*>(mesh);
objects.insert ( pair<std::string,BlenderObject*>(name,obj) );
}
int BlenderScene::addObjectToPovray(std::string name){
BlenderObject *bobject = objects.find(name) -> second;
if (!bobject)
return 0;
int obj_type = bobject -> getType();
switch (obj_type) {
case 2: {
Mesh *mesh = new Mesh(); // create Povray Mesh
mesh -> vertex_vectors = bobject -> vertex_vectors;
break;
}
case 1: {}
default: {}
}
return 1;
}
void BlenderScene::addObjectToPovray(std::string name){
BlenderObject *bobject = objects.find(name) -> second;
bobject -> createPovrayObject();
}
Писдец... я вобще не понимаюТы тупой. :) В C++ не нужно управлять памятью вручную, это тебе не С. Памятью управляют вручную, когда создают указатели.
Ты тупой. :)Нет, Ланухумыч... это ты тупой, потому, что не врубаешься в суть :)
Суть проста: мне нужна программа, и, я её напишу независимо от твоего мнения ;DЦитироватьТы тупой. :)Нет, Ланухумыч... это ты тупой, потому, что не врубаешься в суть :)
да я буду рад этому :) но ещё раз тебе напишу: пока ты не врубишься в машинный код и ассемблер во взаимосвязи с СИ++, твои проги будут работать, но иногда тупить и тормозить...Суть проста: мне нужна программа, и, я её напишу независимо от твоего мнения ;DЦитироватьТы тупой. :)Нет, Ланухумыч... это ты тупой, потому, что не врубаешься в суть :)
Программа будет работать корректно. :)
да я буду рад этому :) но ещё раз тебе напишу: пока ты не врубишься в машинный код и ассемблер во взаимосвязи с СИ++, твои проги будут работать, но иногда тупить и тормозить...Точно тупой ты. :) А, ты не скажешь, сколько мне будет лет, когда я с успехом закончу освоение машинного кода и ассемблера?
Точно тупой ты. :) А, ты не скажешь, сколько мне будет лет, когда я с успехом закончу освоение машинного кода и ассемблера?LanuHum, ты извини, но ты дурень великовозрастный... этому в конце 80-х и начале 90-х школьников в средней школе учили... ты книжки открой, врубись что такое бит, байт, слово, двойное слово... мантисса и порядок...
ЦитироватьТочно тупой ты. :) А, ты не скажешь, сколько мне будет лет, когда я с успехом закончу освоение машинного кода и ассемблера?LanuHum, ты извини, но ты дурень великовозрастный... этому в конце 80-х и начале 90-х школьников в средней школе учили... ты книжки открой, врубись что такое бит, байт, слово, двойное слово... мантисса и порядок...
Продолжай. Я просто хочу понять: ты хочешь мне мозг вынести, или, действительно, знаешь, о чём звиздишь, или, тупо, пытаешься стебаться...Если честно, то и то, и другое:) если действительно хочешь разобраться, то у парней , которые тебе советы пишут спроси, они в курсе :) ...
Действительно, я хочу, чтоб мне помогали, когда я спрашиваю...ну, или хотя бы молчали, если нет желания помочь. :)ЦитироватьПродолжай. Я просто хочу понять: ты хочешь мне мозг вынести, или, действительно, знаешь, о чём звиздишь, или, тупо, пытаешься стебаться...Если честно, то и то, и другое:) если действительно хочешь разобраться, то у парней , которые тебе советы пишут спроси, они в курсе :) ...
ладно... давай так...Указатель является числом (по-моему, шестнадцатеричной системы исчисления), указывающим на ячейку памяти, которую я занял, создав переменную.
Чем является "указатель" в языке Си?
почти попал :) указатель является адресом НАЧАЛЬНОЙ ячейки памяти в которой что-то хранится... но блин, непонятно чито тамо хранится, т.к. одна ячейка памяти - это один байт, но дальше идут другие байты... потому указывается тип ( размерность переменной... или сколько следующих байт используется)... ясно? ...там может хранится и адрес функции (подпрограммы) в памяти... да и пофиг что :) ...Архитектура фон Неймана —принцип совместного хранения команд и данных в памяти компьютера. Знаешь что прикольно, что ты этот мусор из данных (переменных) тоже можешь запустить, оперируя в машинном коде... можешь сделать самомодифицируемый код (прогу, которая сама себя "пишет" и исполняет)... врубайся :) надеюсь, всё-таки я до тебя достучался....ладно... давай так...Указатель является числом (по-моему, шестнадцатеричной системы исчисления), указывающим на ячейку памяти, которую я занял, создав переменную.
Чем является "указатель" в языке Си?
Мне ясно, что char - 1, short - 2, int - 4, double - 8. Если создаём массив, указываем число объектов и тип. Умножаем, получаем.почти попал :) указатель является адресом НАЧАЛЬНОЙ ячейки памяти в которой что-то хранится... но блин, непонятно чито тамо хранится, т.к. одна ячейка памяти - это один байт, но дальше идут другие байты... потому указывается тип ( размерность переменной... или сколько следующих байт используется)... ясно? ...там может хранится и адрес функции (подпрограммы)в памяти... да и пофиг что :)ладно... давай так...Указатель является числом (по-моему, шестнадцатеричной системы исчисления), указывающим на ячейку памяти, которую я занял, создав переменную.
Чем является "указатель" в языке Си?
ну и что ты думаешь делает компилятор Си, когда ты написал функцию и обозвал её?Ой! Я об этом даже не догадывался! :)
он просто пишет в машинном коде:
Call [адрес функции в памяти]
:)
Ну а дальше у проца есть регистры...Это то, что поможет мне заставить рендерер брать данные не из файла, а из интерпретатора Python?
Регистр IP (счётчик команд) указывает на адрес в памяти, где лежит команда к процессору... и ещё есть стэк :) тамо хранятсо все локальные переменные функций...
Python - интерпретатор , т.е. набор подпрограмм (читай лажа по скорости), он не сможет быстро работать никогда...Это тут каким боком? Блендер использует питон для создания файла сцены посредством скрипта экспорта, стало быть это факт, от которого нам не уйти никуда. Хотим мы или нет, но без питона, не влезая в код самого блендера, файл сцены мы не создадим ни для люкса, ни для яфы, ни для поврея, ни для кого, вообще. Но, если мы посмотрим правильно, то увидим, что время отнимает у нас ни столько питон, сколько сама запись в файл, как и вывод в консоль. Даже на С программа считает 100 миллисекунд, а, если захотим видеть результат в консоли, то уйдёт минута, три, пять...
нахрена тебе экспортировать сцену куда-то, тратя на это время и память, если ты можешь читать blend-файл из памяти?Python - интерпретатор , т.е. набор подпрограмм (читай лажа по скорости), он не сможет быстро работать никогда...Это тут каким боком? Блендер использует питон для создания файла сцены посредством скрипта экспорта, стало быть это факт, от которого нам не уйти никуда. Хотим мы или нет, но без питона, не влезая в код самого блендера, файл сцены мы не создадим ни для люкса, ни для яфы, ни для поврея, ни для кого, вообще. Но, если мы посмотрим правильно, то увидим, что время отнимает у нас ни столько питон, сколько сама запись в файл, как и вывод в консоль. Даже на С программа считает 100 миллисекунд, а, если захотим видеть результат в консоли, то уйдёт минута, три, пять...
Другая сторона медали - парсер. Бесконечные сравнения, приведения... Одно дело объявить а = 10, другое дело перебрать сто условий в конце которых таки выяснится, что а = 10...
но если сможешь, то лучше читай напрямую из памяти- это наилучший вариант :)Так я ж это и делаю. Только, чтобы что-то прочитать из памяти, туда нужно сначала положить что-то. Блендера сцену в память может положить только интерпретатор питона. Ты ж раззуй глаза, я не использую бинарник блендера, я использую сборку блендера как сишный питон-модуль. Из С++ я даю команду загрузить сцену в память:
Да, нахера мне твой файл? В нём есть все вычисления деформаций в каждом кадре? В файле только ключи, на основании которых блендер считает деформации в каждом кадре. Или ты предлагаешь мне перенести из кода блендера все алгоритмы вычислений?нахрена тебе экспортировать сцену куда-то, тратя на это время и память, если ты можешь читать blend-файл из памяти?Python - интерпретатор , т.е. набор подпрограмм (читай лажа по скорости), он не сможет быстро работать никогда...Это тут каким боком? Блендер использует питон для создания файла сцены посредством скрипта экспорта, стало быть это факт, от которого нам не уйти никуда. Хотим мы или нет, но без питона, не влезая в код самого блендера, файл сцены мы не создадим ни для люкса, ни для яфы, ни для поврея, ни для кого, вообще. Но, если мы посмотрим правильно, то увидим, что время отнимает у нас ни столько питон, сколько сама запись в файл, как и вывод в консоль. Даже на С программа считает 100 миллисекунд, а, если захотим видеть результат в консоли, то уйдёт минута, три, пять...
Другая сторона медали - парсер. Бесконечные сравнения, приведения... Одно дело объявить а = 10, другое дело перебрать сто условий в конце которых таки выяснится, что а = 10...
да, это сложно... но это наиболее эффективно и быстро....
Или ты предлагаешь мне перенести из кода блендера все алгоритмы вычислений?тебе из кода бленд-файла нужны только те данные, которые поддерживает твой рендер... если он не поддерживает модификаторы, то их придётся схлопнуть, или написать их аналоги, или юзать тормознутый Python... х.з. по идее, в рендер должна покадрово идти только ФИНАЛЬНАЯ сетка с материалами, камера и ИС, а не её модификаторы...
Т.е. ты тупо копируешь данные из памяти в память, а потом ещё и в свой рендерер, расходуя её в х3 больше :) Эффективней будет читать .blend напрямую из памяти, тогда расход уменьшится до х2, но это сложно...Я загружаю в С++ модуль bpy, модуль загружает блендфайл, я даю команду передать данные первого кадра, получаю данные,
или юзать тормознутый Python...Да, в разумных пределах он тормознутый. За 28 секунд у меня создаётся BlenderMesh в 3 000 000 треугольников. Сколько понадобится на преобразование его в PovrayMesh я не знаю ещё, но предполагаю секунд 5, да хоть и 28 ещё - меньше минуты. Сейчас вот запустил обычный вариант, 7 минут подготовка к рендеру. Разница в шесть минут для анимации - уже хороший прирост в экономии времени.
Ладно, Ланухумыч, извини за дерзость... я не вполне шарю, о чём ты... если тебе нет дела до того, что я к тебе пишу, то и не придавай значения.Может, ты и правильно советуешь, но не такому программисту как я. Имей я достаточное количество времени...
У меня к тебе просьба помочь (написать дополнение), если сможешь, и когда у тебя будет время... завтра подробно напишу в личку.