Я пытался подготовить к работе небольшой 3D-движок, но столкнулся с несколькими проблемами. А именно: когда я пытаюсь добавить анимацию к одному из моих объектов / классов, его геометрия (переменная, используемая для описания его формы) также перезаписывает некоторые другие объекты из родительского класса.
Я вставлю здесь несколько фрагментов кода, чтобы показать, что я имею в виду: Родительский класс Geometry:
class ParamSurface : public Geometry {
//---------------------------
unsigned int nVtxPerStrip, nStrips;
public:
ParamSurface() { nVtxPerStrip = nStrips = 0; }
virtual VertexData GenVertexData(float u, float v) = 0;
void create(int N = tessellationLevel, int M = tessellationLevel) {
nVtxPerStrip = (M + 1) * 2;
nStrips = N;
std::vector<VertexData> vtxData; // vertices on the CPU
for (int i = 0; i < N; i++) {
for (int j = 0; j <= M; j++) {
vtxData.push_back(GenVertexData((float)j / M, (float)i / N));
vtxData.push_back(GenVertexData((float)j / M, (float)(i + 1) / N));
}
}
glBufferData(GL_ARRAY_BUFFER, nVtxPerStrip * nStrips * sizeof(VertexData), &vtxData[0], GL_STATIC_DRAW);
// Enable the vertex attribute arrays
glEnableVertexAttribArray(0); // attribute array 0 = POSITION
glEnableVertexAttribArray(1); // attribute array 1 = NORMAL
glEnableVertexAttribArray(2); // attribute array 2 = TEXCOORD0
// attribute array, components/attribute, component type, normalize?, stride, offset
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, normal));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, texcoord));
}
void Draw() {
glBindVertexArray(vao);
for (unsigned int i = 0; i < nStrips; i++) glDrawArrays(GL_TRIANGLE_STRIP, i * nVtxPerStrip, nVtxPerStrip);
}
};
Производные классы Geometry:
class Sphere2 : public ParamSurface{
public:
float R = 1.0f;
float Rt = 1.0f;
Sphere2(float f = 1.0f) { R = f; create(); }
float F(float u, float v, long t) {
float n = 2.0f;
return 1.0 + (R * cosf(n * u) * sinf(n * v) * sinf(t)) * 0.5;
}
VertexData GenVertexData(float u, float v) {
VertexData vd;
float t = glutGet(GLUT_ELAPSED_TIME) / 200;
float U = u * 2.0f * (float)M_PI;
float V = v * (float)M_PI;
Rt = F(U, V, t);
vd.position = vd.normal = vec3( Rt * R * cosf(U) * sinf(V), Rt * R * sinf(U) * sinf(V), Rt * R * cosf(V));
vd.texcoord = vec2(u, v);
return vd;
}
};
(этот меняет свою форму в зависимости от времени, поэтому он вроде как анимированный, однако его нужно каждый раз воссоздавать с нуля)
class Tractricoid : public ParamSurface {
float height = 3;
public:
Tractricoid(float f1 = 3.0f) { height = f1; create(); }
VertexData GenVertexData(float u, float v) {
VertexData vd;
float U = u * height;
float V = v * 2.0f * (float)M_PI;
vd.position = vd.normal = vec3(
cosf(V) / coshf(U),
sinf(V) / coshf(U),
U - tanhf(U));
vd.texcoord = vec2(u, v);
return vd;
}
};
(Это представляет собой неанимированную (исправленную) фигуру, которая должна выглядеть как половина тех элементов, которые используются в начальном mov ie, используемом для определения, спит ли кто-то или нет)
Объект родительский класс, который использует эти геометрии:
struct Object {
//---------------------------
Shader* shader;
Material* material;
Texture* texture;
Geometry* geometry;
vec3 scale, translation, rotationAxis;
float rotationAngle;
public:
Object(Shader* _shader, Material* _material, Texture* _texture, Geometry* _geometry) :
scale(vec3(1, 1, 1)), translation(vec3(0, 0, 0)), rotationAxis(0, 0, 1), rotationAngle(0) {
shader = _shader;
texture = _texture;
material = _material;
geometry = _geometry;
}
virtual void SetModelingTransform(mat4& M, mat4& Minv) {
M = ScaleMatrix(scale) * RotationMatrix(rotationAngle, rotationAxis) * TranslateMatrix(translation);
Minv = TranslateMatrix(-translation) * RotationMatrix(-rotationAngle, rotationAxis) * ScaleMatrix(vec3(1 / scale.x, 1 / scale.y, 1 / scale.z));
}
void Draw(RenderState state) {
mat4 M, Minv;
SetModelingTransform(M, Minv);
state.M = M;
state.Minv = Minv;
state.MVP = state.M * state.V * state.P;
state.material = material;
state.texture = texture;
shader->Bind(state);
geometry->Draw();
}
virtual void Animate(float tstart, float tend) {
//std::cout << "animate Object " << std::endl;
//rotationAngle = 0.8f * tend;
//I tried a basic rotation as animation, it works properly for every object, but it's not possible to change based on what object I want to animate, hence why I wanted to do that in a derived class.
}
};
И, наконец, что не менее важно, возможно ошибочный производный класс, который, к сожалению, должен передать свою геометрическую переменную в ParamSurface, чтобы получить доступ к некоторым из своих функций, но тем временем грустно бросая Переменная геометрии других экземпляров, которые были членами родительского класса, а не производного класса.
struct ParamObject : public Object {
ParamObject(Shader* _shader, Material* _material, Texture* _texture, Geometry* _geometry) : Object(_shader, _material, _texture, _geometry) {}
//Animation for the Param Object
void Animate(float tstart, float tend) {
ParamSurface* ps = (ParamSurface*)geometry;
ps->create();
ps->Draw();
//std::cout << "animate ParamObject " << std::endl;
}
};
Мои вопросы: 1: Правильно ли я предполагаю, что производный объект (ParamObject) класс тот, который вызывает у меня проблемы? (если я попытаюсь создать каждый объект как часть родительского класса, они будут работать, они просто не анимированы / не обновляются, даже если их геометрия будет меняться.) 2: Если я прав, как мне это исправить? проблема?
Заранее спасибо: Сусло