How do I make cube faces opaque on OpenGL? - c++

I'm writing a program to draw a cube on OpenGL and rotate it continuously on mouse clicks. At particular angles, I'm able to see through the cube (transparent). I've enabled Depth Test, so I don't know why this is happening. I am not sure if I have enabled it correctly.
#include <math.h>
#include <vector>
#include <Windows.h>
#include <gl\glut.h>
using namespace std;
void myInit() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 1);
glOrtho(-2, 2, -2, 2, 2, -2);
glMatrixMode(GL_MODELVIEW);
}
float Cube[][3] = { {-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, 1, -1}, {-1, -1, 1}, {1, -1, 1}, {1, 1, 1}, {-1, 1, 1} };
float Colors[][3] = { {0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {1, 1, 0}, {0, 1, 1}, {1, 0, 1}, {1, 1, 1} };
int axis = 0, theta[3] = {0, 0, 0};
void draw_face (int a, int b, int c, int d) {
glBegin(GL_QUADS);
glColor3fv(Colors[a]);
glVertex3fv(Cube[a]);
glColor3fv(Colors[b]);
glVertex3fv(Cube[b]);
glColor3fv(Colors[c]);
glVertex3fv(Cube[c]);
glColor3fv(Colors[d]);
glVertex3fv(Cube[d]);
glEnd();
}
void draw_cube () {
draw_face(0, 3, 2, 1);
draw_face(2, 3, 7, 6);
draw_face(0, 4, 7, 3);
draw_face(1, 2, 6, 5);
draw_face(4, 5, 6, 7);
draw_face(0, 1, 5, 4);
}
void spin_cube() {
theta[axis] += 2;
if (theta[axis] > 360)
theta[axis] = -360;
glutPostRedisplay();
}
void idle_func() {
Sleep(10);
spin_cube();
}
void mouse_func(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
axis = 0;
else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
axis = 1;
else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
axis = 2;
}
void myDrawing() {
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glRotatef(theta[0], 1, 0, 0);
glRotatef(theta[1], 0, 1, 0);
glRotatef(theta[2], 0, 0, 1);
draw_cube();
glPopMatrix();
glFlush();
glutSwapBuffers();
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glEnable(GL_DEPTH_TEST);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("sample");
glutDisplayFunc(myDrawing);
glutIdleFunc(idle_func);
glutMouseFunc(mouse_func);
myInit();
glutMainLoop();
}

Multiple issues:
You aren't requesting a depth buffer from GLUT:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
Solution: OR in GLUT_DEPTH to make sure GLUT requests some depth buffer bits from the OS during GL context creation:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
You're calling glEnable(GL_DEPTH_TEST) before GLUT has created a GL context:
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
// no GL context yet
glEnable(GL_DEPTH_TEST);
Solution: Move the glEnable() to after glutCreateWindow() so it has a current GL context to work with:
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("sample");
glEnable(GL_DEPTH_TEST);
...
You never clear the depth buffer:
void myDrawing() {
// where's GL_DEPTH_BUFFER_BIT?
glClear(GL_COLOR_BUFFER_BIT);
...
Solution: OR in GL_DEPTH_BUFFER_BIT to your glClear() argument:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
All the fixes together:
#include <cmath>
#include <vector>
#include <GL/glut.h>
using namespace std;
void myInit() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 1);
glOrtho(-2, 2, -2, 2, 2, -2);
glMatrixMode(GL_MODELVIEW);
}
float Cube[][3] = { {-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, 1, -1}, {-1, -1, 1}, {1, -1, 1}, {1, 1, 1}, {-1, 1, 1} };
float Colors[][3] = { {0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {1, 1, 0}, {0, 1, 1}, {1, 0, 1}, {1, 1, 1} };
int axis = 0, theta[3] = {0, 0, 0};
void draw_face (int a, int b, int c, int d) {
glBegin(GL_QUADS);
glColor3fv(Colors[a]);
glVertex3fv(Cube[a]);
glColor3fv(Colors[b]);
glVertex3fv(Cube[b]);
glColor3fv(Colors[c]);
glVertex3fv(Cube[c]);
glColor3fv(Colors[d]);
glVertex3fv(Cube[d]);
glEnd();
}
void draw_cube () {
draw_face(0, 3, 2, 1);
draw_face(2, 3, 7, 6);
draw_face(0, 4, 7, 3);
draw_face(1, 2, 6, 5);
draw_face(4, 5, 6, 7);
draw_face(0, 1, 5, 4);
}
void spin_cube() {
theta[axis] += 2;
if (theta[axis] > 360)
theta[axis] = -360;
glutPostRedisplay();
}
void idle_func() {
Sleep(10);
spin_cube();
}
void mouse_func(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
axis = 0;
else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
axis = 1;
else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
axis = 2;
}
void myDrawing() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(theta[0], 1, 0, 0);
glRotatef(theta[1], 0, 1, 0);
glRotatef(theta[2], 0, 0, 1);
draw_cube();
glPopMatrix();
glFlush();
glutSwapBuffers();
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("sample");
glEnable(GL_DEPTH_TEST);
glutDisplayFunc(myDrawing);
glutIdleFunc(idle_func);
glutMouseFunc(mouse_func);
myInit();
glutMainLoop();
}

