I try to code an OpenGL project with Qt (v5.1.1) on OS X 10.9, in the manner of the modern pipeline implementation. The program is supposed to be a multi-agent based system or particle system. However I lack in understanding how to draw something out of another class.
In cinder there were some simple drawThisAndThat() command you could call. I read the 6th edition of the 'OpenGL Superbible'. From this and several tutorials all examples seem to cover just programs where all modifications are made out of the class that initializes OpenGL.
I would like to instantiate some objects moving on a grid and draw pixel to display their position. I know I have to call void glVertexAttrib4fv(GLuint index, const GLfloat * vi); but this is not sufficient.
Do I need to call glEnableVertexAttribArray(1); and glDrawArrays(GL_POINTS, 0, 3); as well and what else?
Am I right, to instantiate the class controlling the particles after instantiating OpenGL and bevor the main loop?
How do I manage that the particle draws himself while erasing the position he was drawn bevor?
The program is based on this code.
To answer your questions completely I would have to write a wall of text, I will try to only point out the most important aspects. I hope this will help you enough to use your knowledge and probably further reading to get it to work.
all modifications are made out of the class that initializes OpenGL
You can encapsulate update(time) and draw() methods for your Objects which you then call in your main loop.
Do I need to call glEnableVertexAttribArray(1); and glDrawArrays(GL_POINTS, 0, 3); as well and what else?
I would put all particles into one vertex array to avoid rebinding of different vertex arrays after each particle. Then you would have to use glBindVertexArray(vaid); and glDrawArrays(GL_POINTS, 0, vertexCount); in your draw() call. Be careful with vertexCount, it's not the number of floats (as your question implies) but the number of vertices, which should be 1 in your example or the number of particles in my suggested approach (If I'm correct in assuming that the 3 stands for "x, y, and z of my vertex").
And since you only have particles glDrawElements(...); would probably already fit your needs.
Am I right, to instantiate the class controlling the particles after instantiating OpenGL and bevor the main loop?
Probably your instantiation order is correct that way. You definitely should do all instantiations before calling the main loop in your case.
How do I manage that the particle draws himself while erasing the position he was drawn bevor?
If understand your last question correctly: Simply by changing the elements in your buffer objects (glBufferData(...);). Since you will clear the screen and swap buffers after each loop this will make them move. Just update their position with an update(time) call, e.g. pos = pos + dir * time;, put the new positions into a buffer and push that buffer with glBufferData(...) to the vertex array. Remember to bind the vertex array before pushing the buffer.
Some additional things I'd like to point out.
glEnableVertexAttribArray(1); is to enable a vertex attribute in your shader program to be able to pass data to that attribute. You should create a shader program
id = glCreateProgram()
// ... create and attach shaders here
// then bind attribute locations, e.g. positionMC
glBindAttribLocation(id, 0, "positionMC");
glLinkProgram(id);
And after initializing the vertex array with glGenVertexArrays(); you should enable all attributes your vertex array needs in your shader program. In this example positionMC would be at location 0, so you would call something like
glUseProgram(pid);
glBindVertexArray(vaid);
glEnableVertexAttribArray(1);
glVertexAttribPointer(...);
This has only to be done once, since OpenGL stores the state for every particular vertex array. By rebinding a vertex array you will restore that state.
In the main loop all you have to do now is calling your update and draw methods, e.g.:
handleInputs();
update(deltaTime);
glClear(...);
draw();
swapBuffers();
Related
If I have the following code:
// objective C++ code .mm
id<MTLTexture> texture = ...;
void* ptr = (void*)CFBridgingRetain(texture);
share_ptr_with_native_code(ptr);
[texture do_stuff]; // is this valid?
// native code .cpp
void share_ptr_with_native(void* ptr)
{
ptr->do_stuff();
CFBridgingRelease(ptr);
}
Will texture be valid and retained by ARC again after the call to share_ptr_with_native()?
Other than various errors in your code snippet, yes, the line in question is valid. ARC continues to maintain its own strong reference to object while it's still in use in the top code, in addition to the one that you become responsible for. CFBridgingRetain() has a +1 effect on the retain count of the object, hence "retain" in its name.
Even everything said is right, it would be nicer if you change your
CFBridgingRelease(ptr);
to
CFRelease(ptr) .
__bridge_retained or CFBridgingRetain casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you.
You are responsible for calling CFRelease or a related function to relinquish ownership of the object.
Taken from https://developer.apple.com/library/content/documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/tollFreeBridgedTypes.html.
I don't know how to get sprites to stick to each other so they become one big object instead of tiny little pieces, for example:
attaching a thruster to a box, then the thruster stays in that spot while pushing the box, and also is there a certain term for what I'm talking about?
You could also attach all parts to one of the objects, it would sort of look like:
//Main object
x = 5;
y = 20;
//other object step event
x = obj_main.x + <any value to put it where you want>;
y = obj_main.y + <any value to put it where you want>;
//This will force the parts to follow the main object.
`
`
You can use an array, defined in the 'main' object to use a sort of grid to define where each piece is and then either draw each individual sprite, based on its position in the array, originating from the 'main' object's coordinates. Or just create an individual instance of an object if you would like to have additional functionality by trading off some performance.
For more information on arrays and how to position sprites and objects based on set coordinates, check out the GML documentation provided below:
Arrays:
https://docs.yoyogames.com/source/dadiospice/002_reference/001_gml%20language%20overview/401_06_arrays.html
lengthdir:
https://docs.yoyogames.com/source/dadiospice/002_reference/maths/real%20valued%20functions/lengthdir_x.html
what I did was make the object disabled, so when I press left and right it doesn't go anywhere, only the other piece would move, but when it came into contact it allowed the other piece to move along with it, and set its speed to the corresponding objects speed, in simpler term, when I collide with it, it turns the movement on and goes in the same direction as the current object in the same speed, making it look like its sticking
I am using Qt 5.4 and setting up the projection matrix and viewport as follows in my resizeGL function override:
glViewport(_off_x, _off_y, _width, _height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, _width, 0, _height, -1, 1);
I can verify this and when I print out the projection matrix as follows, it shows the correct value:
GLdouble projection[16];
glGetDoublev(GL_PROJECTION_MATRIX, projection );
// printing this shows the correct projection matrix.
However, somewhere this is getting overridden. When I print the projection matrix in the paintGL() function, it shows it as identity.
Interestingly, I switched to the old QGLWidget and it performs as expected.
However, somewhere this is getting overridden. When I print the projection matrix in the paintGL() function, it shows it as identity.
And you're surprised exactly why? Qt5 may use OpenGL for drawing its stuff. Which means that Qt will have to set the state of the OpenGL context according to its needs.
What you observed is what is to be expected, so don't be surprised.
I am using Qt 5.4 and setting up the projection matrix and viewport as follows in my resizeGL function override:
You should not be doing that. As with every state based system it's essential to set the state right when you need it to what you need it – or keep track of all of the state changes, which is much more difficult.
Do the right thing and move everything you did in resizeGL to where it belongs: paintGL. The sole purpose of resizeGL is to update resources like FBO renderbuffers and to reflect the new size. But don't use it to set drawing related OpenGL state.
I have a Qt widget with four partitions, separated with splitters.
The top level is a vertical splitter, changing the heights of two horizontal splitters, topSplitter and bottomSplitter.
How can I keep both horizontal splitters positions equal, as if it was just one horizontal splitter?
I looked at linking signal for splitterMoved, and connecting it to a slot on the other splitter but there are no equivalent slots in the splitter class.
This would obviously have to avoid the issue of an infinite loop where one splitter's position updates the second, which updates the first.
It's pretty simple. Initialization (splitter1 and splitter2 are the splitters that need to be syncronized):
connect(ui->splitter1, SIGNAL(splitterMoved(int,int)), this, SLOT(splitterMoved()));
connect(ui->splitter2, SIGNAL(splitterMoved(int,int)), this, SLOT(splitterMoved()));
The slot:
void MainWindow::splitterMoved() {
QSplitter* senderSplitter = static_cast<QSplitter*>(sender());
QSplitter* receiverSplitter = senderSplitter == ui->splitter1 ?
ui->splitter2 : ui->splitter1;
receiverSplitter->blockSignals(true);
receiverSplitter->setSizes(senderSplitter->sizes());
receiverSplitter->blockSignals(false);
}
blockSignals ensures that calls will not go to infinite recursion. Actually, setSizes doesn't cause emitting splitterMoved, so you can remove both blockSigals calls and the code will still work. However, there is no note about this in the documentation, so I wouldn't rely on that.
In the containing widget you can create slots to connect to the splitterMoved signal.
There needs to be one slot for each splitter, where it needs to check if the splitter is already the correct size (to avoid the infinite loop) then update the size if necessary.
I am only including one of the example slots and connections, but one will be needed for each splitter that needs to be linked.
Putting the following content into the new slots for updating the splitter positions.
QList<int> OtherSize,Current;
OtherSize=topSplitter->sizes();
Current=bottomSplitter->sizes();
if(OtherSize!=Current)
{
bottomSplitter->setSizes(OtherSize);
}
This will create two lists ready to hold the sizes for the splitters.
It gets the current sizes of both splitters, and compares them.
The comparison is necessary to avoid the infinite loop.
Then, if they are different, it sets the sizes to match that of the other splitter.
Connecting that slot to the appropriate splitterMoved signal should work.
This connection is used in the constructor of the containing widget (where you created the new slots).
connect(topSplitter,SIGNAL(splitterMoved(int,int)),this,SLOT(updateBottomSplitter()));
It is safe to ignore the position and index supplied by the signal, because we check the sizes in a different way in this slot.
This will set all sizes, so all splitter bars will match position.
If there are only two, it doesn't matter but if there are more than two, when any bar is moved, all will be updated to match.
Delphi's TBitmap type is basically a wrapper over a GDI BITMAP and PALETTE, and can support both top-down and bottom-up scanline ordering.
I have a TBitmap which I need to convert to GDI+ Bitmap, in order to rotate and composite it.
My bitmap is 32-bit ARGB, which windows supports, but VCL doesn't natively 'understand'.
TBitmap *bmp;
...
When I use the following constructor, the alpha channel doesn't work for compositing, but otherwise everything works.
Gdiplus::Bitmap b(bmp->Handle, NULL);
So, I tried the constructor below, which takes size, pixel data and format params.
Gdiplus::Bitmap b(bmp->Width, bmp->Height, bmp->Width *4, PixelFormat32bppARGB,
(BYTE*) bmp->ScanLine[bmp->Height-1]); // bottom up storage
This gets the alpha, but the bitmap is upside down, so I tried this
Gdiplus::Bitmap b(bmp->Width, bmp->Height, - bmp->Width *4, PixelFormat32bppARGB,
(BYTE*) bmp->ScanLine[0]); // negative stride for bottom up bitmaps?!
Now, that works, but of course I'm hard-coded into bottom-up bitmaps. However, I can't find a way of determining if the TBitmap is top-down or bottom-up. They're stored internally with negative height but the height value is massaged before it's passed back to user code.
How can I find out the scanline ordering, or - better yet - is there another way of creating a GDIPlus bitmap from a TBitmap?
The TBitmap::ScanLine property accounts for top-down and bottom-up. For a bottom-up bitmap, ScanLine[0] returns the last row, and ScanLine[Height-1] returns the first row, of the raw pixel data. For a top-down bitmap, ScanLine[0] returns the first row, and ScanLine[Height-1] returns the last row, of the raw pixel data.
To determine if a TBitmap is bottom-up or top-down, you have to manually retreive its BITMAPINFOHEADER structure, which TBitmap does not natively expose. You can use the Win32 API GetObject() function to retreive a DIBSECTION structure, which has a BITMAPINFOHEADER member.