Hello I have a question with Irrlicht library
I want to do a map with a floor I use createHillPlaneMesh.
I'm actually learning Irrlicht, I actually have a camera and cubes.
here is when I launch it :
while (_device.get_device()->run()) {
_device.get_driver()->beginScene(true, true, color);
_scene.get_sceneManager()->drawAll();
_device.get_driver()->endScene();
}
I call addMapBlock and its work great :
void Eo::Scene::addMapBlock(irr::f32 x, irr::f32 y, irr::f32 z)
{
irr::f32 unitSize = 10.0f;
irr::core::vector3df pos;
pos.X = x;
pos.Y = y;
pos.Z = z;
irr::scene::IMeshSceneNode *cube = _sceneManager->addCubeSceneNode(
unitSize, nullptr, -1, pos);
cube->setMaterialFlag(irr::video::EMF_LIGHTING, false);
cube->setMaterialTexture(0,
_device.get_driver()->getTexture("../assets/img/texture.jpg"));
_map.push(cube);
}
and here is when I create the floor but nothing happen :
void Eo::Scene::addMapFloor()
{
irr::core::dimension2d<irr::f32> tileSize(100.0,100.0);
irr::core::dimension2d<irr::u32> tileCount(50,50);
auto material = new irr::video::SMaterial();
irr::f32 hillHeight = 0;
irr::core::dimension2d<irr::f32> countHills(20.0,20.0);
irr::core::dimension2d<irr::f32> textureRepeatCount(1.0,1.0);
irr::scene::IMesh *cube =
_sceneManager->getGeometryCreator()->createHillPlaneMesh(
tileSize,
tileCount,
material,
hillHeight,
countHills,
textureRepeatCount);
material->ColorMaterial = irr::video::E_COLOR_PLANE::ECP_BLUE;
cube->setMaterialFlag(irr::video::EMF_WIREFRAME, true);
}
Might be I miss something but I try to read and replicate the documentation.
When you do:
_sceneManager->getGeometryCreator()->createHillPlaneMesh(/* args */);
You just create a mesh (the geometric description of an object). You then have to create a scene node to display your mesh somewhere in your scene:
IMesh* mesh = _sceneManager->getGeometryCreator()->createHillPlaneMesh(/* args */);
IMeshSceneNode* node = _sceneManager->addMeshSceneNode(mesh /*, optional args*/);
// Once you don't need the mesh variable anymore, drop it.
mesh->drop();
Side note: It's extremely easy to forget to drop something (especially if parts of the code can throw exceptions), resulting in memory leaks. I advise that you wrap these pointers in some sort of smart pointer (here std::unique_ptr with a custom Deleter, for example).
Related
I am trying to display a point cloud, consisting of vertices and color with OSG. A static point cloud to display is rather easy with this guide.
But I am not capable of updating such a point cloud. My intention is to create a geometry and attach it to my viewer class once.
This is the mentioned method which is called once in the beginning.
The OSGWidget strongly depends on this OpenGLWidget based approach.
void OSGWidget::attachGeometry(osg::ref_ptr<osg::Geometry> geom)
{
osg::Geode* geode = new osg::Geode;
geom->setDataVariance(osg::Object::DYNAMIC);
geom->setUseDisplayList(false);
geom->setUseVertexBufferObjects(true);
bool addDrawSuccess = geode->addDrawable(geom.get()); // Adding Drawable Shape to the geometry node
if (!addDrawSuccess)
{
throw "Adding Drawable failed!";
}
{
osg::StateSet* stateSet = geode->getOrCreateStateSet();
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
}
float aspectRatio = static_cast<float>(this->width()) / static_cast<float>(this->height());
// Setting up the camera
osg::Camera* camera = new osg::Camera;
camera->setViewport(0, 0, this->width(), this->height());
camera->setClearColor(osg::Vec4(0.f, 0.f, 0.f, 1.f)); // Kind of Backgroundcolor, clears the buffer and sets the default color (RGBA)
camera->setProjectionMatrixAsPerspective(30.f, aspectRatio, 1.f, 1000.f); // Create perspective projection
camera->setGraphicsContext(graphicsWindow_); // embed
osgViewer::View* view = new osgViewer::View;
view->setCamera(camera); // Set the defined camera
view->setSceneData(geode); // Set the geometry
view->addEventHandler(new osgViewer::StatsHandler);
osgGA::TrackballManipulator* manipulator = new osgGA::TrackballManipulator;
manipulator->setAllowThrow(false);
view->setCameraManipulator(manipulator);
///////////////////////////////////////////////////
// Set the viewer
//////////////////////////////////////////////////
viewer_->addView(view);
viewer_->setThreadingModel(osgViewer::CompositeViewer::SingleThreaded);
viewer_->realize();
this->setFocusPolicy(Qt::StrongFocus);
this->setMinimumSize(100, 100);
this->setMouseTracking(true);
}
After I have 'attached' the geometry, I am trying to update the geometry like this
void PointCloudViewOSG::processData(DepthDataSet depthData)
{
if (depthData.points()->empty())
{
return; // empty cloud, cannot do anything
}
const DepthDataSet::IndexPtr::element_type& index = *depthData.index();
const size_t nPixel = depthData.points().get()->points.size();
if (depthData.intensity().isValid() && !index.empty() )
{
for (int i = 0; i < nPixel; i++)
{
float x = depthData.points().get()->points[i].x;
float y = depthData.points().get()->points[i].y;
float z = depthData.points().get()->points[i].z;
m_vertices->push_back(osg::Vec3(x
, y
, z));
// 32 bit integer variable containing the rgb (8 bit per channel) value
uint32_t rgb_val_;
memcpy(&rgb_val_, &(depthData.points().get()->points[i].rgb), sizeof(uint32_t));
uint32_t red, green, blue;
blue = rgb_val_ & 0x000000ff;
rgb_val_ = rgb_val_ >> 8;
green = rgb_val_ & 0x000000ff;
rgb_val_ = rgb_val_ >> 8;
red = rgb_val_ & 0x000000ff;
m_colors->push_back(
osg::Vec4f((float)red / 255.0f,
(float)green / 255.0f,
(float)blue / 255.0f,
1.0f)
);
}
m_geometry->setVertexArray(m_vertices.get());
m_geometry->setColorArray(m_colors.get());
m_geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
m_geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, m_vertices->size()));
}
}
My guess is that the
addPrimitiveSet(...)
Shall not be called every time I update the geometry.
Or can it be the attachment of the geometry, so that I have to reattach it every time?
PointCloudlibrary (PCL) is unfortunately not an alternative since of some incompatibilities with my application.
Update: When I am reattaching the geometry to the OSGWidget class,
calling
this->attachGeometry(m_geometry)
after
m_geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, m_vertices->size()));
I get my point cloud visible, but this procedure is definitely wrong since I am losing way too much performance and the display driver crashes.
You need to set the array and add the primitive set only once, after that you can update the vertices like this:
osg::Vec3Array* vx = static_cast<osg::Vec3Array*>(m_vertices);
for (int i = 0; i < nPixel; i++)
{
float x, y, z;
// fill with your data...
(*vx)[i].set(x, y, z);
}
m_vertices->dirty();
The same goes for colors and other arrays.
As you're using VBO, you don't need to call dirtyDisplayList()
If you need instead to recompure the bounding box of the geometry, call
m_geometry->dirtyBound()
In case the number of points changes between updates, you can push new vertices into the array if its size is too small, and update the PrimitiveSet count like this:
osg::DrawArrays* drawArrays = static_cast<osg::DrawArrays*>(m_geometry->getPrimitiveSet(0));
drawArrays->setCount(nPixel);
drawArrays->dirty();
rickvikings solution works - I only had one issue... (OSG 3.6.1 on OSX)
I had to modify the m_vertices array directly, it would cause OSG to crash if I used the static_cast method above to modify the vertices array:
osg::Vec3Array* vx = static_cast(m_vertices);
For some reason OSG would not create a buffer object in the vertices array class if using the static_cast approach.
I am really new to OpenGL and I am trying to just make a surface from two triangles. I don't know where I am going wrong with this code. I know that all the positions and colors are getting into the triangles class and that the Triangles are being made, but it's not getting outputted. Can someone help?
I tried to get just the output from the Triangle class but it doesn't seem to be working. I don't think there's anything wrong with the way I am calling the Display function.
Code:
#include<GL/gl.h>
#include<GL/glu.h>
#include<GL/glut.h>
#include<iostream>
#include<vector>
using namespace std;
class Triangle
{
public:
float position[9],color[3];
Triangle()
{}
Triangle(float position_t[], float color_t[])
{
for(int i=0;i<9;i++)
{position[i] = position_t[i];}
for(int i=0;i<3;i++)
{color[i]= color_t[i];}
}
void makeTriangle()
{
glBegin(GL_TRIANGLES);
glColor3f(color[0],color[1],color[2]);glVertex3f(position[0],position[1],position[2]);
glColor3f(color[0],color[1],color[2]);glVertex3f(position[3],position[4],position[5]);
glColor3f(color[0],color[1],color[2]);glVertex3f(position[6],position[7],position[8]);
glEnd();}
};
class Mesh
{
public:
/*float center[3],position[9],color[3];
float size;*/
vector<Triangle> elements;
float center[3],position[9],color[3];
float size;
Mesh(){}
Mesh(float center_in[3], float color_in[3])
{
for (int i=0;i<3;i++)
{
color[i] = color_in[i];
center[i] = center_in[i];
}
}
void getPositions()
{
position[0] = 1;position[1] = 1; position[2] = 1;
position[3] = -1;position[4] = -1; position[5] = 1;
position[6] = 1;position[7] = -1; position[8] = 1;
}
void getColor()
{
color[0] = 1; color[1]=0; color[2]=0;
}
static Mesh makeMesh()
{
Mesh a;
a.elements.resize(2);
a.getPositions();
a.getColor();
Triangle T(a.position,a.color);
a.elements[0] = T;
//Triangle O(2);
//a.elements[1] = 0;
return a;
}
};
void render()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
Mesh a;
a.elements.resize(2);
a.getPositions();
a.getColor();
Triangle T(a.position,a.color);
//vector<Mesh> m;
//m.push_back(Mesh::makeMesh());
glPushMatrix();
T.makeTriangle();
glPopMatrix();
glFlush();
glutSwapBuffers();
glutPostRedisplay();
}
Full Code: http://pastebin.com/xa3B7166
As I suggested you in the comments, you are not setting the gluLookat() function. Everything is being drawn but you are just not looking at it!
Docs: https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
Your code does not specify any transformations. Therefore, your coordinates need to be within the default view volume, which is [-1, 1] in all coordinate directions.
Or more technically, the model/view/projection transformations (or all the transformations applied in your vertex shader if you use the programmable pipeline) transform the coordinates into the clip coordinate space, and after perspective division into the normalized device coordinate (aka NDC) space. The range of the NDC space is [-1, 1] for all coordinates.
If you don't apply any transformations, like is the case in your code, your original coordinates already have to be in NDC space.
With your current coordinates:
position[0] = 1;position[1] = 1; position[2] = 1;
position[3] = -1;position[4] = -1; position[5] = 1;
position[6] = 1;position[7] = -1; position[8] = 1;
all the z-coordinates have values of 1, which means that the whole triangle is right on the boundary of the clip volume. To make it visible, you can simply set the z-coordinates to 0:
position[0] = 1;position[1] = 1; position[2] = 0;
position[3] = -1;position[4] = -1; position[5] = 0;
position[6] = 1;position[7] = -1; position[8] = 0;
This centers it within the NDC space in z-direction, with the vertices being on 3 of the corners in the xy-plane. You will therefore see half of your window covered by the triangle, cutting it in half along the diagonal.
It's of course common in OpenGL to have the original coordinates in a different coordinate space, and then apply transformations to place them within the view volume.
You're probably already aware of this, but I thought I'd mention it anyway: If you're just starting to learn OpenGL, I would suggest that you learn what people often call "modern OpenGL". This includes the OpenGL Core Profile, or OpenGL ES 2.0 or later. The calls you are using now are mostly deprecated in newer versions of OpenGL, and not available anymore in the Core Profile and ES. The initial hurdle is somewhat higher for "modern OpenGL", particularly since you have to write your own shaders, but you will get on the path to acquiring knowledge that is still current.
I would like to know if there's such a very basic method to know where exactly the translated object is in 2D space. I would like to clarify my thoughts regarding OpenGL matrices.
Please have a time to take a look at this very few code examples:
class Rectangle
{
public:
//this function does amazing magic!
//..so continue reading
void draw();
inline bool contains(int x, int y) const {
return x >= this->x && x <= this->x + width &&
y >= this->y && y <= this->y + height;
}
int x;
int y;
uint32_t width;
uint32_t height;
protected:
std::vector<Rectangle *> children;
}
solution #1
void Rectangle::draw()
{
glPushMatrix();
glTranslatef(x, y, 0);
...
//popped out the previous matrix so I have a fresh one
glPopMatrix();
//outside the matrix of parent
//not logical (?)
for (auto &i : children)
{
i->draw();
}
}
solution #2
void Rectangle::draw()
{
glPushMatrix();
glTranslatef(x, y, 0);
...
//inside the matrix of parent
//good! the origin now is parent's coordinate.
for (auto &i : children)
{
//previous matrix is not popped out so the origin is parent's (x,y)
i->draw();
}
glPopMatrix();
}
In solution #1, it is simple and very easy to locate the coordinates of each Rectangle::children, however, its quite hard to manage the code and its not an obvious choice for me because those Rectangle::children's origin position must be their parent container, right?
On the other hand, I much preferred the solution #2 and it is an obvious choice because, for every children I will create, their origin will be the parent's location. But, it's very hard for me to manage those Rectangle::children's coordinates. For example, I want to have a hover effect applied on certain Rectangle::children, I would do in implementation #1 as simple as this:
solution #1
for (auto &i : children)
{
if (i->contains(mouse().x, mouse().y)
{
//hover effect!
}
}
solution #2
for (auto &i : children)
{
if (i->contains(mouse().x - this->x,
mouse().y - this->y)
{
//hover effect!
}
}
The main problem I'm really concern of is that I want to have a fixed function in the Rectangle class like isHovering() this will accept 0 number of parameters and I want it be a cv-qualified. What this will do is: will check that the mouse cursor is inside the rectangle.
I think I would mess up the code for this function if I implement the solution #2 here. What do you think? Is there any nice way algorithm existing there I didn't know yet? I would like to ask first before I proceed along way.
Or...there's an existing magic way to implement in the drawing function to be able to achieve this?
Thanks for reading!
Update
Suppose the drawing hierarchy I want to achieve is something like this:
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
//one matrix for every parent-rectangle and its child-rectangle component
xPushMatrix();
//parent
glTranslatef(parent.x, parent.y, 0);
glDrawables();
//children
glTranslatef(child.x, child.y, 0);
glDrawables();
...to N child
xPopMatrix();
xSwapBuffers(window);
xPollEvents();
The problem: What is the right(efficient, clean code) way to find the coordinates of Rectangle::children ?
Hope you get what I mean.
i am drawing an array of pool balls in opengl using c++
the problem i am facing is the array draws in a straight line.
when i use gltranslate the balls still only translate along the line when i edit the z and y axis
what i want to do is set the balls up in a triangle shape like the breaking of a pool match
how do i use the array code to set the balls up like this?
any help would be much appreciated
balls[7];
for (int x = ball-start; x<ball-end;x++)
{
glTranslatef(0,0,0.5);
glColor3f(1,0,0);
ball[x].drawball();
}
assuming:
struct Ball {
double x,y,z;
void drawball(void);
/* ... */
} ball[7];
try:
for(int i=0; i<7 ;i++)
{
glPushMatrix();
glTranslated(ball[i].x,ball[i].y,ball[i].z);
glColor3f(1,0,0);
ball[i].drawball();
glPopMatrix();
}
details probably vary, but hopefully you get the idea.
Do something like this:
// first of all, include the x,y position (assuming 2D, since pool) in the Ball object:
class Ball
{
//...
private:
float xpos, ypos;
//...
};
Then when you construct the array of balls, rather than just making 8 balls, you're going to want to allocate the memory on the heap so that it will last throughout your entire game. So do this:
Ball *ball= new Ball*[8];
ball[0] = new Ball(x0,y0);
ball[1] = new Ball(x1,y1);
ball[2] = new Ball(x2,y2);
ball[3] = new Ball(x3,y3);
// ...
Make sure that when your game is over, you clean up after yourself.
for (int i = 0; i < 8; i++)
delete ball[i];
delete [] ball;
Then in your Ball::draw() do something like this:
Ball::draw()
{
glColor3f(/*yellow*/); // Set the color to yellow
glTranslatef(-xpos, -ypos, 0); // Move to the position of the ball
// Draw the ball
glTranslatef(xpos, ypos, 0); // Move back to the default position
}
All you have to do is come up with the correct (x0,y0),(x1,y1),(x2,y2)... to form a triangle! Does this make sense/answer your question?
I'm a openFrameworks newbie. I am learning basic 2d drawing which is all great so far. I have drawn a circle using:
ofSetColor(0x333333);
ofFill;
ofCircle(100,650,50);
My question is how do I give the circle a variable name so that I can manipulate in the mousepressed method? I tried adding a name before the ofCircle
theball.ofSetColor(0x333333);
theball.ofFill;
theball.ofCircle(100,650,50);
but get I 'theball' was not declared in this scope error.
As razong pointed out that's not how OF works. OF (to the best of my knowledge) provides a handy wrapper to a lot of OpenGL stuff. So you should use OF calls to effect the current drawing context (as opposed to thinking of a canvas with sprite objects or whatever). I usually integrate that kind of thing into my objects. So lets say you have a class like this...
class TheBall {
protected:
ofColor col;
ofPoint pos;
public:
// Pass a color and position when we create ball
TheBall(ofColor ballColor, ofPoint ballPosition) {
col = ballColor;
pos = ballPosition;
}
// Destructor
~TheBall();
// Make our ball move across the screen a little when we call update
void update() {
pos.x++;
pos.y++;
}
// Draw stuff
void draw(float alpha) {
ofEnableAlphaBlending(); // We activate the OpenGL blending with the OF call
ofFill(); //
ofSetColor(col, alpha); // Set color to the balls color field
ofCircle(pos.x, pos.y, 5); // Draw command
ofDisableAlphaBlending(); // Disable the blending again
}
};
Ok cool, I hope that makes sense. Now with this structure you can do something like the following
testApp::setup() {
ofColor color;
ofPoint pos;
color.set(255, 0, 255); // A bright gross purple
pos.x, pos.y = 50;
aBall = new TheBall(color, pos);
}
testApp::update() {
aBall->update()
}
testApp::draw() {
float alpha = sin(ofGetElapsedTime())*255; // This will be a fun flashing effect
aBall->draw(alpha)
}
Happy programming.
Happy designing.
You can't do it that way. ofCircle is a global drawing method and draws just a circle.
You can declare a variable (or better three int for rgb - since you can't use ofColor as an argument for ofSetColor) that store the color for the circle and modify it in the mousepressed method.
Inside the draw method use your variables for ofSetColor before rendering the circle.