Почему приведение переменной в экземпляре класса также приводит к преобразованию ее в другой экземпляр родительского класса? - PullRequest
0 голосов
/ 04 мая 2020

Я пытался подготовить к работе небольшой 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: Если я прав, как мне это исправить? проблема?

Заранее спасибо: Сусло

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...