OpenGL + Cloth simulation physics isn't working - c++

I am attempting to implement a cloth simulation using a spring-particle system but something isn't quite right with my physics. When I run the simulation the cloth draws as expected but over time the force of gravity pulls the cloth downward indefinitely. In other words the forces caused by the springs are not accumulating properly to overcome the downward pull of gravity and I end up with this...:
It continues to droop downwards indefinitely. From all of the debugging I have done what I have seen is that the accumulation of forces on a particle caused by all of the springs attached to it is not properly summing when the force of gravity causes increased stretch. I can not figure out what I have overlooked in my physics.
My cloth updates every time step using this function
void Cloth::updateGeometry(atlas::utils::Time const& t) {
for (int i = 0; i < mSprings.size(); ++i) {
mSprings[i].calculateForces();
}
for (int i = 0; i < mParticles.size(); ++i) {
mParticles[i].updateGeometry(t);
}
}
My springs update using the below function where p1 and p2 are pointers to each particle that this spring is attached to.
void Spring::calculateForces() {
glm::vec3 springVector = normalize((p2->getCurrentPosition() - p1->getCurrentPosition()));
GLfloat stretchLength = length(p2->getCurrentPosition(), p1->getCurrentPosition());
GLfloat displacementFromRest = restLength - stretchLength;
glm::vec3 springForce = -k * displacementFromRest * normalize(springVector);
//Multiply the displacements by the spring constant to get
//A vector which represents the force on each spring
p1->addToSumOfSpringForces(springForce);
p2->addToSumOfSpringForces(-springForce);
}
Finally my particles update using.
void Particle::updateGeometry(atlas::utils::Time const& t) {
if (!stationary) {
previousPosition = currentPosition;
glm::vec3 forceOfGravity = mass * gravity;
glm::vec3 totalForce = forceOfGravity + (mass * totalSpringForces) - velocity*Damping;
acceleration = totalForce / mass;
//Perform Euler Integration
currentPosition += t.deltaTime * velocity;
velocity += t.deltaTime * acceleration;
//============== End Euler==============//
//Reset the forces acting on the particle from all of the springs
//So that a new accumulated total can be calculated.
totalSpringForces = glm::vec3{ 0.0f, 0.0f, 0.0f };
}
}
The totalSpringForces variable is updated by the call to addToSumOfSpringForces(springForce); in the spring update function. The idea is that each spring is evaluated first according to the current position of each particle then each particle's totalSpringForcevariable is accumulated each iteration using
void Particle::addToSumOfSpringForces(glm::vec3 force) {
totalSpringForces += force;
}
Just to add clarification the cloth is constructed using structural, bend and shear springs in accordance with this description. This may be unneccesary but I've included my cloth constructor below.
Cloth::Cloth(GLfloat width_, GLfloat height_, GLuint numParticlesWide_, GLuint numParticlesHigh_) :
width(width_),
height(height_),
numParticlesHigh(numParticlesHigh_),
numParticlesWide(numParticlesWide_),
clothRotationVector{0.0f, 0.0f, 0.0f},
clothPosition{ 0.0f, 5.0f, 0.0f },
clothRotationAngle(0.0f)
{
USING_ATLAS_MATH_NS;
USING_ATLAS_GL_NS;
glm::vec3 clothColour{1.0f, 0.5f, 0.2f};
//Create Particles
GLuint count = 0;
restLength = (width * (1 / (float)numParticlesWide));
for (GLuint y = 0; y < numParticlesHigh; ++y) {
for (GLuint x = 0; x < numParticlesWide; ++x) {
glm::vec3 pos = {(width * (x / (float)numParticlesWide)), (-height * (y / (float)numParticlesHigh)), 0.0f};
mParticles.push_back(Particle(pos, count, clothColour));
++count;
}
}
//Create Springs
for (GLuint x = 0; x < numParticlesWide; ++x) {
for (GLuint y = 0; y < numParticlesHigh; ++y) {
//============ Structural springs ==========//
//Connect to the particle to the immediate right of the current particle
if (x < numParticlesWide - 1) mSprings.push_back(Spring(getParticle(x,y), getParticle(x+1,y)));
//Connect to the particle that is immediately below the current particle
if (y < numParticlesHigh - 1) mSprings.push_back(Spring(getParticle(x,y), getParticle(x,y+1)));
//============ Shear Springs ================//
//Connect the shear springs to make the X pattern
if (x < numParticlesWide - 1 && y < numParticlesHigh - 1) {
mSprings.push_back(Spring(getParticle(x, y), getParticle(x + 1, y + 1)));
mSprings.push_back(Spring(getParticle(x+1, y), getParticle(x, y+1)));
}
//============ Bend Springs ===============//
//Connect the current particle to the second particle over to the right
if (x < numParticlesWide - 2) mSprings.push_back(Spring(getParticle(x,y), getParticle(x+2,y)));
//Connect the current particle to the particle two below
if (y < numParticlesHigh - 2) mSprings.push_back(Spring(getParticle(x,y), getParticle(x, y+2)));
////Create the X pattern
//if (x < numParticlesWide - 2 && y < numParticlesHigh - 2) {
// mSprings.push_back(Spring(getParticle(x, y), getParticle(x+2,y+2)));
// mSprings.push_back(Spring(getParticle(x+2,y), getParticle(x,y+2)));
//};
}
}
//Set the top left and right as stationary
getParticle(0, 0)->makeStationary();
getParticle(numParticlesWide - 1, 0)->makeStationary();
//Make Indices for Particles
for (GLuint row = 0; row < numParticlesWide - 1; ++row) {
for (GLuint col = 0; col < numParticlesHigh - 1; ++col) {
//Triangle one
mParticleIndices.push_back(getParticle(row,col)->getIndex());
mParticleIndices.push_back(getParticle(row,col+1)->getIndex());
mParticleIndices.push_back(getParticle(row+1, col)->getIndex());
//Triangle two
mParticleIndices.push_back(getParticle(row, col+1)->getIndex());
mParticleIndices.push_back(getParticle(row+1, col+1)->getIndex());
mParticleIndices.push_back(getParticle(row+1, col)->getIndex());
}
}
glGenBuffers(1, &clothVertexBufferID);
glGenBuffers(1, &clothIndexBufferID);
sendDataToGPU();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, clothIndexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mParticleIndices.size() * sizeof(GLushort), &mParticleIndices[0], GL_STATIC_DRAW);
defineVAO();
std::string shaderDir = generated::ShaderPaths::getShaderDirectory();
std::vector<ShaderInfo> shaders
{
{ GL_VERTEX_SHADER, shaderDir + "Cloth.vs.glsl" },
{ GL_FRAGMENT_SHADER, shaderDir + "Cloth.fs.glsl" }
};
mModel = glm::translate(Matrix4(1.0f), clothPosition);
mShaders.push_back(ShaderPointer(new Shader));
mShaders[0]->compileShaders(shaders);
mShaders[0]->linkShaders();
mUniforms.insert(UniformKey("mvpMat",mShaders[0]->getUniformVariable("mvpMat")));
mShaders[0]->disableShaders();
}
EDIT
I have verified that the totalSpringForcesvariable is indeed changing. I added a print statement in my Particle update function which you can see in the image below. The selected the totalSpringForces for only particle #55 which in this case is the particle immediately under particle 0 which is stationary and not allowed to move. Also the printout is after about 20-25 iterations. As you can see the totalSpringForcesin the y direction has positive value of 0.7037 (i.e. is counteracting gravity). I let it run for half an hour and it only got to 5.
Currently my constants are
k = 2.0f
mass = 0.1f
damping = 0.55f
gravity{ 0.0f, -9.81f, 0.0f },

