How to make a spring constraint with Bullet Physics? - c++

I want to test the spring contraint of Bullet Physics. So I created a static box hovering above the ground and a second dynamic box hanging down from it. But activating the spring behavior does nothing! The box is indeed hanging freely. I know it because it rotates freely. But it does not oscillate or anything.
btCollisionShape *boxShape = createBoxShape(0.2f, 0.2f, 0.2f);
btRigidBody *box1 = createStatic(boxShape);
btRigidBody *box2 = createDynamic(1.0f /*mass*/, boxShape);
box1->setWorldTransform(btTransform(btQuaternion::getIdentity(), { 0.0f, 2.0f, 1.0f }));
box2->setWorldTransform(btTransform(btQuaternion::getIdentity(), { 0.0f, 1.0f, 1.0f }));
btGeneric6DofSpring2Constraint *spring = new btGeneric6DofSpring2Constraint(
*box1, *box2,
btTransform(btQuaternion::getIdentity(), { 0.0f, -1.0f, 0.0f }),
btTransform(btQuaternion::getIdentity(), { 0.0f, 0.0f, 0.0f })
);
// I thought maybe the linear movement is locked, but even using these lines do not help.
// spring->setLinearUpperLimit(btVector3(0.0f, 0.1, 0.0f));
// spring->setLinearLowerLimit(btVector3(0.0f, -0.1, 0.0f));
// Enabling the spring behavior for they y-coordinate (index = 1)
spring->enableSpring(1, true);
spring->setStiffness(1, 0.01f);
spring->setDamping (1, 0.00f);
spring->setEquilibriumPoint();
What is wrong? I played a lot with the the Stiffness and Damping parameters. But it changed nothing. Setting linear lower and upper limits makes the box movable in the y-direction, but it still not oscillates. And yes, gravity is activated.

Ok, I found a solution by checking out Bullet's provided example projects (could have come up with the idea earlier). Three things I have learned:
The spring constraint will not violate the linear limits. The problem with my former approach was that the linear movement was either locked, or limited to a too small range for the assigned spring stiffness. Now there are no more limits (by setting the lower limit above the upper one).
The stiffness was far too small, so the joined objects were acting as if they were freely movable inside the linear limits. You can check out the values in my code below, I got them from the example project.
There is a small difference in the behavior between btGeneric6DofSpringConstraint and btGeneric6DofSpring2Constraint. The former one seems to violet the non-spring-axes less (x- and z-axes in my case). The latter one seems to apply a stronger damping. But these are just first observations.
btGeneric6DofSpringConstraint *spring = new btGeneric6DofSpringConstraint(
*box1, *box2,
btTransform(btQuaternion::getIdentity(), { 0.0f, -1.0f, 0.0f }),
btTransform(btQuaternion::getIdentity(), { 0.0f, 0.0f, 0.0f }),
true
);
// Removing any restrictions on the y-coordinate of the hanging box
// by setting the lower limit above the upper one.
spring->setLinearLowerLimit(btVector3(0.0f, 1.0f, 0.0f));
spring->setLinearUpperLimit(btVector3(0.0f, 0.0f, 0.0f));
// Enabling the spring behavior for they y-coordinate (index = 1)
spring->enableSpring(1, true);
spring->setStiffness(1, 35.0f);
spring->setDamping (1, 0.5f);
spring->setEquilibriumPoint();

Related

C++ GDI: I am seeking explanation for color matrix such that I can create any color manipulation mask

I am trying to implement an application that can manipulate the background screen color attributes through a transparent window. Basically trying to recreate Color Oracle. I am progressing here through C++:GDI+ resources. This GDI has a Color Matrix concept. I am able to create filters for greyscale(as shown in the example in the last hyperlink), brightness tweaking, saturation tweaking; However, as advanced use cases such as color blindness filter, blue light filter, contrast tweaks - I am using the hit-n-trial approach, It will be much efficient if anyone can take me in the right direction to learn fundamentals of this color matrix.
Example Matrix is shown below which boosts saturation by a small factor while restricting brightness component.
MAGCOLOREFFECT magEffectSaturationBoost =
{ { // MagEffectBright
{ 1.02f, 0.0f, 0.0f, 0.0f, 1.0f },
{ 0.0f, 1.02f, 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 1.02f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f, 0.0f },
{ -0.1f, -0.1f, -0.1f, 0.0f, 0.0f }
}
}
// Using the Matrix
ret = MagSetColorEffect(hwndMag, &magEffectSaturationBoost);
It will be much efficient if anyone can take me in the right direction to learn fundamentals of this color matrix.
Each color vector is multipled by 5x5 matrix, to make it possible color vector is 5 elements long - the fifth element is a dummy one, this allows to perform additional operations on colors (rotation, scaling, ...).
In your example each color component is multiplied by 1.02f making color brighter, after multiplication - from each color component 0.1 value is subtracted.
You can find full explanation here:
https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-using-a-color-matrix-to-transform-a-single-color-use
and:
https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-coordinate-systems-and-transformations-about
Few more links:
https://docs.rainmeter.net/tips/colormatrix-guide/
https://www.integral-domain.org/lwilliams/math150/labs/matrixcolorfilter.php

