Array of Objects in C++ - c++

i am trying to do chess with openGL c ++, for now i have created the pawn object, where its constructor takes an unsigned int parameter. So I tried to create an array of these pawns, and the only working way I've found to do this is this :
Pawn *pawn[n];
for (int i = 0; i < n; i++) {
pawn[i] = new Pawn(Unsigned int var);
}
To call a function of pawn [0], for example, I have to do this :
pawn[0]->function(parameters);
This is the Pawn class :
class Pawn
{
private:
float vertices [16] = {
//position //text coord
-0.08f, -0.10f, 0.0f, 0.0f,
0.08f, -0.10f, 1.0f, 0.0f,
0.08f, 0.10f, 1.0f, 1.0f,
-0.08f, 0.10f, 0.0f, 1.0f
};
GLuint indices[6] {
0, 1, 2,
0, 2, 3
};
unsigned int shaderID, VBO, VAO, EBO, texture;
public:
glm::vec2 Position = glm::vec2(0.0f, 0.0f);
Pawn () {}
Pawn(GLuint shaderID) {
...
}
~Pawn() {
...
}
void setTexture();
void draw (glm::vec2 position);
};
I also tried this :
Pawn pawn[8];
for (int i = 0; i < 8; i++) {
pawn[i] = Pawn(shaderID);
}
but when i run it doesn't work.
I was wondering if this method is efficient or not, and if so, why it works, since I didn't understand it. Thanks for your help

Related

Storing many objects and their data within arrays from IMUs for further calculation