Related

How to scale and rotate squares to fit inside each other in OpenGl

Im trying to scale and rotate 10 squares to fit inside each other recursively at a rotation angle of 45 in OpenGl. my output should look like this.
my current code is this
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
scale = 1.0f;
angle = 45.0f;
for (int i = 0; i < 10; i++)
{
transformObject(scale -=0.156f, Z_AXIS, angle -= 45.0f, glm::vec3(0.0f, 0.0f, 0.0f));
glDrawArrays(GL_LINE_LOOP, 0, 4);
}
The size of the square gets smaller by the scale 1/sqrt(2) with each iteration of the loop. The outer rectangle is not transformed. The outer rectangle is not transformed. Change the scale and angle at the end of the loop:
scale = 1.0f;
angle = 0.0f;
for (int i = 0; i < 10; i++)
{
transformObject(scale, Z_AXIS, angle, glm::vec3(0.0f));
glDrawArrays(GL_LINE_LOOP, 0, 4);
scale = 1.0f/sqrt(2.0f);
angle -= 45.0f;
}

OpenGL moving vertices with mouse

I am using legacy OpenGL and trying to move vertices around with the mouse. To test whether a vertex is clicked on I loop through all vertices and multiply them by the model and projection matrix before dividing by the w value. This works fine and is shown below:
for (Vertex *vertex : context->getMesh().vertices) {
QVector4D vert(vertex->xPos, vertex->yPos, vertex->zPos, 1.0f);
QVector4D transformedVert = projectionMatrix * modelMatrix * vert;
transformedVert /= transformedVert.w();
if ((mappedX < (transformedVert.x() + 0.1) && mappedX > (transformedVert.x() - 0.1)) &&
(mappedY < (transformedVert.y() + 0.1) && mappedY > (transformedVert.y() - 0.1))) {
std::cout << "SUCCESS" << std::endl;
vertexPicked = true;
currentVertex = vertex;
}
}
Then when I move the mouse I try to work backwards by first multiplying the current mouse coordinates by the same W value as in the first step and then multiplying by the inverse of the projection and model matrices. This moves the vertex around but not to where the mouse is.
float mouseX = ((2.0f * event->x()) / width() - 1.0f);
float mouseY = -((2.0f * event->y()) / height() - 1.0f);
float x = (modelMatrix.inverted() * projectionMatrix.inverted() *
(QVector4D(mouseX, mouseY, 1, 1) * (projectionMatrix * modelMatrix * QVector4D(MousePicker::currentVertex->xPos, MousePicker::currentVertex->yPos, MousePicker::currentVertex->zPos, 1)).w())).x();
MousePicker::currentVertex->xPos = x;
I am currently only trying to change the X coordinate.

