I am trying to complete some basic example in OpenGL from the OGLSuperbible. Basically, I am going to make the background shift from red to orange to green and back.
Here is the code that I am using:
typedef float F32;
void Example1::Render(void) {
time += 0.20f;
const GLfloat color[] = { (F32)sin(time) * 0.5f + 0.5f,
(F32)cos(time) * 0.5f + 0.5f,
0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, color);
}
I have a precision timer that will measure the delta time of the last frame, but, anytime that I call the sin and cos functions with anything less than 1, it just keeps the screen at green. However, If I hard code the value to change by, as I have, if I increase it by 1 or more, it will flash between the colors very quickly (like a rave). I am not sure why the functions wont work for floating point numbers. I am using visual studio, and have included the math.h header. Has anyone seen anything like this before?
Update: Based of suggestions, I have tried a few things with the code. I got the program to have the effect that I was looking for by adding the following:
Testing my code, I manually input the follow:
In the constructor:
Example1(void): red(0.0f), green(1.0f), interval(0.002f), redUp(true), greenUp(false).....
In the render loop
if (red >= 1.0f) { redUp = false; }
else if (red <= 0.0f) { redUp = true; }
if (green >= 1.0f) { greenUp = false; }
else if (green <= 0.0f) { greenUp = true; }
if (redUp) { red += interval; }
else { red -= interval; }
if (greenUp) { green += interval; }
else { green -= interval; }
const GLfloat color[] = { red, green, 0.0f, 1.0f };
It does what its supposed to, but using the sin and cos functions with the floating point numbers has no change. I am baffled by why, I has assumed that giving sin and cos the floating point values that are time would work. I have tried counting time manually, incrementing it by 1/60th of a second manually, but any time I use sin and cos with anything less than 1.0f, it just remains green.
It looks like your time interval is much too large. If you're just assuming you're running at 60fps (It could be hundreds if you're not restricting it) then delta time should be 0.01667 (1/60) seconds per frame. Incrementing by 0.2 every frame (especially if your refresh rate is over 60fps) will result in strobing.
If you're using C++11, I'd suggest using the Chrono libraries and get exact numbers to use. That's well documented in this post.
Once you're using the actual time, remember that sin and cos take radians, not degrees. The range is only [0, 2PI) so in addition to passing in just your time variable, multiply it with some small factor and play around with that number:
time += 0.01667f;
F32 adjustedTime = time * 0.02; // OcillationSpeed
const GLfloat color[] = { (F32)sin( adjustedTime ) * 0.5f + 0.5f,
(F32)cos( adjustedTime ) * 0.5f + 0.5f,
...
Also, I don't know if you just neglected adding it to this question but don't forget to call glClear(GL_COLOR_BUFFER_BIT); after the clear color is set.
I think you need to refresh the screen by glutSwapBuffers();
I have this code and I can change the background color without difficulties:
void RenderScene(void)
{
// Clear the window with current clearing color
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
time+=0.2;
const GLfloat color[]={sin(time)*0.5f+0.5f,cos(time)*0.5f+0.5f,0.0f,1.0f};
glClearBufferfv(GL_COLOR,0,color);
GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
triangleBatch.Draw();
// Perform the buffer swap to display back buffer
glutSwapBuffers();
}
I get these results
Thanks for all the input. With much digging, I was able to find what my issue was. I thought it was logical, but it was not. It was a syntax error. Here is the code that produces that same results that you are seeing:
const GLfloat color[] = { F32(sin(curTime)) * 0.5f + 0.5f,
F32(cos(curTime)) * 0.5f + 0.5f,
0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, color);
The difference is using (F32)sin.... or F32(sin(... I am not 100% why this works, but I think it has something to do with how the constructor is being called on the typedef that I have set up for the F32 type, which I did in the first place because of some advice in a book called Game Engine Architecture by Jason Gregory. Anyway, thanks for working through it with me.
Related
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();
I'm trying to rotate a red triangle and a green triangle one after another after a constant time interval. I tried the following code and the time interval is not constant.I can't figure out the problem.
static void display(void)
{
now=glutGet(GLUT_ELAPSED_TIME);
elapsedTime = now - interval;
if(flag)
{
if(now%3000==0)
{
flag=false;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1,0,0);
glRotatef(0.1,0.0,0.0,1.0);
glBegin(GL_TRIANGLES);
glVertex3f(-0.5f, 0.5f, -5.0f);
glVertex3f(-1.0f, 1.5f, -5.0f);
glVertex3f(-1.5f, 0.5f, -5.0f);
glEnd();
glutSwapBuffers();
}
else
{
if(now%3000==0)
{
flag=true;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0,1,0);
glRotatef(-0.1,0.0,0.0,1.0);
glBegin(GL_TRIANGLES);
glVertex3f(-0.5f, 0.5f, -5.0f);
glVertex3f(-1.0f, 1.5f, -5.0f);
glVertex3f(-1.5f, 0.5f, -5.0f);
glEnd();
glutSwapBuffers();
}
}
Before anything, have you tried debug 101: print key variables? I am pretty confident that if do cout << now % 3000 << endl you can find the source of the problem yourself.
For the answer:
now % 3000 == 0
Does not seem like a good idea.
How can you be sure that glutGet(GLUT_ELAPSED_TIME) will increment as 1, 2, 3, ...? What if rendering one frame takes 2 ms and the following happens:
2998, 2999, 3001? You just lost one switch time.
Due to the unpredictable time taken to redraw, it is difficult to be perfectly precise on about rendering times.
In your case, a good approximation could be:
now % 6000 < 3000
This should work well because 3s is much larger than the frequency at which the display will be called.
In most applications however, we want continuous movement, and the best option is to make movement proportional to the actual time lapses with code like:
float dt;
int t, oldT;
t = glutGet(GLUT_ELAPSED_TIME);
dt = (t - oldT)/1000.0;
oldT = t;
drawTriangle(rotationSpeed * dt);
I use glfw and glm.
If I scroll up - I want to make object bigger, when I scroll down - I want to make object smaller.
How to do it?
I use this function to handle mouse scrolling.
static void mousescroll(GLFWwindow* window, double xoffset, double yoffset)
{
if (yoffset > 0) {
scaler += yoffset * 0.01; //make it bigger than current size
world = glm::scale(world, glm::vec3(scaler, scaler, scaler));
}
else {
scaler -= yoffset * 0.01; //make it smaller than current size
world = glm::scale(world, glm::vec3(scaler, scaler, scaler));
}
}
By default scaler is 1.0.
I can describe the problem like this.
There is an object. If I scroll up - the value of scaler will become 1.01. So the object will be bigger in 1.01 times. When I scroll up again - as far as I can understand in my case the size of object will be bigger in 1.02 than the previous size(which is bigger than the original in 1.01 times)! But I want its size to be bigger than the original in 1.02 times.
How to solve this problem?
Matrix world looks like this
glm::mat4 world = glm::mat4(
glm::vec4(1.0f, 0.0f, 0.0f, 0.0f),
glm::vec4(0.0f, 1.0f, 0.0f, 0.0f),
glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
And I calculate the positions of vertex in the shader
gl_Position = world * vec4(Position, 1.0);
But I want its size to be bigger than the original in 1.02 times.
Then reset the transform each time instead of accumulating the scales:
world = glm::scale( scaler, scaler, scaler );
I'm trying to implement 2D collision detection with two rectangles constructed using a graphics package.
Unfortunately, I'm beginning to think I don't understand the logic needed to write a function that will handle this.
Below is my code that draws a small sprite and a couple of other rectangles. My sprite moves with keyboard inputs.
I've used several books and also tried sites like Nehe etc and although they're really good tutorials, they only seems to deal directly with 3D collision.
Can someone please show me an efficient way of implementing collision detection using my rectangles above? I know you need to compare the coordinates of each object. I'm just unsure how to track the position of the objects, checking collision and stopping it moving should it collide.
I am self learning and seem to have come to a stop for days now. I'm totally out of ideas and searched more google pages than I care to remember. I'm sorry for my naivety.
I'd appreciate any constructive comments and example code. Thank you.
void drawSprite (RECT rect){
glBegin(GL_QUADS);
glColor3f(0.2f, 0.2f, 0.2f);
glVertex3f(rect.x, rect.y, 0.0);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(rect.x, rect.y+rect.h, 0.0);
glColor3f(0.2f, 0.2f, 0.2f);
glVertex3f(rect.x+rect.w, rect.y+rect.h, 0.0);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(rect.x+rect.w, rect.y, 0.0);
glEnd();
}
void drawPlatform (RECT rect){
glBegin(GL_QUADS);
glColor3f(0.2f,0.2f,0.0f);
glVertex3f(rect.x, rect.y, 0.0);
glColor3f(1.0f,1.0f,0.0f);
glVertex3f(rect.x, rect.y+rect.h, 0.0);
glColor3f(0.2f, 0.2f, 0.0f);
glVertex3f(rect.x+rect.w, rect.y+rect.h, 0.0);
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(rect.x+rect.w, rect.y, 0.0);
glEnd();
}
You can use this collide function with an AABB struct (AABB stands for Aligned Axis Bounding Box) before drawing.
AABB.c
AABB* box_new(float x, float y, float w, float h, int solid)
{
AABB* box = 0;
box = (AABB*)malloc(sizeof(AABB*));
box->x = (x) ? x : 0.0f;
box->y = (y) ? y : 0.0f;
box->width = (w) ? w : 1.0f;
box->height = (h) ? h : 1.0f;
return(box);
}
void box_free(AABB *box)
{
if(box) { free(box); }
}
int collide(AABB *box, AABB *target)
{
if
(
box->x > target->x + target->width &&
box->x + box->width < target->x &&
box->y > target->y + target->height &&
box->y + box->height < target->y
)
{
return(0);
}
return(1);
}
AABB.h
#include <stdio.h>
#include <stdlib.h>
typedef struct AABB AABB;
struct AABB
{
float x;
float y;
float width;
float height;
int solid;
};
AABB* box_new(float x, float y, float w, float h, int solid);
void box_free(AABB *box);
int collide(AABB *box, AABB *target);
I hope it will help ! :)
You won't get that far by detecting a collision since you will have issues of floating-point precision. What you can do is detect overlaps between the rects, and if such an overlap occurs the collision has already happened so you can bump the rects out of each other.
Also, you need to split the engine in two states:
Rects get moved by input
Overlaps are detected and if found the rects get moved out of each other
Display the scene
As to detecting whether two rects overlap see this question:
Determine if two rectangles overlap each other?
I tried to draw a line between two vertices with D3D11. I have some experiences in D3D9 and D3D11, but it seems to be a problem in D3D11 to draw a line, which starts in one given pixel and ends in an other.
What I did:
I added 0.5f to the pixel coordinates of each vertex to fit the texel-/pixel coordinate system (I read the Microsoft pages to the differeces between D3D9 and D3D11 coordinate systems):
f32 fOff = 0.5f;
ColoredVertex newVertices[2] =
{
{ D3DXVECTOR3(fStartX + fOff, fStartY + fOff,0), vecColorRGB },
{ D3DXVECTOR3(fEndX + fOff, fEndY + fOff,0), vecColorRGB }
};
Generated a ortho projection matrix to fit the render target:
D3DXMatrixOrthoOffCenterLH(&MatrixOrthoProj,0.0f,(f32)uRTWidth,0.0f,(f32)uRTHeight,0.0f,1.0f);
D3DXMatrixTranspose(&cbConstant.m_matOrthoProjection,&MatrixOrthoProj);
Set RasterizerState, BlendState, Viewport, ...
Draw Vertices as D3D11_PRIMITIVE_TOPOLOGY_LINELIST
Problem:
The Line seems to be one pixel to short. It starts in the given pixel coordinate an fits it perfect. The direction of the line looks correct, but the pixel where I want the line to end is still not colored. It looks like the line is just one pixel to short...
Is the any tutorial explaining this problem or does anybody have the same problem? As I remember it wasn't as difficult in D3D9.
Please ask if you need further information.
Thanks, Stefan
EDIT: found the rasterization rules for d3d10 (should be the same for d3d11):
http://msdn.microsoft.com/en-us/library/cc627092%28v=vs.85%29.aspx#Line_1
I hope this will help me understanding...
According to the rasterisation rules (link in the question above) I might have found a solution that should work:
sort the vertices StartX < EndX and StartY < EndY
add (0.5/0.5) to the start vertex (as i did before) to move the vertex to the center of the pixel
add (1.0/1.0) to the end vertex to move the vertex to the lower right corner
This is needed to tell the rasterizer that the last pixel of the line should be drawn.
f32 fXStartOff = 0.5f;
f32 fYStartOff = 0.5f;
f32 fXEndOff = 1.0f;
f32 fYEndOff = 1.0f;
ColoredVertex newVertices[2] =
{
{ D3DXVECTOR3((f32)fStartX + fXStartOff, (f32)fStartY + fYStartOff,0), vecColorRGB },
{ D3DXVECTOR3((f32)fEndX + fXEndOff , (f32)fEndY + fYEndOff,0), vecColorRGB }
};
If you know a better solution, please let me know.
I don't know D3D11, but your problem sounds a lot like the D3DRS_LASTPIXEL render state from D3D9 - maybe there's an equal for D3D11 you need to look into.
I encountered the exact same issue, and i fixed thank to this discussion.
My vertices are stored into a D3D11_PRIMITIVE_TOPOLOGY_LINELIST vertex buffer.
Thank for this usefull post, you made me fix this bug today.
It was REALLY trickier than i thought at start.
Here a few line of my code.
// projection matrix code
float width = 1024.0f;
float height = 768.0f;
DirectX::XMMATRIX offsetedProj = DirectX::XMMatrixOrthographicRH(width, height, 0.0f, 10.0f);
DirectX::XMMATRIX proj = DirectX::XMMatrixMultiply(DirectX::XMMatrixTranslation(- width / 2, height / 2, 0), offsetedProj);
// view matrix code
// screen top left pixel is 0,0 and bottom right is 1023,767
DirectX::XMMATRIX viewMirrored = DirectX::XMMatrixLookAtRH(eye, at, up);
DirectX::XMMATRIX mirrorYZ = DirectX::XMMatrixScaling(1.0f, -1.0f, -1.0f);
DirectX::XMMATRIX view = DirectX::XMMatrixMultiply(mirrorYZ, viewMirrored);
// draw line code in my visual debug tool.
void TVisualDebug::DrawLine2D(int2 const& parStart,
int2 const& parEnd,
TColor parColorStart,
TColor parColorEnd,
float parDepth)
{
FLine2DsDirty = true;
// D3D11_PRIMITIVE_TOPOLOGY_LINELIST
float2 const startFloat(parStart.x() + 0.5f, parStart.y() + 0.5f);
float2 const endFloat(parEnd.x() + 0.5f, parEnd.y() + 0.5f);
float2 const diff = endFloat - startFloat;
// return normalized difference or float2(1.0f, 1.0f) if distance between the points is null. Then multiplies the result by something a little bigger than 0.5f, 0.5f is not enough.
float2 const diffNormalized = diff.normalized_replace_if_null(float2(1.0f, 1.0f)) * 0.501f;
size_t const currentIndex = FLine2Ds.size();
FLine2Ds.resize(currentIndex + 2);
render::vertex::TVertexColor* baseAddress = FLine2Ds.data() + currentIndex;
render::vertex::TVertexColor& v0 = baseAddress[0];
render::vertex::TVertexColor& v1 = baseAddress[1];
v0.FPosition = float3(startFloat.x(), startFloat.y(), parDepth);
v0.FColor = parColorStart;
v1.FPosition = float3(endFloat.x() + diffNormalized.x(), endFloat.y() + diffNormalized.y(), parDepth);
v1.FColor = parColorEnd;
}
I tested Several DrawLine2D calls, and it seems to work well.