I currently have a robotics project which is using many (16) IMU's specifically the MPU9250 running under SPI.
As a reduced example of six sensors using the Bolder flight library
int cs[6] = {21, 25, 26, 27, 32, 14}; //chipselects
MPU9250 IMU0(SPI, 21); // Header P5
MPU9250 IMU1(SPI, 25); // Header P6
MPU9250 IMU2(SPI, 26); // Header P7
MPU9250 IMU3(SPI, 27); // Header P9
MPU9250 IMU4(SPI, 32); // Header P10
MPU9250 IMU5(SPI, 12); // Header P11
To use these sensors they all have to be calibrated and have magnetic hard and soft offsets applied to them live during use, on top of that, I also have to apply gyroscopic and accel. calibration algorithms. Which means, for each sensor, I have to call 9 different data points from each IMU and apply some maths, so I set up some arrays for storing in between values and final values and offsets:
// Offsets applied to raw x/y/z mag values
float mag_offsets[6][3] = {
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 10.44F, 34.76F, -49.86F },
{ 8.62F, 20.41F, -12.65F },
{ -3.05F, 19.75F, -8.55F },
};
// Soft iron error compensation matrix
float mag_softiron_matrix[6][3][3] = {
// IMUs 27, 14, 32
{{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }},
{{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }},
{{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }},
// IMUs, 21, 25, 26
{{ 1.036F, 0.017F, -0.001F }, { 0.017F, 0.954F, -0.028F }, { -0.001F, 0.028F, 1.013F }},
{{ 1.031F, 0.013F, -0.024F }, { 0.013F, 0.897F, 0.054F }, { -0.024F, 0.054F, 1.085F }},
{{ 1.057F, 0.034F, 0.017F }, { 0.034F, 0.967F, 0.038F }, { 0.017F, 0.038F, 0.981F }},
};
float mag_field_strength[3] = {38.52F, 37.24F , 38.58F };
// Offsets applied to compensate for gyro zero-drift error for x/y/z, sensor dependent
float gyro_zero_offsets[6][3] = {
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
};
// Used for calculating 'in between values' prior to passing to final mag array, sensor dependent
float deltamag[6][3] = {
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
};
// Following array names should always be constant and final values to be given to Magdwick filters, sensor agnostic.
float gyro[6][3] = {
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
};
float accel[6][3] = {
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
};
float mag[6][3] = {
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
{ 0.0F, 0.0F, 0.0F },
};
Then in the loop itself I call each object and get the sensors readings:
void loop(){
IMU0.readSensor();
IMU1.readSensor();
IMU2.readSensor();
IMU3.readSensor();
IMU4.readSensor();
IMU5.readSensor();
// update accel, gyro, mag arrays
float getAccel[6][3] = {
{ IMU0.getAccelX_mss(), IMU0.getAccelY_mss(), IMU0.getAccelZ_mss() },
{ IMU1.getAccelX_mss(), IMU1.getAccelY_mss(), IMU1.getAccelZ_mss() },
{ IMU2.getAccelX_mss(), IMU2.getAccelY_mss(), IMU2.getAccelZ_mss() },
{ IMU3.getAccelX_mss(), IMU3.getAccelY_mss(), IMU3.getAccelZ_mss() },
{ IMU4.getAccelX_mss(), IMU4.getAccelY_mss(), IMU4.getAccelZ_mss() },
{ IMU5.getAccelX_mss(), IMU5.getAccelY_mss(), IMU5.getAccelZ_mss() },
};
float getGyro[6][3] = {
{ IMU0.getGyroX_rads(), IMU0.getGyroY_rads(), IMU0.getGyroZ_rads() },
{ IMU1.getGyroX_rads(), IMU1.getGyroY_rads(), IMU1.getGyroZ_rads() },
{ IMU2.getGyroX_rads(), IMU2.getGyroY_rads(), IMU2.getGyroZ_rads() },
{ IMU3.getGyroX_rads(), IMU3.getGyroY_rads(), IMU3.getGyroZ_rads() },
{ IMU4.getGyroX_rads(), IMU4.getGyroY_rads(), IMU4.getGyroZ_rads() },
{ IMU5.getGyroX_rads(), IMU5.getGyroY_rads(), IMU5.getGyroZ_rads() },
};
float getMag[6][3] = {
{ IMU0.getMagX_uT(), IMU0.getMagY_uT(), IMU0.getMagZ_uT() },
{ IMU1.getMagX_uT(), IMU1.getMagY_uT(), IMU1.getMagZ_uT() },
{ IMU2.getMagX_uT(), IMU2.getMagY_uT(), IMU2.getMagZ_uT() },
{ IMU3.getMagX_uT(), IMU3.getMagY_uT(), IMU3.getMagZ_uT() },
{ IMU4.getMagX_uT(), IMU4.getMagY_uT(), IMU4.getMagZ_uT() },
{ IMU5.getMagX_uT(), IMU5.getMagY_uT(), IMU5.getMagZ_uT() },
};
// Apply magnetic offsets
for (int j = 0; j < 6; j++) {
for (int i = 0; i < 4; i++) {
deltamag[j][i] = getMag[j][i] - mag_offsets[i][j];
}
}
// Apply magnetic softiron offsets
for (int k = 0; k < 6; k++) {
for (int j = 0; j < 6; j++) {
for (int i = 0; i < 4; i++) {
mag[j][i] = deltamag[j][0] * mag_softiron_matrix[k][0][0] + deltamag[j][1] * mag_softiron_matrix[k][0][1] + deltamag[j][2] * mag_softiron_matrix[k][0][2];
}
}
}
// Apply gyroscope offsets
for (int j = 0; j < 6; j++) {
for (int i = 0; i < 4; i++) {
gyro[j][i] = getGyro[j][i] - gyro_zero_offsets[j][i];
}
}
// Update Madgwick filters
filter0.update(gyro[0][0], gyro[0][1], gyro[0][2], accel[0][0], accel[0][1], accel[0][2], mag[0][0], mag[0][1], -1 * mag[0][2]);
filter1.update(gyro[1][0], gyro[1][1], gyro[1][2], accel[1][0], accel[1][1], accel[1][2], mag[1][0], mag[1][1], -1 * mag[1][2]);
filter2.update(gyro[2][0], gyro[2][1], gyro[2][2], accel[2][0], accel[2][1], accel[2][2], mag[2][0], mag[2][1], -1 * mag[2][2]);
filter3.update(gyro[3][0], gyro[3][1], gyro[3][2], accel[3][0], accel[3][1], accel[3][2], mag[3][0], mag[3][1], -1 * mag[3][2]);
filter4.update(gyro[4][0], gyro[4][1], gyro[4][2], accel[4][0], accel[4][1], accel[4][2], mag[4][0], mag[4][1], -1 * mag[4][2]);
filter5.update(gyro[5][0], gyro[5][1], gyro[5][2], accel[5][0], accel[5][1], accel[5][2], mag[5][0], mag[5][1], -1 * mag[5][2]);
// Call All Euler Angle Rotations around {X,Y,Z} or {gamma, delta, epsilon}
float eulerAngles[6][3] = {
{filter0.getRoll(), filter0.getPitch(), filter0.getYaw()},
{filter1.getRoll(), filter1.getPitch(), filter1.getYaw()},
{filter2.getRoll(), filter2.getPitch(), filter2.getYaw()},
{filter3.getRoll(), filter3.getPitch(), filter3.getYaw()},
{filter4.getRoll(), filter4.getPitch(), filter4.getYaw()},
{filter5.getRoll(), filter5.getPitch(), filter5.getYaw()},
};
Serial.print(eulerAngles[0][0]);
Serial.print(eulerAngles[0][1]);
Serial.print(eulerAngles[0][2]);
}
Though the code seems to work the way I expected it, I am confident this is the wrong method to store this data...namely in the getAccel, getGyro, getMag arrays, or to call them like in eulerAngles .
My hunch on this was during initial testing some sensors data that I receive are have an oscillating error being applied to them, which makes me think i'm receiving junk data from the memory somewhere
...I would have used a for loop, but since each object name is individual and do not have indices, I am unsure the best practice, nor the fastest way to call and work with such a large data set. I have found a similar question, though I'm unfortunately too dumb to apply it to my situation.
So the question is what is the proper method to call and store so many objects (and their data) in arrays for further calculations? I would like to avoid having over a hundred variables (when using all 16 IMUs and in-between variables to carry out all the appropriate maths. My apologies for probably terribly written code, my c++/Wiring is not the best.
Research object-oriented programming. Apply encapsulation. Group data depending on object, not similarities - just like you think about them.
Use standard library objects - std::array. Save memory, allow optimization - apply const whenever possible, use constexpr when possible. Research code guidelines and style guides - like https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-philosophy and https://google.github.io/styleguide/cppguide.html .
Let's say in pseudocode, you could encapsulate all variables within one object and use member function to calculate the relevant stuff:
class MyStuff { // pick more meaningfull name
// maybe be more verbose
using axisvals = std::array<float, 3>;
private:
// apply constness to save RAM memory
static const std::array<float, 3> mag_field_strength = { 38.52F, 37.24F , 38.58F };
MPU9250 mpu;
FILTER filter;
const std::array<float, 3> mag_offsets;
const std::array<std::array<float, 3> , 6> mag_softiron_matrix;
std::array<float, 3> gyros{}; // maybe some internal state?
public:
MyStuff(int gpionum,
const std::array<float, 3>& mag_offsets,
const std::array<std::array<float, 3> , 6> mag_softiron_matrix) :
mpu{SPI, gpionum},
filter{some, params, for, filter, constructor},
mag_offsets{mag_offsets},
mag_softiron_matrix{mag_softiron_matrix} {
}
void setup() {
// do some setuping stuff
}
axisvals calculate_stuff() {
mpu.readSensor();
// use const as much as possible
const std::array<float, 3> guro = {
something * mpu.getGyroX_rads(),
something * mpu.getGyroY_rads(),
something * mpu.getGyroZ_rads(),
};
// ...
filter.update(
gyro[0], gyro[1], gyro[2],
accel[0], accel[1], accel[0][2],
mag[0], mag[1], -1 * mag[2]);
// ...
return {filter.getRoll(), filter.getPitch(), filter.getYaw()};
}
};
std::array<MyStuff, 6> imus = {
{ 21, {10.44F, 34.76F, -49.86F}, {{1.036F, 0.017F, -0.001F }, {...}, {...} }, // Header P5
{25, {....} {{...},{..}{...} }, // Header P6
// etc....
};
void setup() {
for (auto&& imu : imus) {
imu.setup();
}
}
void loop() {
for (auto&& imu : imus) {
const auto&vals = imu.calculate_stuff();
for (auto&& v : vals) {
Serial.print(v);
}
}
}

Draw 2 quads with one function DirectX11

I'm Leanrning DirectX11 and I'm trying to draw 2 Quad with a single function but when i call this function , the function override the previous QUAD.
If you want to see the problem , here is a gif :
<video alt="Video from Gyazo" width="1280" autoplay muted loop playsinline controls><source src="https://i.gyazo.com/b819ffc64975c1531434047b9b4a92f7.mp4" type="video/mp4" /></video>
Here is the code :
(here is where i call the function to draw the QUAD)
void Application::ApplicationRun()
{
//wind.SetEventCallBack(std::bind(&Application::OnEvent, Instance, std::placeholders::_1));
Vertex v[] =
{
Vertex(-0.5f, -0.5f, 0.0f, 1.0f), /// botom Left Point - [0]
Vertex(-0.5f, 0.5f, 0.0f, 0.0f), //top Left Point - [1]
Vertex{ 0.0f, -0.5f, 1.0f, 1.0f}, // -[2]
Vertex(0.0f, 0.5f, 1.0f, 0.0f), //Right Point - [3]
};
Vertex vv[] =
{
Vertex(-0.1f, -0.1f, 0.0f, 0.0f), /// botom Left Point - [0]
Vertex(-0.1f, 0.1f, 0.0f, 0.0f), //top Left Point - [1]
Vertex{ 0.05f, -0.1f, 0.0f, 0.0f}, // -[2]
Vertex(0.05f, 0.1f, 0.0f, 0.0f), //Right Point - [3]
};
DWORD indices[] =
{
0,1,2,
1,2,3,
};
while (wind.PorcessMessage())
{
//
if (Armageddon::Application::GetInstance()->GetWindow()->GetNativeKeyBoard().KeyIsPressed(AG_KEY_A))
{
Log::GetLogger()->trace("A ");
wind.GetWindowGraphics()->DrawTriangle(v, ARRAYSIZE(v));
}
if (Armageddon::Application::GetInstance()->GetWindow()->GetNativeKeyBoard().KeyIsPressed(AG_KEY_B))
{
Log::GetLogger()->trace("B");
wind.GetWindowGraphics()->DrawTriangle(vv, ARRAYSIZE(vv));
}
}
}
(Here is the DrawTriangle Function) :
void Armageddon::D3D_graphics::DrawTriangle(Vertex v[], int Vertexcount)
{
HRESULT hr = vertexBuffer.Initialize(this->device.Get(),this->device_context.Get() , v, Vertexcount);
if (FAILED(hr))
{
Armageddon::Log::GetLogger()->error("FAILED INITIALIZE VERTEX BUFFER ");
}
DWORD indices[] =
{
0,1,2,
1,2,3,
};
hr = this->indicesBuffer.Init(this->device.Get(), indices, ARRAYSIZE(indices));
hr = DirectX::CreateWICTextureFromFile(this->device.Get(), L"..\\TestApplication\\assets\\Textures\\tex.png",nullptr,textures.GetAddressOf());
if (FAILED(hr))
{
Armageddon::Log::GetLogger()->error("FAILED INITIALIZE WIC TEXTURE ");
}
}
(Here is where i initialize the Vertex and the Indice buffer) :
HRESULT Initialize(ID3D11Device* device , ID3D11DeviceContext* device_context, T* data, UINT numElements)
{
this->bufferSize = numElements;
this->stride = sizeof(T);
D3D11_BUFFER_DESC vertex_buffer_desc;
ZeroMemory(&vertex_buffer_desc, sizeof(vertex_buffer_desc));
vertex_buffer_desc.Usage = D3D11_USAGE_DEFAULT;
vertex_buffer_desc.ByteWidth = sizeof(Vertex) * numElements;
vertex_buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertex_buffer_desc.CPUAccessFlags = 0;
vertex_buffer_desc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA VertexBufferData;
ZeroMemory(&VertexBufferData, sizeof(VertexBufferData));
VertexBufferData.pSysMem = data;
HRESULT hr = device->CreateBuffer(&vertex_buffer_desc, &VertexBufferData, buffer.GetAddressOf());
UINT offset = 0;
device_context->IASetVertexBuffers(0, 1, buffer.GetAddressOf(), &stride, &offset);
return hr;
};```
HRESULT Init(ID3D11Device* device, DWORD* data, UINT n_indices)
{
D3D11_SUBRESOURCE_DATA Indice_buffer_data;
this->buffer_size = n_indices;
D3D11_BUFFER_DESC Indice_buffer_desc;
ZeroMemory(&Indice_buffer_desc, sizeof(Indice_buffer_desc));
Indice_buffer_desc.Usage = D3D11_USAGE_DEFAULT;
Indice_buffer_desc.ByteWidth = sizeof(DWORD) * n_indices;
Indice_buffer_desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
Indice_buffer_desc.CPUAccessFlags = 0;
Indice_buffer_desc.MiscFlags = 0;
ZeroMemory(&Indice_buffer_data, sizeof(Indice_buffer_data));
Indice_buffer_data.pSysMem = data;
HRESULT hr = device->CreateBuffer(&Indice_buffer_desc, &Indice_buffer_data, buffer.GetAddressOf());
return hr;
};
And here is where I draw the quads :
void Armageddon::D3D_graphics::RenderFrame()
{
float color[] = { 0.1f,0.1f,0.1f,1.0f };
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
// 3. Show another simple window.
if (show_another_window)
{
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
}
ImGui::Render();
this->device_context->OMSetRenderTargets(1, target_view.GetAddressOf(), this->depthStencilView.Get());
this->device_context->ClearRenderTargetView(this->target_view.Get(), color);
this->device_context->ClearDepthStencilView(this->depthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
//ICI QU'ON FAIT TOUT LES RENDU APRES AVOIR CLEAN LE PLAN
this->device_context->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY::D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
f += 0.1;
ConstantBuffer.data.mat = DirectX::XMMatrixRotationRollPitchYaw(0.0f,0.0f,f);
ConstantBuffer.data.mat = DirectX::XMMatrixTranspose(ConstantBuffer.data.mat);
ConstantBuffer.data.Yoffset = f;
ConstantBuffer.data.Xoffset = 0;
// Armageddon::Log::GetLogger()->trace(ConstantBuffer.data.Yoffset);
if (!ConstantBuffer.ApplyChanges())
{
Armageddon::Log::GetLogger()->error("ERRO WHEN APPLYING CHANGES");
}
this->device_context->VSSetConstantBuffers(0, 1, ConstantBuffer.GetAdressOf());
/***********SHADER*******************************/
this->device_context->VSSetShader(vertexShader.GetShader(), NULL, 0);
this->device_context->PSSetShader(pixelShader.GetShader(), NULL, 0);
this->device_context->IASetInputLayout(this->vertexShader.GetInputLayout());
/***********Texture Sampler*******************************/
this->device_context->PSSetSamplers(0, 1, this->ColorSampler.GetAddressOf());
/***********DEPHT BUFFER*******************************/
this->device_context->OMSetDepthStencilState(this->depthStencilState.Get(), 0);
/***********RASTERIZER STATE*******************************/
this->device_context->RSSetState(this->rasterizerState.Get());
/***********UPDATE LES CONSTANTS BUFFER*******************************/
UINT stride = sizeof(Vertex);
UINT offset = 0;
this->device_context->IASetIndexBuffer(indicesBuffer.Get(), DXGI_FORMAT_R32_UINT, 0);
//this->device_context->IASetVertexBuffers(0, 1, vertexBuffer.GetAddressOf(), &stride, &offset);
this->device_context->PSSetShaderResources(0, 1, this->textures.GetAddressOf());
this->device_context->DrawIndexed(indicesBuffer.GetSize(), 0,0);
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
this->swapchain->Present(1,0);
}

3D soft Engine: Array of objects without defining template argument list

I'm trying to write a simple 3D soft engine, but I've got a little problem..
I have a class called Mesh which contains vertex and edge data:
struct Vertex { float x, y, z; };
struct Edge { int from, to; };
template <int vs, int es>
class Mesh {
public:
Vertex vertices[vs];
int vSize = vs;
Edge edges[es];
int eSize = es;
};
then a derived class called Cube which specifies the vertex and edge data for a cube (I will later on add more shapes of course):
class Cube : public Mesh<8, 12> {
public:
inline Cube() {
Vertex v[] = {
{ -1.0f, -1.0f, -1.0f },
{ 1.0f, -1.0f, -1.0f },
{ 1.0f, 1.0f, -1.0f },
{ -1.0f, 1.0f, -1.0f },
{ -1.0f, -1.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f },
{ 1.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, 1.0f }
};
for (int i = 0; i < 8; i++)
this->vertices[i] = v[i];
Edge e[] = {
{ 0,1 },{ 1,2 },{ 2,3 },{ 3,0 },
{ 4,5 },{ 5,6 },{ 6,7 },{ 7,4 },
{ 0,4 },{ 1,5 },{ 2,6 },{ 3,7 }
};
for (int i = 0; i < 12; i++)
this->edges[i] = e[i];
}
};
And after that a class called Engine, which has an array of Mesh parent classes, which should be able to hold Cube and later Triangle etc..
template <int w, int h, int mSize>
class Engine {
private:
int width = w;
int height = h;
Mesh meshes[mSize]; <-- problem
int mCount = 0;
byte fBuffer[w][h];
byte bBuffer[w][h];
public:
inline Engine() {};
inline void addMesh(Mesh mesh) { this->meshes[this->mCount++] = mesh; }
};
which yields this error:
Engine.h: 19:3: error: invalid use of template-name 'Mesh' without an argument list
Mesh* meshes = new Mesh[m]
Engine.h: 25:23: error: 'Mesh' is not a type
inline void addMesh(Mesh mesh) { this->meshes[this->mCount++] = mesh; }
I know it's because the Mesh meshes[mSize]; should have Mesh<a, b> values but of course I don't know that for every possible Mesh.
What's a better way of storing these?
I suppose you could add a not-template base for Mesh, say mBase
struct mBase { };
template <std::size_t vs, std::size_t es>
struct Mesh : public mBase
{ };
and define meshes as an array of mBases
mBase meshes[mSize]; // <-- no more problem
void addMesh(mBase mesh) { this->meshes[this->mCount++] = mesh; }
You don't have to use templates for what you're trying to achieve here. So why don't declare your Mesh.vertices and Mesh.edges as std::vectors (for instance), and fill them as you construct your derived objects?
Like so:
#include <vector>
class Mesh {
public:
std::vector<Vertex> vertices;
std::vector<Edge> edges;
};
class Cube : public Mesh {
public:
Cube() {
// Following stuff is only allowed since c++11
// But there's other tricks for vector's initializations before c++11
this->vertices = {
{ -1.0f, -1.0f, -1.0f },
{ 1.0f, -1.0f, -1.0f },
{ 1.0f, 1.0f, -1.0f },
{ -1.0f, 1.0f, -1.0f },
{ -1.0f, -1.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f },
{ 1.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, 1.0f }
};
this->edges = {
{ 0,1 },{ 1,2 },{ 2,3 },{ 3,0 },
{ 4,5 },{ 5,6 },{ 6,7 },{ 7,4 },
{ 0,4 },{ 1,5 },{ 2,6 },{ 3,7 }
};
}
};
Note that you don't need to store the size of these vectors, since you can get it with: std::vector<T>.size() (Mesh.edges.size())
Make sure to be familiar with the templated objects from the STL before creating your own ;)
(In facts, here your classes should be structs... But that is out of scope of the problem I guess...)

Equivalent memcpy different results?

I used memcpy to copy a struct Vertex comprised of glm::vec3 objects.
It worked to copy the struct in a class function.
It did not work in the copy constructor that was called when that function returned the class object.
Why?
Class function returning object
ShapeData ShapeGenerator::drawTriangle() {
ShapeData ret;
Vertex verts[] = {
glm::vec3(0.0f, 1.0f, 0.0f),
glm::vec3(1.0f, 0.0f, 0.0f),
glm::vec3(-1.0f, -1.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f),
glm::vec3(1.0f, -1.0f, 0.0f),
glm::vec3(0.0f, 0.0f, 1.0f),
};
ret.numVerts = NUM_ARRAY_ELEMENTS(verts);
ret.verts = new Vertex[ret.numVerts];
memcpy(ret.verts, verts, sizeof(verts)); //WORKS
GLushort indicies[] = {0,1,2};
ret.numIndicies = NUM_ARRAY_ELEMENTS(indicies);
ret.indicies = new GLushort[ret.numIndicies];
memcpy(ret.indicies, indicies, sizeof(indicies));
return ret;
}
Copy Constructor
ShapeData(const ShapeData& data) {
verts = new Vertex[data.numVerts];
//memcpy(verts, data.verts, sizeof(data.verts)); //DOES NOT WORK
std::copy( data.verts, data.verts + data.numVerts, verts);
indicies = new GLushort[data.numIndicies];
memcpy(indicies, data.indicies, sizeof(data.indicies));
numVerts = data.numVerts;
numIndicies = data.numIndicies;
std::cout << numVerts << std::endl;
}
Vertex:
#ifndef VERTEX_H
#define VERTEX_H
#include <glm/glm.hpp>
struct Vertex {
glm::vec3 position;
glm::vec3 color;
};
#endif
memcpy(verts, data.verts, sizeof(data.verts)); //DOES NOT WORK
does not work since verts is a pointer, not an array. sizeof(data.verts) does not evaluate to the size of the array the pointer points to. It simply evaluates to the size of a pointer on your platform.
You should be able to use:
size_t n = sizeof(*data.verts)*data.numVerts;
memcpy(verts, data.verts, n);

Opengl Weird Rotation

I'm trying to rotate a simple triangle. The problem is that while it rotates correctly, it decrease its size until it disappears.
Some pieces of my code so far:
// Vertices
GLfloat vertexArray[] =
{
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
// Render funcion (called every frame)
void render()
{
glClearColor(0.0f, 0.0f, 0.4f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObj);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexArray), vertexArray, GL_DYNAMIC_DRAW);
glUseProgram(programID); // simple vertex/frag shader
glDrawArrays(GL_TRIANGLES, 0, 3);
// Swap buffers
glfwSwapBuffers();
}
// Update funcion (called every frame before render function)
void update(float elapsedTime)
{
printf("elapsedTime: %f \r", elapsedTime);
float static theta = elapsedTime * 0.2f;
for(int i = 0; i < 9; i+=3)
{
vertexArray[i] = (vertexArray[i] * cosf(theta)) - (vertexArray[i+1] * sinf(theta));
vertexArray[i+1] = (vertexArray[i] * sinf(theta)) + (vertexArray[i+1] * cosf(theta));
vertexArray[i+2] = 0;
}
}
As you can see, I'm rotating every vertex on update function with a for loop. Maybe the best way to do this is using the shader (correct me if I'm wrong), but I wanted to keep things simple here just to illustrate the problem.
I believe the problem is, that when you compute vertexArray[i+1] = (vertexArray[i] * sinf(theta)) + (vertexArray[i+1] * cosf(theta)); you are not using the value of vertexArray[i] from the previous iteration, but rather the new vertexArray[i] computed in the first assignment of the for loop.
Try this:
for(int i = 0; i < 9; i+=3)
{
double tmp = vertexArray[i];
vertexArray[i] = (tmp * cosf(theta)) - (vertexArray[i+1] * sinf(theta));
vertexArray[i+1] = (tmp * sinf(theta)) + (vertexArray[i+1] * cosf(theta));
vertexArray[i+2] = 0;
}