Trying to Make Endless Runner C++ with OpenGL

I have an array of cube objects initialised like so (index 0 not used here as that's for the player):
game_object[1] = new GameObject();
game_object[1]->setPosition(vec3(7.0f, 0.0f, 0.0f));
game_object[2] = new GameObject();
game_object[2]->setPosition(vec3(14.0f, 0.0f, 0.0f));
game_object[3] = new GameObject();
game_object[3]->setPosition(vec3(21.0f, 0.0f, 0.0f));
game_object[4] = new GameObject();
game_object[4]->setPosition(vec3(36.0f, 0.0f, 0.0f));
game_object[5] = new GameObject();
game_object[5]->setPosition(vec3(42.0f, 0.0f, 0.0f));
I have a render function in which they are drawn:
glDrawElements(GL_TRIANGLES, 3 * INDICES, GL_UNSIGNED_INT, NULL);
In my update they move to the left as expected. To do this I am just adding another vector to their positions:
for (int i = 1; i < MAX_CUBES; i++)
{
game_object[i]->setPosition(game_object[i]->getPosition() + vec3(-0.03, 0.0, 0.00));
}
However, I want the cubes to repeat this until the user exits the game. I made a reset function to send them back to their starting positions:
void Game::reset()
{
game_object[0]->setPosition(vec3(0.0f, 0.0f, 0.0f));
game_object[1]->setPosition(vec3(7.0f, 0.0f, 0.0f));
game_object[2]->setPosition(vec3(14.0f, 0.0f, 0.0f));
game_object[3]->setPosition(vec3(21.0f, 0.0f, 0.0f));
game_object[4]->setPosition(vec3(36.0f, 0.0f, 0.0f));
game_object[5]->setPosition(vec3(42.0f, 0.0f, 0.0f));
}
This function gets called in the update when the final cube's position is off screen to the left:
if (game_object[5]->getPosition().x <= 0.0)
{
reset();
}
However, this isn't working. Nothing resets after the last cube goes to the left.
Not sure how you are using game_object here but looks very error prone. If you have MAX_CUBES = 5 (as you do have 5 cubes), then that for-loop will miss the last one. Adding further objects (e.g. for gaps, vertical rules, hazards, etc.) will make it even more so.
for (int i = 1; i < MAX_CUBES; i++)
{
game_object[i]->setPosition(game_object[i]->getPosition() + vec3(-0.03, 0.0, 0.00));
}
If MAX_CUBES = 5, then it will move index 1, 2, 3, 4, and not 5, which is the one you check in the condition. 5 will just stay at 42 permanently (is that off-screen?).
Stepping through the code in a debugger will make a problem like this pretty clear regardless, and is an essential tool for programming. Maybe the code just never reaches the if (game_object[5]->getPosition().x <= 0.0) check in the first place? Is there any return in that update function, or is that condition inside another one of some sorts?
Because in your comment you noted that game_object[5]->getPosition().x returns a correct value, the most likely problem is with your reset() function and the setPosition function you are using.
1. Check if set position is working in the first place
Perhaps there is an error with setPosition().
After you set the position using setPosition() and then log the object's coordinates using getPosition() does it return the position you expect?
If not, something is wrong with setPosition.
If so, then...
2. You probably changed the position but failed to render it!
This is a very common problem lol
There is a very high chance you changed the position of the object BUT didn't update what's shown on the screen!
3. Side note for scalability
There is a much more efficient and scalable way of doing a reset if you have eventually have more than 5 objects, by placing their reset values in an array and looping through them:
#define MAX_CUBES 6
double resetPositions_x[MAX_CUBES] = {0.0, 7.0, 14.0, 21.0, 36.0, 42.0};
void Game::reset()
{
for(int i=0;i<MAX_CUBES;i++){
game_object[i]->setPosition(vec3(resetPositions_x[i], 0.0f, 0.0f));
}
}
(Also, it seems every x reset position is a multiple of 7 except 36.0 -> is that a mistake?)

Bullet Physics: 'btGeneric6DofSpringConstraint' vs. 'btGeneric6DofSpring2Constraint' to simulate a spring

I am using Bullet Physics to simulate a box fixed two meters above the ground, and another one hanging down from it with a spring (or maybe better a rubberband of equilibrium length 0) simulated by a btGeneric6DofSpringConstraint.
btCollisionShape *shape = createBoxShape(0.2f, 0.2f, 0.2f);
btRigidBody *bodies[] = {
createStaticStatic(shape),
createDynamic(10 * getVolume(shape), shape),
};
bodies[0]->getWorldTransform().setOrigin({ 0.0f, 2.0f, 1.0f });
bodies[1]->getWorldTransform().setOrigin({ 0.0f, 1.0f, 1.0f });
// We can use 'btGeneric6DofSpring2Constraint' instead
btGeneric6DofSpringConstraint *spring = new btGeneric6DofSpringConstraint(
*bodies[0], *bodies[1],
{ 0.0f, -0.2f, 0.0f }, { 0.0f, 0.2f, 0.0f },
true
);
// Disable limits
spring->setLinearLowerLimit({ 1.0f, 1.0f, 1.0f });
spring->setLinearUpperLimit({ -1.0f, -1.0f, -1.0f });
// Enable spring behavior
for (int i = 0; i < 3; ++i)
{
spring->enableSpring(i, true);
spring->setStiffness(i, 35.0f);
spring->setDamping(i, 1.0f);
spring->setEquilibriumPoint(i, 0);
}
world->addConstraint(spring);
Now I enounter the problem that no damping is applied to the spring, no matter what value I use in setDamping. I read that this can be fixed by using btGeneric6DofSpring2Constraint instead (note the 2 after the Spring). But now the spring behaves unpredictable (generates energy, changes direction, etc.) whenever the spring is not attached to the bodies centers of mass (as in the example above).
Has anybody any idea what could be the problem? What is the difference between btGeneric6DofSpringConstraint and btGeneric6DofSpring2Constraint anyway?

How to use glOrtho2D with moving positions?

I'm trying to move the camera based on a player (simple square)'s position (x, y). The scale is relatively small and the character is 0.5f by 0.5f.
How can I focus the camera on the player's x, and y coordinates using glOrtho2D?
I am really confused by how you use left, right, down, and up. It makes absolutely no sense, it apparently defines the screen ratio as well as the position in which it draws?
Any help is EAGERLY appreciated.
I switched from the 3d version (gluLookAt) which was the following:
gluLookAt(jake.px, 0.0f, jake.pz + 20, jake.px, 7.0f, jake.pz, 0.0f, 1.0f, 0.0f );
and on Resize
gluPerspective(45.0f, ratio, 0.1f, 100.0f);

OpenSceneGraph - How to add a Wall or 3

I need to add a wall to my scenegraph, and have it work so I can not go past the wall with my camera. I am creating an laboratory scene, but I am new to 3d programming in general. I have been working with the book OpensceneGraph 3.0 Beginner's guide, and so far, Ok.
I have a couple of furniture in my scene but what I would like to do is add a wall beyond which my camera should not go. My code below, from the book, Openscenegraph beginner, does not seem to do anything(page 83). I add it and I don't see a wall and I am still able to move everywhere in the scene with my camera. How do I create a wall in my application.
osg::ref_ptr<osg::Group> root = new osg::Group();
//adding walls to the lab to make it more room like -- 7/6/12
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
vertices->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
vertices->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
vertices->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
vertices->push_back(osg::Vec3(1.0f, 0.0f, 1.5f));
vertices->push_back(osg::Vec3(2.0f, 0.0f, 0.0f));
vertices->push_back(osg::Vec3(2.0f, 0.0f, 1.0f));
vertices->push_back(osg::Vec3(3.0f, 0.0f, 0.0f));
vertices->push_back(osg::Vec3(3.0f, 0.0f, 1.5f));
vertices->push_back(osg::Vec3(4.0f, 0.0f, 0.0f));
vertices->push_back(osg::Vec3(4.0f, 0.0f, 1.0f));
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));
osg::ref_ptr<osg::Geometry>geom = new osg::Geometry;
geom->setVertexArray(vertices.get());
geom->setNormalArray((normals.get()));
geom->setNormalBinding((osg::Geometry::BIND_OVERALL));
geom->addPrimitiveSet((new osg::DrawArrays(GL_QUAD_STRIP,0,10)));
osg::ref_ptr<osg::Geode> wall = new osg::Geode;
wall->addDrawable(geom.get());
root->addChild(wall);
osgViewer::Viewer viewer;
viewer.setSceneData(root.get());
viewer.run();
You are already drawing the "wall" as coded above - it looks a little more like a fence than a wall, but you can easily fix that by moving the 1.0 values all the way up to 1.5 to match the others. You might not be seeing it with the rest of your scene because of differences of scale - if the dimensions of your furniture are in 100's, for example. Replace your root->addChild(wall) with this code:
// assumes your furniture is already added to root
float scale=root->getBound().radius();
osg::ref_ptr<osg::PositionAttitudeTransform> pax = new osg::PositionAttitudeTransform;
pax->addChild(wall);
pax->setScale(osg::Vec3d(scale,scale,scale));
root->addChild(pax);
Then you will see your fence. Move the position/rotation of pax to place your wall. As I mentioned in the comments, then you'll have to use some intersection code to tell the camera where to stop.