Related

C++ SFML: How to successfully Iteratively render shapes?

I'm looking to iteratively create a set of rectangle shapes of different colours and display them on the screen in different positions. This should produce a maze made up of rectangles.
The positions of the shapes should reflect the array that stores a 9x9 maze.
I'm able to successfully create a single shape, change it's colour and position. However, when I try to do the same to a shape inside an array it does not work. Only a single blue rectangle is generated in the top right corner of the screen.
int main() {
sf::RenderWindow window(sf::VideoMode(1920, 1080), "Baphomet");
sf::RectangleShape tiles[81] = {sf::RectangleShape(sf::Vector2f(20, 20))};
char maze[81] = {0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 1, 0, 1, 1, 1, 0,
0, 1, 0, 1, 0, 1, 0, 1, 0,
0, 1, 1, 1, 0, 1, 0, 1, 0,
0, 0, 0, 1, 0, 1, 0, 1, 0,
0, 1, 1, 1, 0, 1, 1, 1, 0,
0, 0, 1, 0, 0, 0, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0};
int x;
int y;
for (int i = 0; i < 81; i++) {
if (maze[i] == 0) {
tiles[i].setFillColor(sf::Color::Blue);
} else if (maze[i] == 1) {
tiles[i].setFillColor(sf::Color::Red);
}
x = (i % 9) * 20;
y = (i / 9) * 20;
std::cout << x << " " << y << std::endl;
tiles[i].setPosition((float)x, (float)y);
}
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
for (int i = 0; i < 81; i++) {
window.draw(tiles[i]);
}
window.display();
}
return 0;
}
How can I make the shapes change their positions to the x and y variables successfully?
I think the main problem is the definition
sf::RectangleShape tiles[81] = {sf::RectangleShape(sf::Vector2f(20, 20))};
Here you explicitly initialize only the first element (tiles[0]). All the rest of the elements will only have default-constructed shape objects.
To properly initialize all elements to the same values, either use a loop
for (auto& shape : tiles)
shape = sf::RectangleShape(sf::Vector2f(20, 20));
Or use a vector
std::vector<sf::RectangleShape> tiles(81, sf::RectangleShape(sf::Vector2f(20, 20)));

How convert text to pixel array in QT