OpenGL simulate Prince of persia camera

I have an object "character" which can turn around itself left and right and move forward in its face direction, and a camera always looks at the object and can rotate around it.
The problem is : I want to move the camera with the object movement in its direction regardless the camera direction as in Prince of Persia, if the character face against the camera direction and the character move forward this means if the camera is not moving the character become more near to the camera so if the camera is moveable the camera should move back to make the distance between them the same, if the character looks to the right then the camera should moves to its right and so on for any direction, the camera have position, front, right and up vectors and yaw and pitch angles, the character has position and yaw and pitch angles.
the code which makes the character move is:
void Mesh::Move(Move_Directions direction, GLfloat deltaTime) {
GLfloat velocity = 50 * this->movementSpeed * deltaTime;
if (direction == FORWARD) {
glm::vec3 t = glm::vec3(sin(glm::radians(yaw)), 0.0, cos(glm::radians(yaw))) * velocity;
matrix = glm::translate(matrix, t);
for (GLuint i = 0; i < this->m_Entries.size(); i++) {
this->m_Entries[i].setModelMatrix(matrix);
}
//scene->getDefCamera()->Translate(t);
}
if (direction == BACKWARD) {
glm::vec3 t = glm::vec3(sin(glm::radians(yaw)), 0.0, cos(glm::radians(yaw))) * velocity;
matrix = glm::translate(matrix, -t);
for (GLuint i = 0; i < this->m_Entries.size(); i++) {
this->m_Entries[i].setModelMatrix(matrix);
}
//scene->getDefCamera()->Translate(t);
}
if (direction == RIGHT) {
matrix = glm::rotate(matrix, (GLfloat) -M_PI*deltaTime, glm::vec3(0.0, 1.0, 0.0));
for (GLuint i = 0; i < this->m_Entries.size(); i++) {
this->m_Entries[i].setModelMatrix(matrix);
}
}
if (direction == LEFT) {
matrix = glm::rotate(matrix, (GLfloat) M_PI*deltaTime, glm::vec3(0.0, 1.0, 0.0));
for (GLuint i = 0; i < this->m_Entries.size(); i++) {
this->m_Entries[i].setModelMatrix(matrix);
}
}
}
and the code of camera is:
void Camera::updateVectors() {
GLfloat radius = glm::length(center - position);
position.x = radius * cos(glm::radians(this->yaw)) * cos(glm::radians(this->pitch));
position.y = radius * sin(glm::radians(this->pitch));
position.z = radius * sin(glm::radians(this->yaw)) * cos(glm::radians(this->pitch));
this->front = glm::normalize(center - position);
this->right = glm::normalize(glm::cross(this->front, this->worldUp));
this->up = glm::normalize(glm::cross(this->right, this->front));
}
You want to add a behaviour to your camera base maybe on the distance to the object. Maybe add a treshold, if camera.pos - object.pos < d, move the camera else the camera should stay at its position.
For your image you can compute the vector your object is facing.
When you take your "z,q,s,d" input you should move the character and the camera with the same amount

