glMultiDrawElementsIndirect - draws broken mesh... offsets issue? - opengl

I'm trying to build the command array but I keep on getting "broken" mesh draws. here is the struct I try to populate:
My Vertex/indices are stored in buffers as :
QVector<QVector3D> mVertex; // all meshes in 1 vector
QVector<unsigned int> mIndices; // all meshes in 1 vector
int mIndicesCount = mIndices.size(); // this is per mesh accessible
int mVertexCount = mVertex.size(); // this is per mesh accessible
The loop :
int skip =0;
int offset =0;
for (size_t u = 0; u < jobSize; ++u) {
DrawElementsIndirectCommand *cmd = &dstCmds[u];
cmd->count = mNodeList[u]->mIndicesCount;
cmd->instanceCount = 1;
cmd->firstIndex = skip;
cmd->baseVertex = offset;
cmd->baseInstance = 1;
skip += (mNodeList[u]->mIndicesCount * sizeof(unsigned int));
offset += (mNodeList[u]->mVertexCount / sizeof(unsigned int));
}
Does any1 see any errors here? I'm lost.
Also tried this :
skip += (mNodeList[u]->mIndicesCount / sizeof(unsigned int));
offset += (mNodeList[u]->mVertexCount);
based on > OpenGL glMultiDrawElementsIndirect with Interleaved Buffers
EDIT 2
I could not get it to work with the suggesions in comments, or I did somethingw rong... here is the main code responsible for building the buffers & commands.
PS. this exercise is about trying to follow AZDO -
https://github.com/nvMcJohn/apitest/blob/master/src/solutions/untexturedobjects/gl/bufferstorage.cpp
int jobSize = mNodeList.size();
QVector<QVector3D> mVertex;
QVector<QVector3D> mNormals;
QVector<unsigned int> mIndices;
for (auto &node:mNodeList) {
mVertex.append(node->mVertex);
mNormals.append(node->mVertexNormal);
mIndices.append(node->mIndices);
}
glBindVertexArray(m_varray);
glBindBuffer(GL_ARRAY_BUFFER, m_vb);
glBufferData(GL_ARRAY_BUFFER, mVertex.size() * sizeof(QVector3D), &mVertex[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ib);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndices.size() * sizeof(unsigned int), &mIndices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
mShader->enableAttributeArray("In_v3Pos");
mShader->setAttributeBuffer("In_v3Pos", GL_FLOAT, 0, 3, sizeof(QVector3D));
glBindBuffer(GL_ARRAY_BUFFER, m_vn);
glBufferData(GL_ARRAY_BUFFER, mNormals.size() * sizeof(QVector3D), &mNormals[0], GL_STATIC_DRAW);
mShader->enableAttributeArray("In_v3Color");
mShader->setAttributeBuffer("In_v3Color", GL_FLOAT, 0, 3, sizeof(QVector3D));
const GLbitfield mapFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT;
const GLbitfield createFlags = mapFlags | GL_DYNAMIC_STORAGE_BIT;
mCommands.Destroy();
mCommands.Create(BufferStorage::PersistentlyMappedBuffer, GL_DRAW_INDIRECT_BUFFER, 3 * jobSize, createFlags, mapFlags);
mTransformBuffer.Destroy();
mTransformBuffer.Create(BufferStorage::PersistentlyMappedBuffer, GL_SHADER_STORAGE_BUFFER, 3 * jobSize, createFlags, mapFlags);
glBindVertexArray(0);
DrawElementsIndirectCommand *dstCmds = mCommands.Reserve(jobSize);
int skip = 0;
int offset = 0;
for (size_t u = 0; u < jobSize; ++u) {
DrawElementsIndirectCommand *cmd = &dstCmds[u];
cmd->count = mNodeList[u]->mIndicesCount;
cmd->instanceCount = 1;
cmd->firstIndex = skip*sizeof(unsigned int);
cmd->baseVertex = offset;
cmd->baseInstance = 0;
skip += mNodeList[u]->mIndicesCount ;
offset += mNodeList[u]->mVertexCount;
}

Related

OpenGL VBO Indexing ( How to compute Index Array)

We are migrating OpenGL to newer version ( ES 2.0 ). Application actually renders Vector images ( i.e CGM files). I have successfully rendered the graphics using vertices using VBO. But the problem is performance. DisplayList performance is way better than VBO. So I am thinking using VBO indexing.
How to come up the indices array ? Will Indexing improve performance?
Please find my code below
//This is my data structure
struct DisplayIndexID {
int idx;
DrawStateT drawState;
//Every display Index ID has its own draw models.
std::vector<std::unique_ptr<vertexModel>> readytoDrawModels;
};
//Initializing the VBO
void initVbo(std::vector<DisplayIndexID> & v)
{
glBindVertexArray(geomVAO);
glBindBuffer(GL_ARRAY_BUFFER, geomVBO);
std::vector<QVector3D> vecToDraw;
std::vector<QVector3D> finalVecToDraw;
for (int j = 0; j < v.size(); j++)
for (auto& vModel : v[j].readytoDrawModels)
{
if (vModel) {
vecToDraw = vModel->getVertices();
finalVecToDraw.insert(finalVecToDraw.end(), vecToDraw.begin(), vecToDraw.end());
}
}
glBufferData(GL_ARRAY_BUFFER, sizeof(QVector3D) * finalVecToDraw.size(), &finalVecToDraw[0],GL_STATIC_DRAW );
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
//Rendering function
void drawDisplayLists(std::vector<DisplayIndexID> & v)
{
GLintptr offset = 0;
initVbo(v);
for (int i = 0; i < v.size(); i++)
{
//***********PRINT AREA***********************/
for (auto& vModel : v[i].readytoDrawModels)
{
glBindBuffer(GL_ARRAY_BUFFER, geomVBO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(QVector3D), (GLvoid*)offset);
switch (vModel->getDrawMode())
{
case 0: //GL_POINTS
glDrawArrays(GL_POINTS, 0, vModel->getVertices().size());
break;
case 1: //GL_LINES
glDrawArrays(GL_LINES, 0, vModel->getVertices().size());
break;
case 3: // GL_TRIANGLE
...
}
offset += sizeof(QVector3D) * vModel->getVertices().size();
}
}
I never worked with vector graphics but this is just on how to create indices from some vertices. So if I read your code right, your vertices are stored in the finalVecToDraw vector. First create a vector for the indices, the supported types are unsigned char up to unsigned int.
Then resize that vector to the size of your vertex array (this will save you much time resizing the vector).
Fill the vector, so that the element at index n has the value n. So
for example with this code:
for(int i = 0; i < indices.size(); i++) {
indices[i] = i;
}
This will do what you already do, but using indices.
Now we need to remove the duplicate entries in the vertices vector and adjust the indices. I don't know what algorithm would be the best to find duplicates for your case, but you need to do this.
The duplicate is at the index d and the first time this value showed up was at o. d must be bigger than o:
Delete the vertex at d.
Iterate over your indices and if an element has a value bigger than d, subtract one from it.
Set the value of the index at d to o.

Multiple quads in one vbo

I am working on a minecraft-ish game, and I've been working a little more with vbos. However; when drawing multiple faces in a single vbo I seem to have a little bit of a issue.
Here is my vbo-generation code:
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, verts);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, verts * 9 * sizeof(GLfloat), NULL, GL_STATIC_DRAW);
void* ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
GLfloat*model = (GLfloat*)ptr;
GLfloat*tex = ((GLfloat*)ptr) + verts * 6;
GLfloat*color = ((GLfloat*)ptr) + verts * 3;
int p = 0;
int k = p * 3;
for (int mcy = 0; mcy < 5; mcy++) {
for (int mcx = 0; mcx < 5; mcx++) {
double addonX = mcx*32.0;
double addonY = mcy*32.0;
int addonx = mcx * 32;
int addony = mcy * 32;
if (!(hill.get(addonX, addonY)*400.0 > 100 && hill.get(32 + addonX, addonY)*400.0 > 100 && hill.get(addonX, 32 + addonY)*400.0 > 100 && hill.get(32 + addonX, 32 + addonY)*400.0 > 100)) {
draw = true;
int biome1 = BiomeToColor(GetBiome(x, y, addonX, addonY), hill.get(addonX, addonY)*400.0);
int biome2 = BiomeToColor(GetBiome(x, y, 32 + addonX, addonY), hill.get(32 + addonX, addonY)*400.0);
int biome3 = BiomeToColor(GetBiome(x, y, addonX, 32 + addonY), hill.get(addonX, 32 + addonY)*400.0);
int biome4 = BiomeToColor(GetBiome(x, y, 32 + addonX, 32 + addonY), hill.get(32 + addonY, 32 + addonY)*400.0);
model[k] = addonx+ 32;
model[k + 1] = addony;
model[k + 2] = hill.get(addonX + 32, addonY)*400.0;
color[k] = BiomeColors[biome2].r;
color[k + 1] = BiomeColors[biome2].g;
color[k + 2] = BiomeColors[biome2].b;
p++;
k = p * 3;
model[k] = addonx + 32;
model[k + 1] = addony + 32;
model[k + 2] = hill.get(addonX + 32, addonY + 32)*400.0;
color[k] = BiomeColors[biome4].r;
color[k + 1] = BiomeColors[biome4].g;
color[k + 2] = BiomeColors[biome4].b;
p++;
k = p * 3;
model[k] = addonx;
model[k + 1] = addony + 32;
model[k + 2] = hill.get(addonX, addonY + 32)*400.0;
color[k] = BiomeColors[biome3].r;
color[k + 1] = BiomeColors[biome3].g;
color[k + 2] = BiomeColors[biome3].b;
p++;
k = p * 3;
model[k] = addony;
model[k + 1] = addony;
model[k + 2] = hill.get(addonX, addonY)*400.0;
color[k] = BiomeColors[biome1].r;
color[k + 1] = BiomeColors[biome1].g;
color[k + 2] = BiomeColors[biome1].b;
p++;
k = p * 3;
}
}
}
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
And here's the code I use to draw the vbo:
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexPointer(3, GL_FLOAT, 0, 0);
glTexCoordPointer(3, GL_FLOAT, 0, (char*)NULL + verts * 6 * sizeof(GLfloat));
glColorPointer(3, GL_FLOAT, 0, (char*)NULL + verts * 3 * sizeof(GLfloat));
glDrawArrays(GL_QUADS, 0, VBO);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Here's the result I want (using a single quad in every vbo):
unfortunatly I'm still new so you have to click this link :/
And here is the result I get with multiple quads in every vbo:
image
So why do I want to draw multiple quads in a single vbo?
One word: performance, if you compare the two images the thing that really pops out (well, except for the bug with the second image) is the framerate counter. I want to make this game into a big thing, so every fps matters to me.
EDIT:
Omg, I'm so stupid:
model[k] = addony;
A very simple mistake, but so devistating.
Just proves how so small things can brake the game.
It all workes now.
glDrawArrays(GL_QUADS, 0, VBO);
There are a few problems with this call:
the third parameter of glDrawArrays is the count of the things you are drawing so what you are actually saying is:
Draw Quads from my Buffer at 0 until VBO and then stop.
What you should be saying is:
Draw Quads from my Buffer at 0 until Buffer Length and then stop
so now it looks like this:
glDrawArrays(GL_QUADS, 0, verts);
'VBO' in your code is the ID of the Buffer that you want to use.
think about it like a pointer who's number you know or rather a user with an ID.
GL_QUADS is not good use GL_TRIANGLES there are many problems with GL_QUADS later especialy on mobile phones and on other platforms making your data in triangles is much much nicer.
You shouldn't be drawing in GL_QUADS for multiple reasons
Why are you not using VAO's? Are you using an older version of OpenGL that doesn't have VAO's? Otherwise I would suggest using VAO here instead of VBO so you dont need to bind pointers for each draw call.
glBindBuffer(GL_ARRAY_BUFFER, verts);
What you are trying to here is bind a VBO of id: 'verts' to be our current VBO.
'So why do I want to draw multiple quads in a single vbo? One word: performance'
Have you tried to draw multiple quads using instancing?
So sending a model matrix for each of the shapes so that you modify their positions and shapes in the shader and not in the buffer. This way you can draw one vbo over and over again just slightly transformed with a single draw call.
Here is a good tutorial on instancing:
http://learnopengl.com/#!Advanced-OpenGL/Instancing
Just out of curiosity but why did you decide to use:
glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
instead of buffering your data in the glBufferData call?
If you need to buffer the data later you can use glBufferSubData
Honestly though I think your performance problems stem from a range of factors.
I would personally use glBufferData instead of map data and when I need to do it during run time and not during loading I would use glBufferSubData.
I would upload the colors to the shader and draw multiples of the SAME VBO again and again with a different model matrix and colors allowing me to instance it.
However you shouldn't need to do that.
What I would recommend is making up the data in triangles and colors and drawing the whole ground as a mesh which you have seemed to tried to do. Your problem was most likely caused by glDrawArrays length being set to that of a VBO.
However in this case I would build a VBO using glBufferData with the size of a chunk then I would use glBufferSubData for each of the quads with colors etc. and once I am done I would draw that multiple times alongside different chunks.
I think it would be of use to you to do more theory of OpenGL.

CImg Image is Colorless

Currently I am in the process of refining a function in my basic level editor program that allows me to save the maps I create. It spits out a .bmp image of the map produced. It does this through a library I've just discovered called CImg, which I know next to nothing about. Everything seems to work, but the resulting .bmp image is not colored, appearing instead in different shades of black and white. Like I said, I know basically nothing about the library, so if you know what the problem could be here, I would appreciate some help.
Here's the save function:
void Map::Save() {
Vertex top_left_most, top_right_most, bottom_left_most;
int img_w = 0, img_h = 0;
std::vector<std::pair<GLuint, GLuint>>::iterator tl = bufferIDs.begin(); //This little block gives the _most variables valid starting vals
glBindBuffer(GL_ARRAY_BUFFER, tl->second);
glGetBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureCoord), sizeof(Vertex), &top_left_most);
top_right_most = bottom_left_most = top_left_most;
for (auto i = bufferIDs.begin(); i != bufferIDs.end(); ++i) { //SEEKS TOP LEFT MOST TILE ON MAP
Vertex current_coord;
glBindBuffer(GL_ARRAY_BUFFER, i->second);
glGetBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureCoord), sizeof(Vertex), &current_coord);
if ((current_coord.x < top_left_most.x && current_coord.y < top_left_most.y) ||
(current_coord.x == top_left_most.x && current_coord.y < top_left_most.y) ||
(current_coord.x < top_left_most.x && current_coord.y == top_left_most.y)) {
top_left_most = current_coord;
}
}
for (auto i = bufferIDs.begin(); i != bufferIDs.end(); ++i) { //SEEKS TOP RIGHT MOST TILE ON MAP
Vertex current_coord;
glBindBuffer(GL_ARRAY_BUFFER, i->second);
glGetBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureCoord), sizeof(Vertex), &current_coord);
if ((current_coord.x > top_right_most.x && current_coord.y < top_right_most.y) ||
(current_coord.x == top_right_most.x && current_coord.y < top_right_most.y) ||
(current_coord.x > top_right_most.x && current_coord.y == top_right_most.y)) {
top_right_most = current_coord;
}
}
for (auto i = bufferIDs.begin(); i != bufferIDs.end(); ++i) { //SEEKS BOTTOM LEFT MOST TILE ON MAP
Vertex current_coord;
glBindBuffer(GL_ARRAY_BUFFER, i->second);
glGetBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureCoord), sizeof(Vertex), &current_coord);
if ((current_coord.x < bottom_left_most.x && current_coord.y > bottom_left_most.y) ||
(current_coord.x == bottom_left_most.x && current_coord.y > bottom_left_most.y) ||
(current_coord.x < bottom_left_most.x && current_coord.y == bottom_left_most.y)) {
bottom_left_most = current_coord;
}
}
img_w = (top_right_most.x + 64) - top_left_most.x; //Calculating image dimensions for the buffer
img_h = (bottom_left_most.y + 64) - top_left_most.y;
GLuint *image = new GLuint[img_w * img_h]; //Creating the image buffer
int int_start_x = 0; //start_x and y that will be used in buffer pointer positioning computations
int int_start_y = 0;
//these nested fors fill the buffer
for (GLfloat start_y = top_left_most.y; start_y != bottom_left_most.y + 64; start_y += 64) {
for (GLfloat start_x = top_left_most.x; start_x != top_right_most.x + 64; start_x += 64) {
bool in_map = false;
std::vector<std::pair<GLuint, GLuint>>::iterator valid_tile;
for (auto i = bufferIDs.begin(); i != bufferIDs.end(); ++i) { //This for checks to see if tile corresponding to start_x & y is present in map
Vertex current_tile_pos;
glBindBuffer(GL_ARRAY_BUFFER, i->second);
glGetBufferSubData(GL_ARRAY_BUFFER, sizeof(TextureCoord), sizeof(Vertex), &current_tile_pos);
if (current_tile_pos.x == start_x && current_tile_pos.y == start_y) {
in_map = true;
valid_tile = i;
break;
}
}
GLuint *imagepos = image; //Repositioning the pointer into the final image's buffer
imagepos += int_start_x + (int_start_y * img_w);
if (in_map) { //if in map, that tile's texture is used to fill the corresponding part of the image buffer
GLuint *texture = new GLuint[64 * 64];
glBindTexture(GL_TEXTURE_2D, valid_tile->first);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture);
GLuint *texturepos = texture;
for (GLuint ypos = 0; ypos != 64; ++ypos) {
std::memcpy(imagepos, texturepos, 64 * 4);
texturepos += 64;
imagepos += img_w;
}
if (texture)
delete[] texture;
}
else { //otherwise, a default all-black array is used to fill the corresponding untiled part of the image buffer
GLuint *black_buffer = new GLuint[64 * 64];
GLuint *blackpos = black_buffer;
GLuint solid_black;
char *p = (char *)&solid_black;
p[0] = 0;
p[1] = 0;
p[2] = 0;
p[3] = 255;
for (GLuint i = 0; i != 64 * 64; ++i) {
black_buffer[i] = solid_black;
}
for (GLuint ypos = 0; ypos != 64; ++ypos) {
std::memcpy(imagepos, blackpos, 64 * 4);
blackpos += 64;
imagepos += img_w;
}
if (black_buffer)
delete[] black_buffer;
}
int_start_x += 64;
}
int_start_x = 0;
int_start_y += 64;
}
cimg_library::CImg<GLuint> final_image(image, img_w, img_h); //no color!!
final_image.save_bmp("map.bmp");
if (image)
delete[] image;
}
In case some explanation would be helpful, Vertex is a simple struct of two GLfloats (as is TextureCoord), bufferIDs is an std::vector of std::pairs of GLuints, the first representing a texture ID, and the second representing a VBO ID.
Here are the requested sample images:
what the image should look like (this is in monochrome)
Same exact image as above, but created using the reinterpret_cast method
Your line
cimg_library::CImg<GLuint> final_image(image, img_w, img_h);
is wrong if you are expecting a colour image because that creates a single channel image. You need a 3 at the end to make 3 channels - one for Red, one for Green and one for Blue.
Also, your data is stored in GLuint which means that a 4x2 pixel image will be stored like this, i.e. band-interleaved-by-pixel:
RGBA RGBA RGBA RGBA
RGBA RGBA RGBA RGBA
whereas CImg wants to store that in a band-interleaved-by-plane fashion:
RRRRRRRR
GGGGGGGG
BBBBBBBB
AAAAAAAA
This link explains the layout of CImg memory buffers.