I'm new user of QT. Is it possible to convert for example one character or string to array where 0 means white field and 1 means black field? For example when I have character "a" saved as QString or any representation of font and I would like to get following array:
int array[9][6] = { //"a" char array
{0, 0, 0, 0, 0, 0}, //- - - - - -
{0, 1, 1, 1, 1, 0}, //- * * * * -
{1, 0, 0, 0, 0, 1}, //* - - - - *
{0, 0, 0, 0, 0, 1}, //- - - - - *
{0, 1, 1, 1, 1, 1}, //- * * * * *
{1, 0, 0, 0, 0, 1}, //* - - - - *
{1, 0, 0, 0, 1, 1}, //* - - - * *
{0, 1, 1, 1, 0, 1}, //- * * * - *
{0, 0, 0, 0, 0, 0}, //- - - - - -
};
Is there any way in QT for reach that goal ? I hope I describe my problem as clear as possible and someone can help me with this?
And very important thing size array must depend on selected font size, so if I choose for example 30 pt font, array should be appropriate bigger than 10 pt font.
Thank You very much.
Best regards.
You can draw text onto a bitmap image, which will give you a bitmap containing text. Which is a pixel array, for all intents and purposes.
Note that you will also have to use a "bitmap font", regular fonts won't really do the trick as most have been created to utilize antialiasing and won't result in a crisp and readable bitmap image.
Qt also offers font metrics, which can give you a clear idea how big text or individual characters are.
I misinterpreted the question on my first read through... well, here is what was asked for...
#include <QApplication>
#include <QPixmap>
#include <QLabel>
#include <QPainter>
#include <QDebug>
#include <QVector>
#include <QFontMetrics>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSize size;
// QPixmap pixmap(100,100);
QImage image(20,20, QImage::Format_Mono);// Change the width and height here as needed if your letters get too big
image.fill(0);
{
QPainter painter(&image);
//// alternative to fill method
// painter.setBrush(Qt::black);
// painter.drawRect(0,0,image.width(), image.height());
painter.setPen(Qt::white);
QFontMetrics fm(painter.font());
size.setHeight(fm.height());
size.setWidth(fm.width('a'));
painter.drawText(0,fm.height(),"a");
}
QLabel label;
label.setPixmap(QPixmap::fromImage(image).scaled(400,400, Qt::KeepAspectRatio));
label.show();
QVector <QVector <int> > array(size.height(), QVector < int> (size.width(), 0));
for(int r = 0; r < size.height(); r++)
for(int c = 0; c < size.width(); c++)
array[r][c] = (image.pixelColor(c,r) == Qt::white ? 1 : 0);
// qDebug() << size << array;
foreach(QVector <int> row, array)
qDebug() << row;
return a.exec();
}
Output:
QVector(0, 0, 0, 0, 0, 0)
QVector(0, 0, 0, 0, 0, 0)
QVector(0, 0, 0, 0, 0, 0)
QVector(0, 0, 0, 0, 0, 0)
QVector(0, 0, 0, 0, 0, 0)
QVector(0, 0, 0, 0, 0, 0)
QVector(0, 0, 0, 0, 0, 0)
QVector(0, 1, 1, 1, 0, 0)
QVector(0, 0, 0, 0, 1, 0)
QVector(0, 1, 1, 1, 1, 0)
QVector(1, 0, 0, 0, 1, 0)
QVector(1, 0, 0, 0, 1, 0)
QVector(0, 1, 1, 1, 1, 0)

How to get Player to interact with Monster using ncurses library?

I've been trying to create my roguelike type of game for C++ using the ncurses library. After following many different tutorials, I am able to create the Player character, the map, the code to prevent the Player from going through walls and the random movements for the Monster character.
The next problem I'm encountering is implementing a boolean so whenever the Player character interacts with the Monster character, the game will quit (much like the roguelike games). However, I can't seem to get it to function the way I wanted. I think it has to do with the coordinates that I have set for the Player and the Monster but I'm still not sure. Can anyone help me out please?
Here is the code:
#include <iostream>
#include <ncurses.h>
#define MAP_WIDTH 22
#define MAP_HEIGHT 15
#define TILE_FLOOR 0
#define TILE_WALL 1
int PlayerX, PlayerY;
void erase (int y, int x) {
mvaddch(y, x, '.');
}
int nMapArray[MAP_HEIGHT][MAP_WIDTH] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{ 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};
bool IsPassable (int nMapX, int nMapY) { //prevents from walking into walls
if (nMapX < 0 || nMapX >= MAP_WIDTH || nMapY < 0 || nMapY >= MAP_HEIGHT)
return false;
int nTileValue = nMapArray[nMapY][nMapX];
if( nTileValue == TILE_FLOOR) {
return true;
}
return false;
}
class Monster {
public:
void Appearance(char monster) {
this->Monster = monster;
}
void SetPos(int x, int y) {
this->PosX = x;
this->PosY = y;
}
void Movement(int &MonsX, int &MonsY) {
int x = (rand() % 3 - 1);
int y = (rand() % 3 - 1);
if (IsPassable(this->PosX+x, this->PosY+y)) {
erase(PosY, PosX);
MonsX = this->PosX += x;
mvaddch(this->PosY, MonsX, this->Monster);
refresh();
erase(PosY, PosX);
MonsY = this->PosY += y;
mvaddch(MonsY, this->PosX, this->Monster);
refresh();
}
}
protected:
int PosX;
int PosY;
char Monster;
};
bool MonsterContact (int nMapY, int nMapX, int x, int y) {
if (nMapArray[nMapY][nMapX] == nMapArray[y][x]) {
return true;
}
return false;
}
void map() {
for (int y = 0; y < MAP_HEIGHT; y++) { //loops to print the map
move(y,0);
for (int x = 0; x < MAP_WIDTH; x++) {
switch (nMapArray[y][x]) {
case TILE_FLOOR:
printw(".");
break;
case TILE_WALL:
printw("#");
break;
}
}
}
};
void init() { //starts the ncurses screen.
initscr();
clear();
noecho();
raw();
keypad(stdscr, TRUE);
curs_set(0);
}
void game_loop (char Player, int row, int col, int ch) {
Monster npc;
npc.SetPos(7, 8);
npc.Appearance('g');
int MonsX,MonsY;
mvaddch(row,col, Player); //player movement
refresh();
while(true) {
npc.Movement(MonsX, MonsY);
ch = getch();
switch (ch) {
case 'w':
if (IsPassable(col, row-1)) {
erase(row,col);
row = row - 1;
mvaddch(row, col, Player);
refresh();
}
if (MonsterContact(col, row, MonsX, MonsY)) {
return();
}
break;
case 's':
if (IsPassable(col, row+1)) {
erase(row, col);
row = row + 1;
mvaddch(row, col, Player);
refresh();
}
if (MonsterContact(col, row, MonsX, MonsY)) {
return();
}
break;
case 'a':
if (IsPassable(col-1, row)) {
erase(row,col);
col = col - 1;
mvaddch(row, col, Player);
refresh();
}
if (MonsterContact(col, row, MonsX, MonsY)) {
return();
}
break;
case 'd':
if (IsPassable(col+1, row)) {
erase(row,col);
col = col + 1;
mvaddch(row,col, Player);
refresh();
}
if (MonsterContact(col, row, MonsX, MonsY)) {
return();
}
break;
case 'q':
return;
default:
break;
}
}
}
int main(int argc, const char * argv[]) {
PlayerX = 2, PlayerY = 1; //Player initial position.
char Player = '#';
init(); //starts the ncurses screen.
printw("Press any key to start the game");
int ch = getch();
clear();
map();
game_loop(Player, PlayerY, PlayerX, ch);
endwin();
return 0;
}
I'll sum up what jonhopkins commented on.
This is essentially a result of inconsistency. Your code passes arguments in different orders in different functions (first x, then y in isPassable, but vice versa in MonsterContact), and uses different names for the same things (row and x are the same.)
Your problem is caused by the fact that you passed col, row into MonsterContact, when you should have passed row, col. Perhaps you subconsciously copied the order of arguments from when you wrote isPassable a little earlier, forgetting that the order of arguments is reversed. Or you momentarily mistakenly thought that col meant y and row meant x.
Always remember to keep your code as consistent as possible, and you can avoid these sorts of mistakes in the future.

