I have the following code...
void draw_polygon(struct vector2d* center, int num_points,
struct vector2d* points, int mode)
{
int i;
if(mode == GL_TRIANGLE_FAN)
glVertex2f(center->x, center->y);
for(i = 0; i < num_points; i++)
glVertex2f(points[i].x, points[i].y);
glVertex2f(points[0].x, points[0].y);
}
and I am trying to convert it so it is OpenGLES 1.1 compat. From other posts I thought it looked like I would need something similar to this...
void draw_polygon(struct vector2d* center, int num_points,
struct vector2d* points, int mode)
{
int i;
int offset=0;
GL_FLOAT *arr;
if(mode == GL_TRIANGLE_FAN)i{
*arr = (GL_FLOAT *)malloc(sizeof(GL_FLOAT) * ((num_points+1)*2));
arr[0]=center->x;
arr[1]=center->y;
offset = 2;
}
else{
*arr = (int *)malloc(sizeof(GL_FLOAT) * (num_points*2)) ;
}
for(i = 0; i < num_points; i++){
int g = i+offset;
arr[g]=points[i].x;
arr[g+1]=points[i].y;
i++;
}
}
But of course that doesn't compile. Can someone help me understand the proper way to handle this in GLES?
Firs about not compiling:
struct vector2d {
GLfloat x, y;
};
void draw_polygon(struct vector2d* center, int num_points,
struct vector2d* points, int mode)
{ //1st GL_FLOAT is not a type, use GLfloat
int i;
int offset=0;
GLfloat *arr;
if(mode == GL_TRIANGLE_FAN) { //what was that "i" doing here
arr = (GLfloat *)malloc(sizeof(GLfloat) * ((num_points+1)*2)); //no "*" before arr
arr[0]=center->x;
arr[1]=center->y;
offset = 2;
}
else{
arr = (GLfloat *)malloc(sizeof(GLfloat) * (num_points*2)) ; //no "*" before arr; Why do you typcast it to "(int *)"?
}
for(i = 0; i < num_points; i++){
int g = (i*2)+offset;//i*2
arr[g]=points[i].x;
arr[g+1]=points[i].y;
i++;
}
}
As for doing the whole code. GLES does not work with begin/end calls but you have to call the draw call. At this point with the code above what you did was create an array of vertex data, now you need to push it to GPU (or set the pointer for the data) and call glDrawArrays.
So you need to add:
glEnableClientState(GL_VERTEX_ARRAY); //this is usually set only once unless you want to disable it at some point for some very unlikelly reason
glVertexPointer(2, GL_FLOAT, 0, arr); //set the pointer (alternative is to use the VBO and copy the data directly to the GPU)
glDrawArrays(mode, 0, num_points+offset/2);
free(arr); //you need to free the allocated memory
in the same function.
To make your method look a bit less complicated you can try this:
void draw_polygon2(struct vector2d* center, int num_points, struct vector2d* points, int mode) {
if(mode == GL_TRIANGLE_FAN) {
vector2d *newBuffer = (vector2d *)malloc(sizeof(vector2d)*(num_points+1));//create a new buffer just to append center to beginning
newBuffer[0] = *center; //copy center
memcpy(newBuffer+1, points, sizeof(vector2d)*num_points); //copy all other points after center
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(vector2d), newBuffer);
glDrawArrays(mode, 0, num_points+1);
free(newBuffer);
}
else {
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(vector2d), points);
glDrawArrays(mode, 0, num_points);
}
}
Do note that since this function uses directly vector2d structure it is considered, that x and y are the first 2 parameters in the vector2d structure. Even if you added 'z' as the 3rd parameter the code should work.
Related
I'm trying to make a game of sorts in c++ where the player has to move 3 '#' chars, or otherwise known in the game as bears.
I can't seem to access the contents of my structure that I created for various items in the program, such as bears and bombs. For example, the x coordinates and the symbol are inaccessible in the called function, so I'm assuming it is to do with my passed parameters and my vector not being initialised properly. Code is below:
const char BEAR('#');
const int SIZEX(10); //horizontal dimension
const int SIZEY(6); //vertical dimension
struct Item {
int x, y;
char symbol;
};
vector<Item> bear(3); //there are supposed to be 3 bears
int main()
{
void initialiseGame(char g[][SIZEX], char m[][SIZEX], vector<Item>& b);
//local variable declarations
char grid[SIZEY][SIZEX]; //grid for display
char maze[SIZEY][SIZEX]; //structure of the maze
initialiseGame(grid, maze, bear); //initialise grid (incl. walls & bear)
//other irrelevant stuff
return 0;
}
void initialiseGame(char grid[][SIZEX], char maze[][SIZEX], vector<Item>& bear)
{ //initialise grid & place bear in middle
void setInitialMazeStructure(char maze[][SIZEX], vector<Item>& bear);
void setInitialDataFromMaze(char maze[][SIZEX], vector<Item>& bear);
void updateGrid(char g[][SIZEX], const char m[][SIZEX], vector<Item>& bear);
setInitialMazeStructure(maze, bear); //initialise maze
setInitialDataFromMaze(maze, bear); //initialise bear's position
updateGrid(grid, maze, bear); //prepare grid
}
void setInitialMazeStructure(char maze[][SIZEX], vector<Item>& bear)
{ //set the position of the walls in the maze
//initialise maze configuration
int initialMaze[SIZEY][SIZEX] //local array to store the maze structure
= { { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 2, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 2, 0, 1, 0, 0, 1, 0, 0, 1 },
{ 1, 2, 0, 1, 1, 0, 1, 0, 1, 1 },
{ 1, 1, 0, 0, 0, 1, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
// with 1 for wall, 0 for tunnel, etc.
//copy into maze structure
for (int row(0); row < SIZEY; ++row)
for (int col(0); col < SIZEX; ++col)
switch (initialMaze[row][col])
{
case 0: maze[row][col] = TUNNEL; break;
case 1: maze[row][col] = WALL; break;
case 2: maze[row][col] = BEAR; break;
}
}
void setInitialDataFromMaze(char maze[][SIZEX], const vector<Item>& bear)
{ //extract bear's coordinates from initial maze info
for (int row(0); row < SIZEY; ++row)
for (int col(0); col < SIZEX; ++col)
switch (maze[row][col])
{
case bear:
{
bear.x = col;
bear.y = row;
maze[row][col] = TUNNEL;
}
break;
}
}
This switch statement in setInitialiDateFromMaze() is where I'm getting the error with regards to the vector of Item, the error states that x & y as well as symbol do not exist as members of my struct Item.
for (int row(0); row < SIZEY; ++row)
for (int col(0); col < SIZEX; ++col)
switch (maze[row][col])
{
case bear:
{
bear.x = col;
bear.y = row;
maze[row][col] = TUNNEL;
}
break;
}
What can I do to fix this error? Is my vector of 3 bears being passed correctly?
std::vector doesn't have member data x and y. The way you are using your vector is therefore wrong. You should access x and y in the following manner:
bear[i].x
Bound-checking:
bear.at(i).x
case bear:
bear is declared as a:
vector<Item> bear(3);
The case value, in a switch, must be a single, literal constant value. bear is a vector, and it is not clear what your intent is, but this is the reason for your compilation error. Not to mention that, subsequently bear.x and bear.y also makes no sense, since bear is a vector, and it does not have either x, or y, as a class member.
atm I'm trying to code a rubics cube but I can't get it working.
So I got my class which is called "littlecube". It got an array of it's vertices(4 per side * 6 sides).The array is already filled with the right values. So I imagine each cube of the rubics cube as an object with 24 vertices. Is there another way to declare the three floats in the cpp file? Thought of the cubes as objects. Like in java or c#.To be honest I'm a big noob in C++.
littleCube.h:
#pragma once
class littleCube
{
public:
littleCube(void);
littleCube(const int positionX,const int positionY,const int positionZ);
~littleCube(void);
void calculateVertices(void);
void rotateVertical(const float rotationAngle);
void rotateHorizontal(const float rotationAngle);
void printLittleCube(void);
void printPosition(void);
void printRotation(void);
void printVertices(void);
float* getMyVertices(void);
};
littleCube.cpp:
#include "littleCube.h"
#include <iostream>
#include <math.h>
//Position of each Cube
float f_myPosition[4];
//Rotation of each Cube
float f_myRotation[4][4];
//All Vertices of a cube
float f_myVertices[24][3];
using namespace std;
//default constructor
littleCube::littleCube(void)
{
}
float* littleCube::getMyVertices(void)
{
return &f_myVertices[0][0];
}
After that I made an array of littleCubes which is 3 dimensional and I want to access each cubes field of vertices.
#include "littleCube.h"
typedef struct BasicVertex
{
float position[3];
uint32_t color;
} BasicVertex;
static BasicVertex *s_basicVertices= NULL;
littleCube bigCube[3][3][3];
int main( void )
{
for(int x = 0; x < 3; x++)
{
for(int y = 0; y < 3; y++)
{
for(int z = 0; z < 3; z++)
{
bigCube[x][y][z] = littleCube::littleCube(x+1,y+1,z+1);
}
}
}
createGmxData();
}
So in the following Code I'm getting an error at the following line:
"s_basicVertices[i].position[0] = &pointer[cubeVertices][0];"
void createGxmData( void )
{
s_basicVertices = (BasicVertex *)graphicsAlloc( ..., numVertices * 6 *sizeof(BasicVertex), 4, ..., ...);
int x,y,z,i = 0;
while(true)
{
float* pointer = bigCube[x][y][z].getMyVertices();
for(int cubeVertices = 0; cubeVertices < 24; cubeVertices++)
{
s_basicVertices[i].position[0] = &pointer[cubeVertices][0]; //x
s_basicVertices[i].position[1] = &pointer[cubeVertices][1]; //y
s_basicVertices[i].position[2] = &pointer[cubeVertices][2]; //z
i++;
}
z++;
if(z == 3)
{
z = 0;
y++;
if( y == 3)
{
y = 0;
x++;
if( x == 3)
break;
}
}
}
}
The Problem I get now is "error 143: expression must have pointer-to-object type" and I don't know why. Thought I got a pointer to the f_myVertices of each cube now.
The reason why I'm not showing the whole code is that it's the development kit for the psVita and I'm not shure if I'm allowed to show the code.
Many thanks
Ben
I'm sure this has been asked before, but the search terms are failing me for my specific situation.
Essentially, I'm creating a 2D tile engine. For overall efficiency and to reduce a bit of overhead, I have decided to implement my own simple memory management container...
The following code is what I'm using to do so:
Tile.h:
//Tile class
class CTile
{
public:
CTile();
~CTile();
unsigned int row;
unsigned int column;
};
//Container class
class CTileLayer
{
public:
CTileLayer(unsigned int nRows, unsigned int nCols, float w, float h);
~CTileLayer();
protected:
CTile** m_tiles;
unsigned long count;
void Allocate(unsigned int nRows, unsigned int nCols, float w, float h);
void Free();
};
Tile.cpp:
#include "Tile.h"
CTile::CTile() : row(0), column(0)
{
}
CTile::~CTile()
{
}
CTileLayer::CTileLayer(unsigned int nRows, unsigned int nCols, float w, float h) : m_tiles(NULL)
{
Allocate(nRows, nCols, w, h);
}
CTileLayer::~CTileLayer()
{
if(m_tiles != NULL) Free();
}
void CTileLayer::Allocate(unsigned int nRows, unsigned int nCols, float w, float h)
{
unsigned int column = 0, row = 0;
if(m_tiles != NULL) Free();
m_tiles = new CTile*[count = (nRows * nCols)];
for( unsigned long l = 0; l < count; l++ ) {
m_tiles[l] = new CTile[count];
m_tiles[l]->column = column + 1;
m_tiles[l]->row = row + 1;
//
//...
//
if(++column > nCols) {
column = 0;
row++;
}
}
}
void CTileLayer::Free()
{
delete [] *m_tiles;
delete [] m_tiles;
m_tiles = NULL;
count = 0;
}
So by seeing how each tile is allocated/freed, is it safe to say this won't produce any memory leaks?
If it will, what would be the most appropriate way to free this array, while making sure each object's destructor gets called? Should I loop through the array, manually deleting each object instead?
Why not do this:
CTile* m_tiles;
m_tiles = new CTile[nRows*nColumns];
delete[] m_tiles;
You called new CTile[count] count times, once for each m_tiles[l].
You need to therefore call delete[] count times, for each m_tiles[l].
It isn't clear what count is good for, however. You should be using nRows and nColumns for the two layers of the array. Right now you have nRows * nRows * nColumns * nColumns instances of CTile allocated, which is probably too many.
Instead try
m_tiles = new CTile*[nRows];
m_tiles[l] = new CTile[nColumns];
I am trying to do the following:
in main.cpp:
// Create an array of pointers to Block objects
Block *blk[64];
for (i=0; i<8; i++) {
for (j=0; j<8; j++) {
int x_low = i*80;
int y_low = j*45;
blk[j*8+i] = new Block(30, x_low+40.0f, y_low+7.5f, &b);
}
}
And then I am trying to pass it to the graphics object I have created:
Graphics g(640, 480, &b, &p, blk[0], number_of_blocks);
the graphics constructor looks like:
Graphics::Graphics(int width, int height, Ball *b, Paddle *p, Block *blk, int number_of_blocks) {
if I look at what is contained in the array from the graphics object, only the first item exists and then all the other items are in hyperspace:
for (int i=0; i<64; i++) {
printf("for block %d, %f, %f ", i, (_blk+(sizeof(_blk)*i))->_x_low, (_blk+(sizeof(_blk)*i))->_y_low);
printf("blah %d\n", (_blk+(sizeof(_blk)*i)));
}
and if I look at the addresses, they are different (6956552 rather than 2280520 when I examine the addresses in the main class using:
printf(" blah %d\n", &blk[j*8*i]);
I am sure there must be something subtle I am doing wrong as its like I have copied the first item from the blk array to a new address when passed to the graphics object.
Does this make sense? Any ideas?
Cheers,
Scott
If you want to pass the whole array, the constructor should look like this:
Graphics::Graphics(int width, int height, Ball *b, Paddle *p,
Block **blk, int number_of_blocks)
and you should pass the array like this:
Graphics g(640, 480, &b, &p, blk, number_of_blocks);
It looks like:
Graphics::Graphics(int width, int height, Ball *b, Paddle *p, Block *blk, int number_of_blocks) {
is expecting an array of Blocks, not an array of pointers to Blocks. Passing the first element would probably work if you made_number_of blocks 1, but it can't work for anything else using your current data structure. If I were you, I would give up on using arrays and use std::vector instead - it will greatly simplify your code.
The Graphics function is expecting a contiguous array of Block objects in memory and you are creating each new Block independently. Try
Block* blk = new Block[64];
then loop through and initialize each Block's values. This will only work if you can initialize the block objects in another way from using the constructor with arguments since new in this case can only call the default constructor. If the only way to initialize a Block is using the constructor with arguments, you'll have to do something else like passing Block** to the function.
From what I can see, you are passing the first element of the array to the contructor, not the whole array. This is what you are doing:
#include <iostream>
#include <cstdlib>
void foo(int* item, const int length);
int main() {
const int length = 10;
int* array[length];
for (int i = 0; i < length; ++i) {
array[i] = new int(i + 100);
}
foo(array[0], length);
return (EXIT_SUCCESS);
}
void foo(int* item, const int length) {
for (int i = 0; i < length; ++i) {
std::cout << item[i] << std::endl;
}
}
I believe this is what you wanted to do:
#include <iostream>
#include <cstdlib>
void foo(int** array, const int length);
int main() {
const int length = 10;
int* array[length];
for (int i = 0; i < length; ++i) {
int* item = new int(i + 100);
array[i] = item;
}
foo(array, length);
return (EXIT_SUCCESS);
}
void foo(int** array, const int length) {
for (int i = 0; i < length; ++i) {
int* item = array[i];
std::cout << *item << std::endl;
}
}
Regards,
Rafael.
I have a program that looks like the following:
double[4][4] startMatrix;
double[4][4] inverseMatrix;
initialize(startMatrix) //this puts the information I want in startMatrix
I now want to calculate the inverse of startMatrix and put it into inverseMatrix. I have a library function for this purpose whose prototype is the following:
void MatrixInversion(double** A, int order, double** B)
that takes the inverse of A and puts it in B. The problem is that I need to know how to convert the double[4][4] into a double** to give to the function. I've tried just doing it the "obvious way":
MatrixInversion((double**)startMatrix, 4, (double**)inverseMatrix))
but that doesn't seem to work. Is that actually the right way to do it?
No, there's no right way to do specifically that. A double[4][4] array is not convertible to a double ** pointer. These are two alternative, incompatible ways to implement a 2D array. Something needs to be changed: either the function's interface, or the structure of the array passed as an argument.
The simplest way to do the latter, i.e. to make your existing double[4][4] array compatible with the function, is to create temporary "index" arrays of type double *[4] pointing to the beginnings of each row in each matrix
double *startRows[4] = { startMatrix[0], startMatrix[1], startMatrix[2] , startMatrix[3] };
double *inverseRows[4] = { /* same thing here */ };
and pass these "index" arrays instead
MatrixInversion(startRows, 4, inverseRows);
Once the function finished working, you can forget about the startRows and inverseRows arrays, since the result will be placed into your original inverseMatrix array correctly.
For given reason that two-dimensional array (one contiguous block of memory) and an array of pointers (not contiguous) are very different things, you can't pass a two-dimensional array to a function working with pointer-to-pointer.
One thing you could do: templates. Make the size of the second dimension a template parameter.
#include <iostream>
template <unsigned N>
void print(double a[][N], unsigned order)
{
for (unsigned y = 0; y < order; ++y) {
for (unsigned x = 0; x < N; ++x) {
std::cout << a[y][x] << ' ';
}
std::cout << '\n';
}
}
int main()
{
double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
print(arr, 3);
}
Another, a bit clumsier way might be to make the function accept a pointer to a single-dimensional array, and both width and height given as arguments, and calculate the indexes into a two-dimensional representation yourself.
#include <iostream>
void print(double *a, unsigned height, unsigned width)
{
for (unsigned y = 0; y < height; ++y) {
for (unsigned x = 0; x < width; ++x) {
std::cout << a[y * width + x] << ' ';
}
std::cout << '\n';
}
}
int main()
{
double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
print(&arr[0][0], 3, 3);
}
Naturally, a matrix is something that deserves a class of its own (but the above might still be relevant, if you need to write helper functions).
Since you are using C++, the proper way to do something like this would be with a custom class and some templates. The following example is rather rough, but it gets the basic point across.
#include <iostream>
using namespace std;
template <int matrix_size>
class SquareMatrix
{
public:
int size(void) { return matrix_size; }
double array[matrix_size][matrix_size];
void copyInverse(const SquareMatrix<matrix_size> & src);
void print(void);
};
template <int matrix_size>
void SquareMatrix<matrix_size>::copyInverse(const SquareMatrix<matrix_size> & src)
{
int inv_x;
int inv_y;
for (int x = 0; x < matrix_size; x++)
{
inv_x = matrix_size - 1 - x;
for (int y = 0; y < matrix_size; y++)
{
inv_y = matrix_size - 1 - y;
array[x][y] = src.array[inv_x][inv_y];
}
}
}
template <int matrix_size>
void SquareMatrix<matrix_size>::print(void)
{
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
cout << array[x][y] << " ";
}
cout << endl;
}
}
template <int matrix_size>
void Initialize(SquareMatrix<matrix_size> & matrix);
int main(int argc, char * argList[])
{
SquareMatrix<4> startMatrix;
SquareMatrix<4> inverseMatrix;
Initialize(startMatrix);
inverseMatrix.copyInverse(startMatrix);
cout << "Start:" << endl;
startMatrix.print();
cout << "Inverse:" << endl;
inverseMatrix.print();
return 0;
}
template <int matrix_size>
void Initialize(SquareMatrix<matrix_size> & matrix)
{
for (int x = 0; x < matrix_size; x++)
{
for (int y = 0; y < matrix_size; y++)
{
matrix.array[x][y] = (x+1)*10+(y+1);
}
}
}
Two dimensional array is not a pointer to pointer or something similar. The correct type for you startMatrix is double (*)[4]. For your function, the signature should be like:
MatrixInversion( double (*A)[4], int order, double (*B)[4] );
There is a solution using the pointer to point by bobobobo
William Sherif (bobobobo) used the C version and I just want to show C++ version of bobobobo's answer.
int numRows = 16 ;
int numCols = 5 ;
int **a ;
a = new int*[ numRows* sizeof(int*) ];
for( int row = 0 ; row < numRows ; row++ )
{
a[row] = new int[ numCols*sizeof(int) ];
}
The rest of code is the same with bobobobo's.
You can definitely do something like the code below, if you want.
template <typename T, int n>
class MatrixP
{
public:
MatrixP operator()(T array[][n])
{
for (auto i = 0; i < n; ++i) {
v_[i] = &array[i][0];
}
return *this;
}
operator T**()
{
return v_;
}
private:
T* v_[n] = {};
};
void foo(int** pp, int m, int n)
{
for (auto i = 0; i < m; ++i) {
for (auto j = 0; j < n; ++j) {
std::cout << pp[i][j] << std::endl;
}
}
}
int main(int argc, char** argv)
{
int array[2][2] = { { 1, 2 }, { 3, 4 } };
auto pa = MatrixP<int, 2>()(array);
foo(pa, 2, 2);
}
The problem is that a two-dimensional array is not the same as an array of pointers. A two-dimensional array stores the elements one row after another — so, when you pass such an array around, only a pointer to the start is given. The receiving function can work out how to find any element of the array, but only if it knows the length of each row.
So, your receiving function should be declared as void MatrixInversion(double A[4][], int order, double B[4][]).
by nice coding if c++:
struct matrix {
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
so the interface would be
void MatrixInversion(matrix &A, int order, matrix &B);
and use it
MatrixInversion(startMatrix, 4, inverseMatrix);
The benefit
the interface is very simple and clear.
once need to modify "m" of matrix internally, you don't need to update the interface.
Or this way
struct matrix {
void Inversion(matrix &inv, int order) {...}
protected:
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
...
An ugly way in c
void MatrixInversion(void *A, int order, void *B);
MatrixInversion((void*)startMatrix, 4, (void*)inverseMatrix);
EDIT: reference code for MatrixInversion which will not crash:
void MatrixInversion(void *A, int order, void *B)
{
double _a[4][4];
double _b[4][4];
memcpy(_a, A, sizeof _a);
memcpy(_b, B, sizeof _b);
// processing data here
// copy back after done
memcpy(B, _b, sizeof _b);
}