Related
I'm looking to make a function return an array of set size, and assign the value of that array to another array. The function is located in one file and the array I will be assigning it's return value to is located in another.
I'm attempting to do this in an SFML project. Whenever I call the array function, my program freezes and stops responding.
generate_maze.cpp:
#include <SFML/Graphics.hpp>
#include "generate_maze.h"
char* generate_maze() {
char test_maze[169] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0,
0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0,
0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
return test_maze;
}
extract of main.cpp:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <SFML/Graphics.hpp>
#include "controls.h"
#include "generate_maze.h"
...
char* maze = generate_maze();
std::cout << (int) maze[0] << std::endl;
generate_maze.h:
char* generate_maze();
Thanks in advance for the help.
The code does not work because generate_maze() returns a pointer to a local variable, which is destroyed on exiting the function. To make it work one could design generate_maze() to allocate an array of char via new, then the allocated array survives after generate_maze() is finished. But that would also require to explicitly free the memory, after char *maze is no longer used.
A much better c++-like solution is the following.
If the size of the array is fixed, you should better use std::array to store the result of generate_maze(), as:
#include <array>
std::array<char, 169> generate_maze() {
return { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0,
0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0,
0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
}
If the size of the array returned by generate_maze() is not fixed, the correct way is to use std::vector and declare generate_maze() as
#include <vector>
std::vector<char> generate_maze();
generate_maze returns the address of test_maze[0], which is a local variable. You should never ever return addresses of (or references to) local variables from a function.
Allocate the maze on the heap instead and return that:
char* generate_maze() {
char local[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0,
0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0,
0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0,
0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0,
0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
char* ret = new char[sizeof local];
memcpy(ret, local, sizeof local);
return ret;
}
Alternatively, just return a std::vector which does its own memory management.
std::vector<char> generate_maze() {
return {0, 0, 0, ...};
}
generate_maze() returns pointer to local array, which is destroyed when function exits.
To solve this problem, you can define test_maze static: static char test_maze[].
This will create one permanent array for all generaze_maze() function calls. If you going to implement generate_maze() to return different maze arrays, better use std::vector or std::array.
I am currently trying to program Pacman in C++ using OpenGL. I am currently trying to create a display list to draw the maze. My thoughts were to create a square tile and then simply display said tile if matrix indicates a wall segment at some position. My code for this is:
const unsigned int FREE = 0;
const unsigned int WALL = 1;
const unsigned int GHOST_WALL = 2;
const unsigned int matrix[22][19] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1},
{1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1},
{1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1},
{1, 1, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1},
{1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1},
{1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1},
{1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1},
{1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1},
{1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
GLuint tile_handle = 0;
GLuint maze_handle = 0;
/*
* Initialize maze by precompiling its components
*/
void maze_init() {
// request a single display list handle for the tile
tile_handle = glGenLists(1);
glNewList(tile_handle, GL_COMPILE);
glColor3f(0, 0, 0.7f); // Blue
glBegin(GL_QUADS);
glVertex2i(0,0);
glVertex2i(1,0);
glVertex2i(1,1);
glVertex2i(0,1);
glEnd();
glEndList();
// request a single display list handle for the entire maze
maze_handle = glGenLists(1);
glNewList(maze_handle, GL_COMPILE);
glColor3f(0, 0, 0.7f); // Blue
for(int row = 0; row < 22; row--) {
for(int col = 0; col < 19; col++) {
if(matrix[21-row][col] == WALL) {
glPushMatrix();
glScaled(30, 30, 1);
glTranslated(col, row, 0);
glCallList(tile_handle);
glPopMatrix();
}
}
}
glEndList();
}
I then use maze_init() in my main initialisation method and use the call glCallList(maze_handle); in my main display function. This compiles fine but when I try to run it, it gives me a Bus error: 10 error.
Now I tried the same without the loops in the definition of glNewList(maze_handle, GL_COMPILE); and it ran fine. My question is therefore this: why do the loops (or the conditional statement) inside the call list create a bus error?
I tried a simple loop inside glNewList(maze_handle, GL_COMPILE); that made calls to DISTINCT display lists and it ran fine. So is the problem here that I make a repeated call to the same display list? For some reason I just can't seem to find the problem here ...
This is a school project that I'm currently working on. I have a problem with returning the multidimensional array Map[25][60]. The method get_map() has to return the whole map so I can use it as a parameter in the function move_left().
// ProjectX v3.0.cpp : Defines the entry point for the console application.
#include <iostream>
#include <windows.h>
#include <conio.h>
#include <thread>
#include <fstream>
using namespace std;
class wallz
{
int i;
int j;
public:
wallz();
~wallz();
void set_i(int def_i);
void set_j(int def_j);
int get_i();
int get_j();
void move_left(int Map[25][60], wallz wallz_temp);
};
wallz::wallz()
{
}
wallz::~wallz()
{
}
void wallz::set_i(int def_i)
{
i = def_i;
}
void wallz::set_j(int def_j)
{
j = def_j;
}
int wallz::get_i()
{
return i;
}
int wallz::get_j()
{
return j;
}
void wallz::move_left(int Map[25][60], wallz wallz_temp)
{
int x = 0;
while (x == 0)
{
if (Map[wallz_temp.get_i()][wallz_temp.get_j()] == 11)
{
Map[wallz_temp.get_i()][wallz_temp.get_j()] = 0;
Map[wallz_temp.get_i() - 1][wallz_temp.get_j()] = 11;
}
if (Map[wallz_temp.get_i() - 1][wallz_temp.get_j()] == 11)
{
Map[wallz_temp.get_i()][wallz_temp.get_j()] = 11;
Map[wallz_temp.get_i() - 1][wallz_temp.get_j()] = 0;
}
}
}
class map
{
wallz wallz_mass[30];
int char_X;
int char_Y;
int i;
int j;
int Map[25][60];
public:
map(int Map[25][60]);
~map();
void map_print();
void controlz();
int get_map();
wallz get_wallz(int h);
void map1_set_wallz();
void map2_set_wallz();
void map3_set_wallz();
void map4_set_wallz();
void map5_set_wallz();
void move_left();
void move_right();
void move_horizontal();
void move_up();
void move_down();
void move_vertical();
};
map::map(int m[25][60])
{
char_X = 1;
char_Y = 1;
for (int i = 0; i<25; i++)
for (int j = 0; j<60; j++)
Map[i][j] = m[i][j];
}
map::~map()
{
}
void map::map_print()
{
int MapCounter = 0;
for (int i = 0; i<25; i++)
{
for (int j = 0; j<60; j++)
{
if (MapCounter == 60)
{
cout << "" << endl;
MapCounter = 0;
}
if (i == char_X && j == char_Y)
{
cout << char(35);
}
else if (Map[i][j] == 1)
{
cout << char(186);//vertikalna liniq
}
else if (Map[i][j] == 0)
{
cout << " ";
}
else if (Map[i][j] == 2)//horizontalna liniq
{
cout << char(205);
}
else if (Map[i][j] == 3)
{
cout << char(200);//dolen lqv ugul
}
else if (Map[i][j] == 4)
{
cout << char(201);//goren lqv ugul
}
else if (Map[i][j] == 5)
{
cout << char(188);//dolen desen ugul
}
else if (Map[i][j] == 6)
{
cout << char(187);//goren desen ugul
}
else if (Map[i][j] == 7)
{
cout << char(204);//lqv vodoprovod
}
else if (Map[i][j] == 8)
{
cout << char(185);//desen vodoprovod
}
else if (Map[i][j] == 9)
{
cout << char(202);//goren vodoprovod
}
else if (Map[i][j] == 10)
{
cout << char(203);//desen vodoprovod
}
else if (Map[i][j] == 11)
{
cout << char(254); //
}
MapCounter++;
}
}
}
void map::controlz()
{
if (GetAsyncKeyState(VK_UP) != 0)
{
if (Map[char_X - 1][char_Y] == 0)
{
char_X--;
}
}
if (GetAsyncKeyState(VK_DOWN) != 0)
{
if (Map[char_X + 1][char_Y] == 0)
{
char_X++;
}
}
if (GetAsyncKeyState(VK_LEFT) != 0)
{
if (Map[char_X][char_Y - 1] == 0)
{
char_Y--;
}
}
if (GetAsyncKeyState(VK_RIGHT) != 0)
{
if (Map[char_X][char_Y + 1] == 0)
{
char_Y++;
}
}
}
int map::get_map()
{
return Map[25][60];
}
wallz map::get_wallz(int h)
{
return wallz_mass[h];
}
void map::map1_set_wallz()
{
wallz_mass[0].set_i(6);
wallz_mass[0].set_j(2);
}
void move_left(map map1)
{
map1.get_wallz(0).move_left(map1.get_map(), map1.get_wallz(0));
}
int main()
{
int x, y;
COORD ord;
ord.X = x = 0;
ord.Y = y = 0;
system("cls");
int Map[25][60] = {
4, 2, 6, 0, 0, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0, 0, 0, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6,
1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 3, 2, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 2, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 6, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
1, 0, 4, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 2, 6, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 2, 0, 0, 1,
1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
1, 0, 11, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 2, 5, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 2, 0, 0, 1,
1, 0, 1, 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 2, 5, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
1, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 2, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 2, 2, 6, 0, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 0, 7, 2, 2, 8, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 2, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 2, 2, 2, 2, 2, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 2, 0, 0, 1,
0, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0, 1, 0, 0, 4, 2, 2, 2, 2, 2, 2, 2, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 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, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 2, 2, 8,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 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, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 5, 0, 0, 1, 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, 1, 0, 0, 3, 2, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 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, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 1, 0, 0, 7, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 9, 2, 6, 2, 2, 2, 6, 0, 0, 0, 1,
0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 9, 2, 2, 2, 5,
};
map map1(Map);
bool stop = false;
while (stop == false)
{
map1.controlz();
map1.map_print();
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), ord);
}
thread first(move_left, map1);
first.join();
system("pause>nul");
return 0;
}
from here
In C++, it is not possible to pass the entire block of memory
represented by an array to a function directly as an argument. But
what can be passed instead is its address. In practice, this has
almost the same effect, and it is a much faster and more efficient
operation.
You may find this forum post helpful for learning about this exact thing. Here is a quick example on how to operate on the contents of a multidimensional array (taken from the forum).
const int MAX_ROWS = 4;
const int MAX_COLS = 4;
void printMatrix(int matrix[MAX_ROWS][MAX_COLS], int r, int c)
{
for(int i=0;i<r;i++)
{
for(int j=0;j<c;j++)
{
cout<<matrix[i][j]<<" ";
}
cout<<endl;
}
}
See also: How do I use arrays in c++?
I am experimenting with doing bicubic interpolation of some gridded data using Eigen, and I can't figure out how to reshape the 16x1 column vector of coefficients into a 4x4 matrix. Ideally I would like to do something along the lines of https://bitbucket.org/eigen/eigen/pull-request/41/reshape/diff without any copying, but I can't make heads or tails of the docs. Alternatively, a map would be fine as well, but I can't figure out how to use a map on an already existing matrix.
More here: http://en.wikipedia.org/wiki/Bicubic_interpolation
/// The inverse of the A matrix for the bicubic interpolation
/// (http://en.wikipedia.org/wiki/Bicubic_interpolation)
static const double Ainv_data[16*16] = {
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-3, 3, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2, -2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -2, -1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 1, 1, 0, 0,
-3, 0, 3, 0, 0, 0, 0, 0, -2, 0, -1, 0, 0, 0, 0, 0,
0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0, 0, -2, 0, -1, 0,
9, -9, -9, 9, 6, 3, -6, -3, 6, -6, 3, -3, 4, 2, 2, 1,
-6, 6, 6, -6, -3, -3, 3, 3, -4, 4, -2, 2, -2, -2, -1, -1,
2, 0, -2, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 0, -2, 0, 0, 0, 0, 0, 1, 0, 1, 0,
-6, 6, 6, -6, -4, -2, 4, 2, -3, 3, -3, 3, -2, -1, -2, -1,
4, -4, -4, 4, 2, 2, -2, -2, 2, -2, 2, -2, 1, 1, 1, 1};
Eigen::Matrix<double, 16, 16> Ainv(Ainv_data);
Eigen::Matrix<double, 16, 1> f;
f.setRandom();
Eigen::Matrix<double, 16, 1> alpha = Ainv*f;
// This next line works, but it is making a copy, right?
Eigen::Matrix<double, 4, 4> a(alpha.data());
The last line is indeed doing a copy, so you can use a Map as follow:
Map<Matrix4d,Eigen::Aligned> a(alpha.data());
a behaves like a Matrix4d and it is read-write. The Eigen::Aligned flag tells Eigen that the pointer you pass to Map is properly aligned for vectorization. The only difference with a pure Matrix4d is that the C++ type is not the same.
So I have a 2D array which acts as a map for my tiles to be drawn.
int sMap[12][20] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 2, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1},
{1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1},
{1, 1, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 1, 0, 1, 1, 2, 2, 2, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
};
Once my tiles have been loaded in, I use this function() to place the tiles:
for (int y = 0; y < 12; y++){
for (int x = 0; x < 20; x++){
if (sMap[y][x] == 1)
glBindTexture( GL_TEXTURE_2D, brick1);
else if (sMap[y][x] == 2)
glBindTexture( GL_TEXTURE_2D, brick2);
else
glBindTexture( GL_TEXTURE_2D, wall );
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(float(x + offsetx), float(MAP_SIZEY - (y + offsety)), 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(float(x + 1 + offsetx), float(MAP_SIZEY - (y + offsety)), 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(float(x + 1 + offsetx), float(MAP_SIZEY - (y + 1 + offsety)), 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(float(x + offsetx), float(MAP_SIZEY - (y + 1 + offsety)), 0.0f);
glEnd();
}
}
I think I may have confused myself with the coordinate system of the tiles because when I draw a basic OpenGL square which acts as a sprite, I just get a black screen upon running the program.
I'm unsure whether this means the scale of the sprite to the tiles is wrong, or whether the sprite and tiles are on different Zplanes...
I would appreciate if someone could explain the coordinate system in case I don't understand it as much as I thought and also advise me how to draw an OpenGLsquare on the same coordinates.
Currently I have this to draw my basic sprite:
struct RECT{float x, y, w, h;};
RECT sprite = {0, 0, 10, 10};
void drawSprite (RECT rect){
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(rect.x, rect.y, 0.0);
glVertex3f(rect.x, rect.y+rect.h, 0.0);
glVertex3f(rect.x+rect.w, rect.y+rect.h, 0.0);
glVertex3f(rect.x+rect.w, rect.y, 0.0);
glEnd();
}
EDIT:
resize screen:
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,20.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
draw scene:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(10.0f, 8.0f, 20.0f, 10.0f, 8.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glTranslatef(5.0f,4.0f,0.0f);
draw_tiles();
draw_sprite();
In the draw_tiles function it looks like you might be passing incorrect coordinates - maybe you should be multiplying the x and y values by your tile size.
Also try turning off depth testing and backface culling to help resolve your black screen problem.
glDisable( GL_DEPTH_TEST );
glDisable( GL_CULL_FACE );