Accessing Lua global tables with C++

How can I access a global table that already exists in Lua using C++ ?
Below are code which I tried. I tried creating a global variable and try modifying a that local to the local in Lua but things dont seem to work
lua_State *lua_state = luaL_newstate();
luaL_openlibs(lua_state);
// lua_createtable(lua_state, 0, 81);
// for (int i = 1; i <= 81; i++)
// {
// lua_pushnumber(lua_state, i);
// lua_pushnumber(lua_state, grid_[i - 1]);
// lua_settable(lua_state, -3);
// }
//
// lua_setglobal(lua_state, "arg");
// lua_createtable(lua_state, 81, 1);
//
// for (int i = 1; i <= 81; i++)
// {
// lua_pushnumber(lua_state, i);
// lua_pushnumber(lua_state, grid_[i - 1]);
// lua_settable(lua_state, -3);
// }
// lua_setglobal(lua_state, "arg");
luaL_loadfile(lua_state, "main.lua");
lua_call(lua_state, 0, 0);
int t = 2;
/* table is in the stack at index 't' */
lua_pushnil(lua_state); /* first key */
while (lua_next(lua_state, t) != 0) {
/* uses 'key' (at index -2) and 'value' (at index -1) */
printf("%s - %s\n",
lua_typename(lua_state, lua_type(lua_state, -2)),
lua_typename(lua_state, lua_type(lua_state, -1)));
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(lua_state, 1);
}
Lua
problem =
{
{9, 0, 0, 1, 0, 0, 0, 0, 5},
{0, 0, 5, 0, 9, 0, 2, 0, 1},
{8, 0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 7, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 6, 0, 0, 9},
{2, 0, 0, 3, 0, 0, 0, 0, 6},
{0, 0, 0, 2, 0, 0, 9, 0, 0},
{0, 0, 1, 9, 0, 4, 5, 7, 0},
}
Update 1
int main()
{
lua_State *lua_state = luaL_newstate();
luaL_openlibs(lua_state);
luaL_loadfile(lua_state, "main.lua");
lua_getglobal(lua_state, "problem");
//lua_pushglobaltable(lua_state); // Get global table
lua_pushnil(lua_state); // put a nil key on stack
while (lua_next(lua_state, -2) != 0) { // key(-1) is replaced by the next key(-1) in table(-2)
std::string name = lua_tostring(lua_state, -2); // Get key(-2) name
std::cout << name << std::endl;
lua_pop(lua_state, 1); // remove value(-1), now key on top at(-1)
}
lua_pop(lua_state, 1); // remove global table(-1)
lua_call(lua_state, 0, 0);
return 0;
}
Lua
problem =
{
{9, 0, 0, 1, 0, 0, 0, 0, 5},
{0, 0, 5, 0, 9, 0, 2, 0, 1},
{8, 0, 0, 0, 4, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 0, 0, 0, 0},
{0, 0, 0, 7, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 2, 6, 0, 0, 9},
{2, 0, 0, 3, 0, 0, 0, 0, 6},
{0, 0, 0, 2, 0, 0, 9, 0, 0},
{0, 0, 1, 9, 0, 4, 5, 7, 0},
}
print("Lua Works")
user_input = io.read();
You don't have any values to iterate on Lua stack.
That int t=2; doesn't reflect anything, and your script doesn't return values to be left on stack.
See PIL book: 25.1 – Table Manipulation for examples on accessing global table.