HeightFIeld divided into parts - PhysX

I have a terrain with a specific length and width, which take the information from he file bmp. With Shade of grey i can modify my terrain. Fine, it works great.
Here comes the problem.
I need my terrain divided into physically smaller parts, joined together create the original terrain.
How can i do this? I know that its possible. Any sugestions? Where, why there?
Mys file:
HeightField.cpp
#include "HeightField.h"
HeightField::HeightField(Terrain terrain, PxPhysics& sdk, PxMaterial &material, int width, int height)
{
this->nrVertices = terrain.NumVertices;
this->terrain = terrain;
this->width = width;
this->height = height;
this->fillSamples();
this->fillDesc();
this->aHeightField = sdk.createHeightField(hfDesc);
this->hfGeom = new PxHeightFieldGeometry(aHeightField, PxMeshGeometryFlags(), this->terrain.dy / 255.0, this->terrain.dx, this->terrain.dz);
this->terrainPos = new PxTransform(PxVec3(-this->terrain.dx*(this->width - 1) / 2, 0.0f, this->terrain.dz*(this->height - 1) / 2), PxQuat(3.1415 / 2.0, PxVec3(0, 1, 0)));
this->g_pxHeightField = sdk.createRigidDynamic(*this->terrainPos);
this->g_pxHeightField->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);
PxShape* aHeightFieldShape = this->g_pxHeightField->createShape(*(this->hfGeom), material);
}
HeightField::~HeightField()
{
}
void HeightField::fillSamples()
{
this->samples = (PxHeightFieldSample*)malloc(sizeof(PxHeightFieldSample)*(this->nrVertices));
for (int i = 0; i < this->nrVertices; i++)
{
samples[i].height = this->terrain.hminfo.heightMap[i].y;
samples[i].clearTessFlag();
}
}
void HeightField::fillDesc()
{
this->hfDesc.format = PxHeightFieldFormat::eS16_TM;
this->hfDesc.nbColumns = this->width;
this->hfDesc.nbRows = this->height;
this->hfDesc.samples.data = this->samples;
this->hfDesc.samples.stride = sizeof(PxHeightFieldSample);
}
Terrain.cpp
#include "Terrain.h"
Terrain::Terrain(void)
{
v = NULL;
indices = NULL;
dx = dz = 1000; //odleg³oœæ miêdzy punktami grid'a
dy = 1000; //maksymalna wysokoϾ terenu
}
Terrain::~Terrain(void)
{
if (v != NULL) delete [] v;
if (indices != NULL) delete indices;
if (hminfo.heightMap != NULL) delete [] hminfo.heightMap;
}
bool Terrain::HeightMapLoad(char* filename, float sx, float sz, float maxy)
{
FILE *filePtr; // Point to the current position in the file
BITMAPFILEHEADER bitmapFileHeader; // Structure which stores information about file
BITMAPINFOHEADER bitmapInfoHeader; // Structure which stores information about image
int imageSize, index;
unsigned char height;
// Open the file
filePtr = fopen(filename,"rb");
if (filePtr == NULL)
return 0;
dx = sz;
dz = sz;
dy = maxy;
// Get the width and height (width and length) of the image
hminfo.terrainWidth = bitmapInfoHeader.biWidth;
hminfo.terrainHeight = bitmapInfoHeader.biHeight;
// Initialize the heightMap array (stores the vertices of our terrain)
hminfo.heightMap = new IntV3[hminfo.terrainWidth * hminfo.terrainHeight];
// We use a greyscale image, so all 3 rgb values are the same, but we only need one for the height
// So we use this counter to skip the next two components in the image data (we read R, then skip BG)
int k=0;
// Read the image data into our heightMap array
for(int j=0; j< hminfo.terrainHeight; j++)
{
for(int i=0; i< hminfo.terrainWidth; i++)
{
height = bitmapImage[k];
index = ( hminfo.terrainWidth * (hminfo.terrainHeight - 1 - j)) + i;
hminfo.heightMap[index].x = i - (hminfo.terrainWidth - 1)/2;
hminfo.heightMap[index].y = height;
hminfo.heightMap[index].z = j - (hminfo.terrainHeight - 1)/2;
k+=3;
}
k++;
}
int cols = hminfo.terrainWidth;
int rows = hminfo.terrainHeight;
//Create the grid
NumVertices = 2 * rows * cols;
NumFaces = (rows-1)*(cols-1)*2;
v = new struct HeightFieldVertex[NumVertices];
for(DWORD i = 0; i < rows; ++i)
{
for(DWORD j = 0; j < cols; ++j)
{
v[i*cols+j].pos.x = hminfo.heightMap[i*cols+j].x * dx;
v[i*cols+j].pos.y = (float(hminfo.heightMap[i*cols+j].y)/255.0) * dy;
v[i*cols+j].pos.z = hminfo.heightMap[i*cols+j].z * dz;
v[i*cols+j].texCoord = D3DXVECTOR2(j, i);
}
}
indices = new DWORD[NumFaces * 3];
k = 0;
for(DWORD i = 0; i < rows-1; i++)
{
for(DWORD j = 0; j < cols-1; j++)
{
indices[k] = i*cols+j; // Bottom left of quad
indices[k+1] = i*cols+j+1; // Bottom right of quad
indices[k+2] = (i+1)*cols+j; // Top left of quad
indices[k+3] = (i+1)*cols+j; // Top left of quad
indices[k+4] = i*cols+j+1; // Bottom right of quad
indices[k+5] = (i+1)*cols+j+1; // Top right of quad
k += 6; // next quad
}
}
//normals & tangents
std::vector<D3DXVECTOR3> tempNormal;
//normalized and unnormalized normals
D3DXVECTOR3 unnormalized(0.0f, 0.0f, 0.0f);
//tangent stuff
std::vector<D3DXVECTOR3> tempTangent;
D3DXVECTOR3 tangent(0.0f, 0.0f, 0.0f);
float tcU1, tcV1, tcU2, tcV2;
//Used to get vectors (sides) from the position of the verts
float vecX, vecY, vecZ;
//Two edges of our triangle
D3DXVECTOR3 edge1(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 edge2(0.0f, 0.0f, 0.0f);
//Compute face normals
//And Tangents
for(int i = 0; i < NumFaces; ++i)
{
//Get the vector describing one edge of our triangle (edge 0,2)
vecX = v[indices[(i*3)+1]].pos.x - v[indices[(i*3)]].pos.x;
vecY = v[indices[(i*3)+1]].pos.y - v[indices[(i*3)]].pos.y;
vecZ = v[indices[(i*3)+1]].pos.z - v[indices[(i*3)]].pos.z;
edge1 = D3DXVECTOR3(vecX, vecY, vecZ); //Create our first edge
//Get the vector describing another edge of our triangle (edge 2,1)
vecX = v[indices[(i*3)+2]].pos.x - v[indices[(i*3)]].pos.x;
vecY = v[indices[(i*3)+2]].pos.y - v[indices[(i*3)]].pos.y;
vecZ = v[indices[(i*3)+2]].pos.z - v[indices[(i*3)]].pos.z;
edge2 = D3DXVECTOR3(vecX, vecY, vecZ); //Create our second edge
//Cross multiply the two edge vectors to get the un-normalized face normal
D3DXVec3Cross(&unnormalized, &edge1, &edge2);
tempNormal.push_back(unnormalized);
//Find first texture coordinate edge 2d vector
tcU1 = v[indices[(i*3)+1]].texCoord.x - v[indices[(i*3)]].texCoord.x;
tcV1 = v[indices[(i*3)+1]].texCoord.y - v[indices[(i*3)]].texCoord.y;
//Find second texture coordinate edge 2d vector
tcU2 = v[indices[(i*3)+2]].texCoord.x - v[indices[(i*3)]].texCoord.x;
tcV2 = v[indices[(i*3)+2]].texCoord.y - v[indices[(i*3)]].texCoord.y;
//Find tangent using both tex coord edges and position edges
tangent.x = (tcV2 * edge1.x - tcV1 * edge2.x) / (tcU1 * tcV2 - tcU2 * tcV1);
tangent.y = (tcV2 * edge1.y - tcV1 * edge2.y) / (tcU1 * tcV2 - tcU2 * tcV1);
tangent.z = (tcV2 * edge1.z - tcV1 * edge2.z) / (tcU1 * tcV2 - tcU2 * tcV1);
tempTangent.push_back(tangent);
}
//Compute vertex normals (normal Averaging)
D3DXVECTOR4 normalSum(0.0f, 0.0f, 0.0f, 0.0f);
D3DXVECTOR4 tangentSum(0.0f, 0.0f, 0.0f, 0.0f);
int facesUsing = 0;
float tX, tY, tZ; //temp axis variables
//Go through each vertex
for(int i = 0; i < NumVertices; ++i)
{
//Check which triangles use this vertex
for(int j = 0; j < NumFaces; ++j)
{
if(indices[j*3] == i ||
indices[(j*3)+1] == i ||
indices[(j*3)+2] == i)
{
tX = normalSum.x + tempNormal[j].x;
tY = normalSum.y + tempNormal[j].y;
tZ = normalSum.z + tempNormal[j].z;
normalSum = D3DXVECTOR4(tX, tY, tZ, 0.0f); //If a face is using the vertex, add the unormalized face normal to the normalSum
facesUsing++;
}
}
//Get the actual normal by dividing the normalSum by the number of faces sharing the vertex
normalSum = normalSum / facesUsing;
facesUsing = 0;
//Check which triangles use this vertex
for(int j = 0; j < NumFaces; ++j)
{
if(indices[j*3] == i ||
indices[(j*3)+1] == i ||
indices[(j*3)+2] == i)
{
//We can reuse tX, tY, tZ to sum up tangents
tX = tangentSum.x + tempTangent[j].x;
tY = tangentSum.y + tempTangent[j].y;
tZ = tangentSum.z + tempTangent[j].z;
tangentSum = D3DXVECTOR4(tX, tY, tZ, 0.0f); //sum up face tangents using this vertex
facesUsing++;
}
}
//Get the actual normal by dividing the normalSum by the number of faces sharing the vertex
tangentSum = tangentSum / facesUsing;
//Normalize the normalSum vector and tangent
D3DXVec4Normalize(&normalSum, &normalSum);
D3DXVec4Normalize(&tangentSum, &tangentSum);
//Store the normal and tangent in our current vertex
v[i].normal.x = normalSum.x;
v[i].normal.y = normalSum.y;
v[i].normal.z = normalSum.z;
v[i].tangent.x = tangentSum.x;
v[i].tangent.y = tangentSum.y;
v[i].tangent.z = tangentSum.z;
D3DXVECTOR3 bit;
D3DXVec3Cross(&bit, &v[i].normal, &v[i].tangent);
v[i].bitangent = -1.0 * bit;
//Clear normalSum, tangentSum and facesUsing for next vertex
normalSum = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
tangentSum = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
facesUsing = 0;
}
////terrain AABB
//MinX = -1.0 * dx * (hminfo.terrainWidth - 1)/2;
//MinY = 0.0;
//MinZ = -1.0 * dz * (hminfo.terrainHeight - 1)/2;
//MaxX = dx * (hminfo.terrainWidth - 1)/2;
//MaxY = dy;
//MaxZ = dz * (hminfo.terrainHeight - 1)/2;
return true;
}
Fragment of Base.cpp
HeightField *hf = new HeightField(g_Terrain, *g_PhysicsSDK, *material, g_Terrain.hminfo.terrainWidth, g_Terrain.hminfo.terrainHeight);
g_PxScene->addActor(*(hf->g_pxHeightField));
I want to get something similar, but in order to work correctly
PVD - simulation Terrain
If you are familiar with the website rastertek for working with DirectX 10 or 11 in c++ within his updated DirectX 11 Terrain Series or version 2 a similar construct was created in tutorial 9 in which he calls Terrain Cells. The direct link to that tutorial can be found here: DirectX 11: Terrain Series2: Tutorial 9 - Terrain Cells. This should provide an excellent reference that I think is related toward the topic at hand and your initial question.

Drawing a circle in c++ using openGL

I've been trying to draw a circle in c++ using openGL. So far i have a compresses circle and it just has a random line going across the screen.
This is the function I'm using to get this shape.
void Sprite::init(int x, int y, int width, int height, Type mode, float scale) {
_x = x;
_y = y;
_width = width;
_height = height;
//generate buffer if it hasn't been generated
if (_vboID == 0) {
glGenBuffers(1, &_vboID);
}
Vertex vertexData[360];
if (mode == Type::CIRCLE) {
float rad = 3.14159;
for (int i = 0; i < 359; i++) {
vertexData[i].setPosition((rad * scale) * cos(i), (rad * scale) * sin(i));
}
}
//Tell opengl to bind our vertex buffer object
glBindBuffer(GL_ARRAY_BUFFER, _vboID);
//Upload the data to the GPU
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
//Unbind the buffer
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
What is causing the line? Why is my circle being compressed?
Sorry if this is a dumb question or if this question doesn't belong on this website I'm very new to both c++ as well as this website.
It is difficult to be sure without testing the code myself, but I'll guess anyway.
Your weird line is probably caused by the buffer not being fully initialized. This is wrong:
Vertex vertexData[360];
for (int i = 0; i < 359; i++) {
It should be:
for (int i = 0; i < 360; i++) {
or else the position at vertexData[359] is left uninitialized and contains some far away point.
About the ellipse instead of a circle, that is probably caused by your viewport not having the same scale horizontally and vertically. If you configure the viewport plus transformation matrices to have a viewing frustum of X=-10..10, Y=-10..10, but the actual viewport is X=0..800 and the Y=0..600, for example, then the scale would be different and you'll get your image distorted.
The solution would be one of:
Create a square viewport instead of rectangular. Check your arguments to glViewport().
Define a view matrix to consider the same ratio your viewport has. You don't show how you set the view/world matrix, maybe you are not even using matrices... If that is the case, you should probably use one.
I don't understand, exactly, what you want obtain but... cos() and sin() receive a radiant argument; so, instead of cos(i) and sin(i), I suppose you need cos((2*rad*i)/360.0)) and sin((2*rad*i)/360.0)) or, semplified, cos((rad*i)/180.0)) and cos((rad*i)/180.0))
And what about the center and the radious of the circle?
(x, y) should be the center of the circle?
scale is the radious?
In this case, I suppose you should write something like (caution: not tested)
Vertex vertexData[360];
float rad = 3.14159;
if (mode == Type::CIRCLE) {
for (int i = 0; i < 359; ++i) {
float angle = (rad / 180) * i; // (thanks Rodrigo)
vertexData[i].setPosition(x + scale * cos(angle), y + scale * sin(angle));
}
}
or, loosing precision but avoidind some moltiplication,
Vertex vertexData[360];
float rad = 3.14159;
float angIncr = rad / 180.0;
if (mode == Type::CIRCLE) {
for (int i = 0, float angle = 0.0; i < 359; ++i, angle += angIncr) {
vertexData[i].setPosition(x + scale * cos(angle), y + scale * sin(angle));
}
}
But what about width and heigth?
p.s.: sorry for my bad English.
--- modified with suggestion from Rodrigo --