Anyone offer me an example using glMultiDrawArraysIndirect with JOGL?

I learned the method glMultiDrawArraysIndirect() from OpenGL, and I want to use this method call with JOGL. In the sample code, a C++ struct is used and the data in that struct is stored in a buffer by using glMapBufferRange(). I was wondering how it is down with JOGL? It would be great if there is any example.
Here is the sample code using OpenGL:
struct DrawArraysIndirectCommand
{
GLuint count;
GLuint primCount;
GLuint first;
GLuint baseInstance;
};
load_shaders();
object.load("media/objects/asteroids.sbm");
glGenBuffers(1, &indirect_draw_buffer);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, indirect_draw_buffer);
glBufferData(GL_DRAW_INDIRECT_BUFFER,
NUM_DRAWS * sizeof(DrawArraysIndirectCommand),
NULL,
GL_STATIC_DRAW);
DrawArraysIndirectCommand * cmd = (DrawArraysIndirectCommand *)
glMapBufferRange(GL_DRAW_INDIRECT_BUFFER,
0,
NUM_DRAWS * sizeof(DrawArraysIndirectCommand),
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
for (i = 0; i < NUM_DRAWS; i++)
{
object.get_sub_object_info(i % object.get_sub_object_count(),
cmd[i].first,
cmd[i].count);
cmd[i].primCount = 1;
cmd[i].baseInstance = i;
}
glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);
You can see the struct is just 4 gluint one after the other, you will need to imitate that:
ByteBuffer cmd = gl.glMapBufferRange(GL_DRAW_INDIRECT_BUFFER,
0,
NUM_DRAWS * 4 * 4,
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
for (int i = 0; i < NUM_DRAWS; i++)
{
int first = object.get_sub_object_info_first(i % object.get_sub_object_count());
int count = object.get_sub_object_info_count(i % object.get_sub_object_count());
int primCount = 1;
int baseInstance = i;
cmd.putInt(count);
cmd.putInt(primCount);
cmd.putInt(first);
cmd.putInt(basInstance);
}

texture problems with librocket, ogre & ios

We are trying to use librocket http://librocket.com/ together with Ogre http://www.ogre3d.org/. They're both part of gamekit http://code.google.com/p/gamekit/ which I use for this project.
This all works fine together as long as I don't load an image with librocket. As soon as I do that the viewport on the iPad is not fullscreen anymore but small in the lower corner. Like this: http://uploads.undef.ch/machine/ipad.png
I can't make a connection between loading/rendering a texture and resizing of the viewport. And I can't find anything wrong with the RenderInterface. http://uploads.undef.ch/machine/RenderInterfaceOgre3D.cpp
Is there any OpenGLES command that could have an affect on the active viewport size?
This is the relevant code that loads an image and displays it:
// Called by Rocket when a texture is required by the library.
bool RenderInterfaceOgre3D::LoadTexture(Rocket::Core::TextureHandle& texture_handle, Rocket::Core::Vector2i& texture_dimensions, const Rocket::Core::String& source)
{
Ogre::TextureManager* texture_manager = Ogre::TextureManager::getSingletonPtr();
Ogre::TexturePtr ogre_texture = texture_manager->getByName(Ogre::String(source.CString()));
if (ogre_texture.isNull())
{
ogre_texture = texture_manager->load(Ogre::String(source.CString()),
DEFAULT_ROCKET_RESOURCE_GROUP,
Ogre::TEX_TYPE_2D,
0);
}
if (ogre_texture.isNull())
return false;
texture_dimensions.x = ogre_texture->getWidth();
texture_dimensions.y = ogre_texture->getHeight();
texture_handle = reinterpret_cast<Rocket::Core::TextureHandle>(new RocketOgre3DTexture(ogre_texture));
return true;
}
// Called by Rocket when it wants to render geometry that it does not wish to optimise.
void RenderInterfaceOgre3D::RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation)
{
// We've chosen to not support non-compiled geometry in the Ogre3D renderer.
// But if you want, you can uncomment this code, so borders will be shown.
/*
Rocket::Core::CompiledGeometryHandle gh = CompileGeometry(vertices, num_vertices, indices, num_indices, texture);
RenderCompiledGeometry(gh, translation);
ReleaseCompiledGeometry(gh);
*/
}
// Called by Rocket when it wants to compile geometry it believes will be static for the forseeable future.
Rocket::Core::CompiledGeometryHandle RenderInterfaceOgre3D::CompileGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture)
{
RocketOgre3DCompiledGeometry* geometry = new RocketOgre3DCompiledGeometry();
geometry->texture = texture == NULL ? NULL : (RocketOgre3DTexture*) texture;
geometry->render_operation.vertexData = new Ogre::VertexData();
geometry->render_operation.vertexData->vertexStart = 0;
geometry->render_operation.vertexData->vertexCount = num_vertices;
geometry->render_operation.indexData = new Ogre::IndexData();
geometry->render_operation.indexData->indexStart = 0;
geometry->render_operation.indexData->indexCount = num_indices;
geometry->render_operation.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
// Set up the vertex declaration.
Ogre::VertexDeclaration* vertex_declaration = geometry->render_operation.vertexData->vertexDeclaration;
size_t element_offset = 0;
vertex_declaration->addElement(0, element_offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
element_offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
vertex_declaration->addElement(0, element_offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE);
element_offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR);
vertex_declaration->addElement(0, element_offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES);
#if GK_PLATFORM == GK_PLATFORM_APPLE_IOS
// Create the vertex buffer.
Ogre::HardwareVertexBufferSharedPtr vertex_buffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertex_declaration->getVertexSize(0), num_vertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE,true);
geometry->render_operation.vertexData->vertexBufferBinding->setBinding(0, vertex_buffer);
// Fill the vertex buffer.
RocketOgre3DVertex* ogre_vertices = (RocketOgre3DVertex*) vertex_buffer->lock(0, vertex_buffer->getSizeInBytes(), Ogre::HardwareBuffer::HBL_DISCARD);
#else
Ogre::HardwareVertexBufferSharedPtr vertex_buffer = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertex_declaration->getVertexSize(0), num_vertices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
geometry->render_operation.vertexData->vertexBufferBinding->setBinding(0, vertex_buffer);
// Fill the vertex buffer.
RocketOgre3DVertex* ogre_vertices = (RocketOgre3DVertex*) vertex_buffer->lock(0, vertex_buffer->getSizeInBytes(), Ogre::HardwareBuffer::HBL_NORMAL);
#endif
for (int i = 0; i < num_vertices; ++i)
{
ogre_vertices[i].x = vertices[i].position.x;
ogre_vertices[i].y = vertices[i].position.y;
ogre_vertices[i].z = 0;
Ogre::ColourValue diffuse(vertices[i].colour.red / 255.0f, vertices[i].colour.green / 255.0f, vertices[i].colour.blue / 255.0f, vertices[i].colour.alpha / 255.0f);
render_system->convertColourValue(diffuse, &ogre_vertices[i].diffuse);
ogre_vertices[i].u = vertices[i].tex_coord[0];
ogre_vertices[i].v = vertices[i].tex_coord[1];
}
vertex_buffer->unlock();
#if GK_PLATFORM == GK_PLATFORM_APPLE_IOS
// Create the index buffer.
Ogre::HardwareIndexBufferSharedPtr index_buffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, num_indices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
geometry->render_operation.indexData->indexBuffer = index_buffer;
geometry->render_operation.useIndexes = true;
#else
Ogre::HardwareIndexBufferSharedPtr index_buffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_32BIT, num_indices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
geometry->render_operation.indexData->indexBuffer = index_buffer;
geometry->render_operation.useIndexes = true;
#endif
// Fill the index buffer.
unsigned short * ogre_indices = (unsigned short*)index_buffer->lock(0, index_buffer->getSizeInBytes(), Ogre::HardwareBuffer::HBL_NORMAL);
#if GK_PLATFORM == GK_PLATFORM_APPLE_IOS
//unsigned short short_indices[num_indices];
for(int i=0;i<num_indices;i++)
ogre_indices[i] = indices[i];
//memcpy(ogre_indices, short_indices, sizeof(unsigned short) * num_indices);
#else
memcpy(ogre_indices, indices, sizeof(unsigned int) * num_indices);
#endif
index_buffer->unlock();
return reinterpret_cast<Rocket::Core::CompiledGeometryHandle>(geometry);
}
// Called by Rocket when it wants to render application-compiled geometry.
void RenderInterfaceOgre3D::RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry, const Rocket::Core::Vector2f& translation)
{
Ogre::Matrix4 transform;
transform.makeTrans(translation.x, translation.y, 0);
render_system->_setWorldMatrix(transform);
render_system = Ogre::Root::getSingleton().getRenderSystem();
RocketOgre3DCompiledGeometry* ogre3d_geometry = (RocketOgre3DCompiledGeometry*) geometry;
if (ogre3d_geometry->texture != NULL)
{
render_system->_setTexture(0, true, ogre3d_geometry->texture->texture);
// Ogre can change the blending modes when textures are disabled - so in case the last render had no texture,
// we need to re-specify them.
render_system->_setTextureBlendMode(0, colour_blend_mode);
render_system->_setTextureBlendMode(0, alpha_blend_mode);
}
else
render_system->_disableTextureUnit(0);
render_system->_render(ogre3d_geometry->render_operation);
}