The function glMultiDrawElements does not work correctly

I want to render a simple cube using the function 'glMultiDrawElements' (even if there is just one object!) but there is a bad display! However if I use the function 'glDrawElements' everything works! I want to precise 'glewInit' has been correctly initialized.
Here's the code using 'glDrawElements' :
[...]
std::vector<std::vector<int32_t>> indexArray = pRenderBatch->GetIndexAttribArray();
std::vector<int32_t> countArray = pRenderBatch->GetCountElementArray(indexArray);
// indexArray[0] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 0, 2, 19, 3, 5, 20, 21, 22, 10, 23, 11, 13, 24, 14, 25, 15, 17}
//Size(indexArray) = 1, Size(indexArray[0])=36
// countArray = {36} //Size(countArray)=1
glDrawElements(GL_TRIANGLES, countArray[0], GL_UNSIGNED_INT, (const GLvoid *)&indexArray[0][0]);
[...]
Now, here's the code using 'glMultiDrawElements' :
[...]
std::vector<std::vector<int32_t>> indexArray = pRenderBatch->GetIndexAttribArray();
std::vector<int32_t> countArray = pRenderBatch->GetCountElementArray(indexArray);
glMultiDrawElements(GL_TRIANGLES, &countArray[0], GL_UNSIGNED_INT, (const GLvoid **)&indexArray[0], countArray.size());
[...]
Here's the display:
However according the OpenGL documentation (http://www.opengl.org/sdk/docs/man3/xhtml/glMultiDrawElements.xml), the function 'glMultiDrawElements' has the following signature:
void glMultiDrawElements(GLenum mode, const GLsizei * count, GLenum type, const GLvoid ** indices, GLsizei primcount);
I don't understand why the display is not correct. Does anyone can help me?
std::vector<std::vector<int32_t>> indexArray
glMultiDrawElements() is expecting a pointer to an array of indexes. It doesn't know anything about the layout of std::vector<int32_t>.
Try this instead:
std::vector< int32_t* > indexArray2
You can construct it like this:
std::vector< int32_t* > indexArray2( indexArray.size() );
for( size_t i = 0; i < indexArray.size(); ++i )
{
indexArray2[i] = &indexArray[i][0];
}
EDIT: Complete example:
#include <GL/glew.h>
#include <GL/glut.h>
#include <vector>
using namespace std;
void display()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( -2, 2, -2, 2, -1, 1 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
GLfloat verts[] =
{
0, 0,
1, 0,
1, 1,
0, 0,
-1, 0,
-1, -1,
};
vector< GLsizei > counts;
vector< vector< unsigned int > > indexes;
{
vector< unsigned int > index;
index.push_back( 0 );
index.push_back( 1 );
index.push_back( 2 );
counts.push_back( index.size() );
indexes.push_back( index );
}
{
vector< unsigned int > index;
index.push_back( 3 );
index.push_back( 4 );
index.push_back( 5 );
counts.push_back( index.size() );
indexes.push_back( index );
}
vector< unsigned int* > indexes2( indexes.size() );
for( size_t i = 0; i < indexes.size(); ++i )
{
indexes2[i] = &indexes[i][0];
}
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_FLOAT, 0, verts );
glMultiDrawElements
(
GL_TRIANGLES,
&counts[0],
GL_UNSIGNED_INT,
(const GLvoid **)&indexes2[0],
counts.size()
);
glutSwapBuffers();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
glutInitWindowSize( 600, 600 );
glutCreateWindow( "GLUT" );
glewInit();
glutDisplayFunc( display );
glutMainLoop();
return 0;
}