OpenGL: new window displays content of the current window opened - c++

I tried to draw Bezier surface using OpenGL. My program reads an input file with number of sample points for plot, control points and color palette for surface coloring. It must output a new window with surface plot where I can manipulate properties of surface and control points.
Points generated from Bernstein polynomial are triangulated and assigned a color by color palette by mapping it from minimum and maximum height of triangles.
Unfortunately, it opens a window with a portion of the current window opened in OS without creating a new interface for surface.
Here is the code:
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <cmath>
using namespace std;
struct vertex
{
float x;
float y;
float z;
};
struct RGB
{
float r;
float g;
float b;
};
int main_window;
bool TM = true;
vertex surfaceTranslate;
float surfaceRotate = 0;
vertex camera;
vertex up;
int currentPointX = 0, currentPointY = 0;
vertex toY;
int SampleR, SampleC;
int M, N;
int K;
vector < vector <vertex> > points;
vector <RGB> palette;
vector < vector <vertex> > control;
float minH, maxH;
int fact (int n)
{
if (!n || n == 1)
{
return 1;
}
return n * fact (n - 1);
}
int C (int n, int i)
{
return fact (n) / (fact (i) * fact (n - i));
}
void initialDisplay(void)
{
glClearColor (1.0, 1.0, 1.0, 1.0);
glDisable (GL_LIGHTING);
glEnable (GL_RESCALE_NORMAL);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective (60, 1, 1, 1000000);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
}
void updateControl()
{
control.clear();
for (int i = 0; i < SampleR; ++i)
{
vector <vertex> temp;
for (int j = 0; j < SampleC; ++j)
{
float u = (float)(i) / (SampleR - 1);
float v = (float)(j) / (SampleC - 1);
vertex p;
p.x = p.y = p.z = 0;
for (int k = 0; k < M; ++k)
{
for (int m = 0; m < N; ++m)
{
float B_u = float (C (M - 1, k)) * pow (u, k) * pow (1 - u, M - 1 - k);
float B_v = float (C (N - 1, m)) * pow (v, m) * pow (1 - v, N - 1 - m);
p.x += B_u * B_v * points[k][m].x;
p.y += B_u * B_v * points[k][m].y;
p.z += B_u * B_v * points[k][m].z;
}
}
temp.push_back (p);
}
control.push_back (temp);
}
maxH = 1 << ((sizeof(float) * 8) - 1);
minH = -maxH;
for (int i = 0; i < SampleR - 1; ++i)
{
for (int j = 0; j < SampleC - 1; ++j)
{
float h = (control[i][j].y + control[i + 1][j].y + control[i][j + 1].y) / 3;
if (h > maxH)
{
maxH = h;
}
if (h < minH)
{
minH = h;
}
h = (control[i][j + 1].y + control[i + 1][j].y + control[i + 1][j + 1].y) / 3;
if (h > maxH)
{
maxH = h;
}
if (h < minH)
{
minH = h;
}
}
}
for (int i = 0; i < SampleR; ++i)
{
for (int j = 0; j < SampleC; ++j)
{
toY.x += control[i][j].x;
toY.z += control[i][j].z;
}
toY.x /= SampleR * SampleC;
toY.z /= SampleR * SampleC;
}
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt (camera.x, camera.y, camera.z, 0, 0, 0, up.x, up.y, up.z);
glTranslatef (surfaceTranslate.x, surfaceTranslate.y, surfaceTranslate.z);
glTranslatef (toY.x, toY.y, toY.z);
glRotatef (surfaceRotate, 0, 1, 0);
glTranslatef (- toY.x, -toY.y, -toY.z);
if (!TM)
{
glPointSize (10);
glBegin (GL_POINTS);
for (int i = 0; i < M; ++i)
{
for (int j = 0; j < N; ++j)
{
if (i == currentPointX && j == currentPointY)
{
glColor3f (1.0, 0.0, 0.0);
}
else
{
glColor3f (0.0, 0.0, 1.0);
}
glVertex3f (points[i][j].x, points[i][j].y, points[i][j].z);
}
}
glEnd();
}
glBegin (GL_TRIANGLES);
for (int i = 0; i < SampleR - 1; ++i)
{
for (int j = 0; j < SampleC - 1; ++j)
{
glVertex3f (control[i][j].x, control[i][j].y, control[i][j].z);
glVertex3f (control[i + 1][j].x, control[i + 1][j].y, control[i + 1][j].z);
glVertex3f (control[i][j + 1].x, control[i][j + 1].y, control[i][j + 1].z);
float h = (control[i][j].y + control[i + 1][j].y + control[i][j + 1].y) / 3;
int r = (palette[K - 1].r - palette[0].r) * (h - minH) / (maxH - minH);
int g = (palette[K - 1].g - palette[0].g) * (h - minH) / (maxH - minH);
int b = (palette[K - 1].b - palette[0].b) * (h - minH) / (maxH - minH);
glColor3f (palette[r].r / (palette[K - 1].r - palette[0].r), palette[g].g / (palette[K - 1].g - palette[K - 1].g), palette[b].b / (palette[K - 1].b - palette[0].b));
glVertex3f (control[i + 1][j].x, control[i + 1][j].y, control[i + 1][j].z);
glVertex3f (control[i][j + 1].x, control[i][j + 1].y, control[i][j + 1].z);
glVertex3f (control[i + 1][j + 1].x, control[i + 1][j + 1].y, control[i + 1][j + 1].z);
h = (control[i + 1][j].y + control[i][j + 1].y + control[i + 1][j + 1].y) / 3;
r = (palette[K - 1].r - palette[0].r) * (h - minH) / (maxH - minH);
g = (palette[K - 1].g - palette[0].g) * (h - minH) / (maxH - minH);
b = (palette[K - 1].b - palette[0].b) * (h - minH) / (maxH - minH);
glColor3f (palette[r].r / (palette[K - 1].r - palette[0].r), palette[g].g / (palette[K - 1].g - palette[K - 1].g), palette[b].b / (palette[K - 1].b - palette[0].b));
}
}
glEnd();
}
void keyboardEvent (unsigned char key, int x, int y)
{
if (TM)
{
switch (key)
{
case ('2'):
TM = false;
glutSetWindowTitle ("Surface Editing Mode");
break;
case ('q'):
--surfaceTranslate.x;
break;
case ('w'):
++surfaceTranslate.x;
break;
case ('a'):
--surfaceTranslate.y;
break;
case ('s'):
++surfaceTranslate.y;
break;
case ('z'):
--surfaceTranslate.z;
break;
case ('x'):
++surfaceTranslate.z;
break;
case ('r'):
++surfaceRotate;
break;
case ('t'):
--surfaceRotate;
break;
}
}
else
{
switch (key)
{
case ('1'):
TM = true;
glutSetWindowTitle ("Transformation Mode");
break;
case ('q'):
--points[currentPointX][currentPointY].x;
updateControl();
break;
case ('w'):
++points[currentPointX][currentPointY].x;
updateControl();
break;
case ('a'):
--points[currentPointX][currentPointY].y;
updateControl();
break;
case ('s'):
++points[currentPointX][currentPointY].y;
updateControl();
break;
case ('z'):
--points[currentPointX][currentPointY].z;
updateControl();
break;
case ('x'):
++points[currentPointX][currentPointY].z;
updateControl();
break;
case ('i'):
if (!(SampleR % 2))
{
SampleR /= 2;
updateControl();
}
break;
case ('o'):
SampleR *= 2;
updateControl();
break;
case ('k'):
if (!(SampleC % 2))
{
SampleC /= 2;
updateControl();
}
break;
case ('l'):
SampleC *= 2;
updateControl();
break;
case (GLUT_KEY_UP):
if (currentPointY < N - 1)
{
++currentPointY;
}
break;
case (GLUT_KEY_DOWN):
if (currentPointY)
{
--currentPointY;
}
break;
case (GLUT_KEY_LEFT):
if (currentPointX)
{
--currentPointX;
}
break;
case (GLUT_KEY_RIGHT):
if (currentPointX < M - 1)
{
++currentPointX;
}
break;
}
}
glutPostRedisplay();
}
void changeDirection (int x, int y)
{
float dist = sqrt (pow (camera.x, 2) + pow (camera.y, 2) + pow (camera.z, 2));
camera.x = dist * sin (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532);
camera.y = dist * cos (360.0 / 800 * y * 0.0174532);
camera.z = dist * cos (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532);
up.x = dist * sin (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532 - 1) - camera.x;
up.y = dist * cos (360.0 / 800 * y * 0.0174532 - 1) - camera.y;
up.z = dist * cos (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532 - 1) - camera.z;
glutPostRedisplay();
}
void mouseEvent (int key, int state, int x, int y)
{
if (key == GLUT_KEY_LEFT)
{
changeDirection (x, y);
}
}
void readFile (char *fname)
{
ifstream file (fname);
if (file.is_open())
{
file >> SampleR >> SampleC;
file >> M >> N;
for (int i = 0; i < M; ++i)
{
vector <vertex> tempv;
for (int j = 0; j < N; ++j)
{
vertex temp;
file >> temp.x >> temp.y >> temp.z;
tempv.push_back (temp);
}
points.push_back (tempv);
}
file >> K;
for (int i = 0; i < K; ++i)
{
RGB temp;
file >> temp.r >> temp.g >> temp.b;
palette.push_back (temp);
}
}
file.close();
}
int main (int argc, char *argv[])
{
surfaceTranslate.x = surfaceTranslate.y = surfaceTranslate.z = toY.x = toY.y = toY.z = up.x = up.z = 0;
up.y = 1;
camera.x = camera.y = camera.z = 100;
readFile (argv[1]);
updateControl();
glutInit (&argc,argv);
glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition (50, 50);
glutInitWindowSize (800, 800);
main_window = glutCreateWindow ("Transformation Mode");
glutDisplayFunc (display);
glutKeyboardFunc (keyboardEvent);
glutMouseFunc (mouseEvent);
glutMotionFunc (changeDirection);
initialDisplay();
glutMainLoop();
}

You're missing the call to glutSwapBuffers() at the end of your display() function. This is needed to display the frame when using double buffered rendering.

Related

How do I add a wave to a curved surface composed of triangle primatives in C++?

I want to preface this post: This is perhaps more of a math question than a coding question.
I am developing a plant (lettuce) model which involves somewhat complex geometry. At this stage I have a surface curved in 2 dimensions but now I want to add waviness to this curved surface but am having a hard time envisioning how to do so. The surface is made of triangle primatives, the primatives take xyz vectors to encode location of vertices. I am using an API termed HELIOS to develop this procedural model of lettuce. I essentially created the surface with for loops and the sine function. Disclaimer: I do not have a strong background in geometry, computer graphics, or C++.
Here is the relevant code:
#include "Context.h"
#include "Visualizer.h"
using namespace helios;
using namespace std;
vector<uint> addLeaf(float leaf_length, float leaf_width, float leaf_bend_x, float leaf_bend_y, float rotation_z, float rotation_x, float displacement, float radius, Context* context ) {
std::vector<uint> UUIDs;
// float leaf_length = 10;
float Nz = 10; // params.s1_leaf_subdivisions ; number of times to split the dimension
float dz = leaf_length / Nz; // length of each subdivision
// float leaf_width = 10;
float Ny = 10; // params.s1_leaf_subdivisions ; number of times to split the dimension
float dy = leaf_width / Ny; // length of each subdivision
// leaf wave
// float A_3 = leaf_length * float(0.5); // Half waves on the leaf 10
// float A_2 = leaf_length * float(0.1); // amplitude 0.25
float A_3 = 1; // Half waves on the leaf 10
float A_2 = 1; // amplitude 0.25
float leaf_amplitude = leaf_length / float(10);
// the 2 * dx extends the sine wave a bit beyond 1/2 wavelength so base of leaves come together
for (int i = 0; i < Nz + (2 * dz); i++) {
for (float j = 0; j < Ny; j++) {
float z = i * dz; //for each subdivision in z define Z coord
float y = j * dy; //for each subdivision in y define y coord
float x = 0; // we will also need an x coord
float sz = dz; // the next step in z will be equal to a subdivision in z
float sy = dy; // the next step in y will be equal to a subdivision in y
float z_i = z * M_PI / (Nz * dz); // the second coord for z is z_i needed to define a triangle primitive
float sz_i = (z + sz) * M_PI / (Nz * dz); //
// this would be y_1 in sorghum model
float y_i = (y * M_PI / (Ny * dy)) / (A_3); // the second coord for y is y_i needed to define a triangle primitive
float sy_i = ((y + sy) * M_PI / (Ny * dy)) / (A_3);
//waviness of leaf
float leaf_wave_1;
float leaf_wave_2;
float leaf_wave_3;
float leaf_wave_4;
if (j == 0) {
leaf_wave_1 = A_2 * sin(z_i);
leaf_wave_2 = A_2 * sin(sz_i);
} else {
leaf_wave_1 = A_2 * sin(z_i);
leaf_wave_2 = A_2 * sin(sz_i);
}
// Now define x based on z,y and add leaf bend in x and y
x = leaf_bend_x * sin(z_i);
x = ((x*radius + displacement + (leaf_bend_y * sin(y_i))) / 2) + leaf_wave_1;
vec3 v0(x*radius + displacement, y, z);
x = leaf_bend_x * sin(sz_i);
x = ((x*radius + displacement + (leaf_bend_y * sin(y_i))) / 2) + leaf_wave_2;
vec3 v1(x*radius + displacement, y, z + sz);
if (j == Nz - 1) {
leaf_wave_3 = sin(sz_i) * A_2;
leaf_wave_4 = sin(z_i) * A_2;
} else {
leaf_wave_3 = sin(sz_i) * A_2;
leaf_wave_4 = sin(z_i) * A_2;
}
x = leaf_bend_x * sin(sz_i);
x = ((x*radius + displacement + (leaf_bend_y * sin(sy_i))) / 2) + leaf_wave_3 ;
vec3 v2(x*radius + displacement, y + sy, z + sz);
x = leaf_bend_x * sin(z_i);
x = ((x*radius + displacement + (leaf_bend_y * sin(sy_i))) / 2) + leaf_wave_4 ;
vec3 v3(x*radius + displacement, y + sy, z);
// set of two triangles which form a rectangle or square as subunits of leaf
UUIDs.push_back(context->addTriangle(v0, v1, v2, RGB::cyan));
UUIDs.push_back(context->addTriangle(v0, v2, v3, RGB::magenta));
}
}
return UUIDs;
}
// call to functions and build lettuce geometries
int main( void ){
Context context;
float leaf_length = 10;
float leaf_width = 10;
float radius = 1; // additional control leaf curvature
// add leaves one by one; 'i' here is # of leaves external to whorl
for (int i = 0; i < 6; i++) {
if (i == 0)addLeaf(leaf_length, leaf_width, 0.5*leaf_length, 0.5*leaf_width, 4 * M_PI / 9*i, 0, i/5, radius, &context);
// if (i == 1)addLeaf(leaf_length, leaf_width, 0.5*leaf_length, 0.5*leaf_width, 4 * M_PI / 9*i, -M_PI/ 20, i/5, radius, &context);
// if (i == 2)addLeaf(leaf_length, leaf_width, 0.5*leaf_length, 0.5*leaf_width, 4 * M_PI / 9*i, -M_PI/ 10, i/5, radius, &context);
// if (i == 3)addLeaf(leaf_length, leaf_width, 0.5*leaf_length, 0.5*leaf_width, 4 * M_PI / 9*i, -M_PI/ 9, i/5, radius, &context);
// if (i == 4)addLeaf(leaf_length, leaf_width, 0.5*leaf_length, 0.5*leaf_width, 4 * M_PI / 9*i, -M_PI/ 7, i/5, radius, &context);
// if (i == 5)addLeaf(leaf_length, leaf_width, 0.5*leaf_length, 0.5*leaf_width, 4 * M_PI / 9*i, -M_PI/ 5, i/5, radius, &context);
}
Visualizer visualizer(800);
visualizer.buildContextGeometry(&context);
visualizer.setLightingModel(Visualizer::LIGHTING_PHONG);
visualizer.plotInteractive();
}
I tried to use a sine function and an additional for loop to create a series of values to add to the X coordinate of the triangles but did not obtain the result I was looking for.
This is how you can create a Wave Geometry.
you can keep updating the m_fTime values to animate the wave.
// m_iWaveFlowOut -> value to be either 0 or 1
//m_fFrequency -> Number of waves
//m_fAmplitude -> Amplitude of wave
void Generate()
{
const int n8 = m_iNSegments * 8; // size of VBO gfx data
const int sz0 = m_iMSegments * n8; // size of VBO gfx data
const int sz1 = (m_iMSegments - 1) * (m_iNSegments - 1) * 6;// size of indices
verticesRect.clear();
indicesRect.clear();
int a,i, j, k, b;
float x, y, z, dx, dy, l;
glm::vec3 u, v, nor;
dx = 2.0 * ( m_fWidth / float(m_iNSegments - 1));
dy = 2.0 * ( m_fHeight / float(m_iMSegments - 1));
for (a = 0, y = -m_fHeight, j = 0; j < m_iMSegments; j++, y += dy)
for (x = -m_fWidth, i = 0; i < m_iNSegments; i++, x += dx)
{
float dist = glm::length(glm::vec2(x + m_fxOffset, y + m_fyOffset));
float attenuation, kc, kq;
kc = 1.0; kq = 0.0;
attenuation = 1.0f;
if (m_bUseAttenuation) {
attenuation = 1.0 / (kc + (this->m_fKl * dist) + (kq * pow(dist, 2)));
if (attenuation > 1.0) attenuation = 1.0;
}
switch (m_WAVETYPE)
{
case Sum_Wave2::WAVE2_TYPE::COS:
z = (-m_fAmplitude * attenuation) * cos(((x + m_fxOffset) / m_fFrequency) + m_fTime * m_iWaveFlowOut);
break;
case Sum_Wave2::WAVE2_TYPE::SIN:
z = (-m_fAmplitude * attenuation) * sin(((y + m_fyOffset) / m_fFrequency) + m_fTime * m_iWaveFlowOut);
break;
case Sum_Wave2::WAVE2_TYPE::RING:
z = (-m_fAmplitude * attenuation) * sin((glm::length(glm::vec2(x + m_fxOffset, y + m_fyOffset)) + m_fTime * m_iWaveFlowOut) / m_fFrequency);
break;
default:
z = 0.0;
break;
}
verticesRect.push_back(x); a++;
verticesRect.push_back(y); a++;
verticesRect.push_back(z); a++;
// Normal ( will be recomputed later)
verticesRect.push_back(0.0); a++;
verticesRect.push_back(0.0); a++;
verticesRect.push_back(1.0); a++;
// TexCoord
verticesRect.push_back((x + m_fWidth) / (m_fWidth + m_fWidth)); a++;
verticesRect.push_back((y + m_fHeight) / (m_fHeight + m_fHeight)); a++;
}
// triangulation indices
for(a = 0, j = 1; j < m_iMSegments; j++ )
for (i = 1; i < m_iNSegments; i++)
{
b = ((m_iNSegments * j) + i) * 8;
// First triangle per quad
indicesRect.push_back(b - 8); a++;
indicesRect.push_back(b - 8 - n8); a++;
indicesRect.push_back(b); a++;
// Second triangle per quad
indicesRect.push_back(b - 8 - n8); a++;
indicesRect.push_back(b - n8); a++;
indicesRect.push_back(b); a++;
// recompute inner normals
for (k = 0; k < 3; k++) {
u[k] = verticesRect[indicesRect[a - 6] + k] - verticesRect[indicesRect[a - 4] + k];
v[k] = verticesRect[indicesRect[a - 5] + k] - verticesRect[indicesRect[a - 4] + k];
}
glm::vec3 cross1 = crossProduct(u, v);
cross1 = glm::normalize(cross1);
for (k = 0; k < 3; k++) {
u[k] = verticesRect[indicesRect[a - 3] + k] - verticesRect[indicesRect[a - 1] + k];
v[k] = verticesRect[indicesRect[a - 2] + k] - verticesRect[indicesRect[a - 1] + k];
}
glm::vec3 cross2 = crossProduct(u, v);
cross2 = glm::normalize(cross2);
for (k = 0; k < 3; k++) {
verticesRect[indicesRect[a - 1] + 3 + k] = 0.5 * (cross1[k] + cross2[k]);
}
}
for (i = 0; i < sz1; i++) {
indicesRect[i] = indicesRect[i] /= 8;
}
}

Reflection model does not work correctly in OpenGl using glColor3f

I have a depth map as 2D double array 480x640. I visualize it using openGL using glBegin(GL_TRIANGLES).
This is my code, it works correctly:
int main(int argc, char** argv){
ifstream ifs("D:\\DepthMaps1-20\\DepthMap_1.dat", std::ios::binary);
if (ifs) {
double dheight, dwidth;
ifs.read(reinterpret_cast<char*>(&dheight), sizeof dheight);
ifs.read(reinterpret_cast<char*>(&dwidth), sizeof dwidth);
height = static_cast<size_t>(dheight);
width = static_cast<size_t>(dwidth);
vector<vector<double>> dmap(height, vector<double>(width));
for (auto& row : dmap) {
for (double& col : row)
ifs.read(reinterpret_cast<char*>(&col), sizeof col);
}
double fx = 525.0;
double fy = 525.0; // default focal length
double cx = 319.5;
double cy = 239.5; // default optical center
vector<vector<double>> x(height, vector<double>(width));
vector<vector<double>> y(height, vector<double>(width));
vector<vector<double>> z(height, vector<double>(width));
for (unsigned i = 0; i < dmap.size(); i++)
{
for (unsigned j = 0; j < dmap[i].size(); j++)
{
z[i][j] = dmap[i][j] / 500.0;
x[i][j] = (j - cx) * z[i][j] / fx;
y[i][j] = (i - cy) * z[i][j] / fy;
}
}
GLFWwindow * window;
if (!glfwInit())
return -1;
window = glfwCreateWindow(640, 640, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, keyCallback);
while (!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glBegin(GL_TRIANGLES);
glColor3f(189.0/255.0, 140.0 / 255.0, 194.0 / 255.0);
for (unsigned i = 0; i < dmap.size(); i++)
{
for (unsigned j = 0; j < dmap[i].size(); j++)
{
if (j < dmap[i].size() - 2 && i < dmap.size() - 2)
{
if (z[i][j] != 0 && z[i][j + 1] != 0 && z[i + 1][j] != 0 && z[i + 1][j+1] != 0)
{
glVertex3d(x[i][j], y[i][j], z[i][j]);
glVertex3d(x[i][j + 1], y[i][j + 1], z[i][j + 1]);
glVertex3d(x[i + 1][j], y[i + 1][j], z[i + 1][j]);
glVertex3d(x[i][j+1], y[i][j+1], z[i][j+1]);
glVertex3d(x[i + 1][j + 1], y[i + 1][j + 1], z[i + 1][j + 1]);
glVertex3d(x[i + 1][j], y[i + 1][j], z[i + 1][j]);
}
}
}
}
glEnd();
glFlush();
glfwSwapBuffers(window);
glfwPollEvents();
}
ifs.close();
}
return 0;}
So now I need to add lighting using mathematical formulas for reflection model. Idea is - lighting is taken as parallel (unidirectional) beams of the same intensity, the size of the light source is not limited. Illumination is set by the direction L [Lx Ly Lz].
This is my code for Lambert reflection model and it works, but I want better result.
float coord = -1.0f;
float coord1 = -1.0f;
float coord2 = -0.0f;
float coord4 = -1.0f;
float coord5 = -2.0f;
float coord6 = -1.0f;
int main(int argc, char** argv)
{
ifstream ifs("D:\\DepthMaps1-20\\DepthMap_1.dat", std::ios::binary);
if (ifs) {
double dheight, dwidth;
ifs.read(reinterpret_cast<char*>(&dheight), sizeof dheight);
ifs.read(reinterpret_cast<char*>(&dwidth), sizeof dwidth);
height = static_cast<size_t>(dheight);
width = static_cast<size_t>(dwidth);
vector<vector<double>> dmap(height, vector<double>(width));
for (auto& row : dmap) {
for (double& col : row)
ifs.read(reinterpret_cast<char*>(&col), sizeof col);
}
double fx = 525.0;
double fy = 525.0; // default focal length
double cx = 319.5;
double cy = 239.5; // default optical center
vector<vector<double>> x(height, vector<double>(width));
vector<vector<double>> y(height, vector<double>(width));
vector<vector<double>> z(height, vector<double>(width));
vector<vector<int>> brightness(height, vector<int>(width));
for (unsigned i = 0; i < dmap.size(); i++)
{
for (unsigned j = 0; j < dmap[i].size(); j++)
{
z[i][j] = dmap[i][j] / 500.0;
x[i][j] = (j - cx) * z[i][j] / fx;
y[i][j] = (i - cy) * z[i][j] / fy;
}
}
GLFWwindow * window;
if (!glfwInit())
return -1;
window = glfwCreateWindow(640, 640, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, keyCallback);
while (!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(tippangle, 1, 0, 0);
glRotatef(viewangle, 0, 1, 0);
glScalef(scaleF, scaleF, scaleF);
//x
glRasterPos3f(1.1, 0.0, 0.0);
//y
glRasterPos3f(0.0, 1.1, 0.0);
//z
glRasterPos3f(0.0, 0.0, 1.1);
glTranslatef(d[0], d[1], d[2]);
glBegin(GL_TRIANGLES);
for (unsigned i = 0; i < dmap.size(); i++)
{
for (unsigned j = 0; j < dmap[i].size(); j++)
{
if (j < dmap[i].size() - 2 && i < dmap.size() - 2)
{
if (z[i][j] != 0 && z[i][j + 1] != 0 && z[i + 1][j] != 0 && z[i + 1][j + 1] != 0)
{
//Determination of the normal
glm::vec3 left = glm::vec3(0, 1, (z[i][j + 1] - z[i][j+1]));
glm::vec3 right = glm::vec3(1, 0, (z[i + 1][j] - z[i + 1][j]));
glm::vec3 normal = glm::normalize(glm::cross(left, right));
glm::vec3 Position_Light = glm::vec3(coord + 0, coord1+ 0, coord2 + 0); //Light source
glm::vec3 Position_View = glm::vec3(coord4, coord5, coord6); //observer
glm::vec3 Position_Point = glm::vec3(x[i][j], y[i][j], z[i][j]);
//Directions
glm::vec3 Light_Direction = glm::normalize(Position_Light - Position_Point); //To source
glm::vec3 View_Direction = glm::normalize(Position_View - Position_Point); // To the observer
glm::vec3 HalfWay_Direction = glm::normalize(Light_Direction + View_Direction); //Median vector (halfway)
double kd = 1;//diffuse reflectance for the Lambert model
double I = 0; //variable brightness
I = kd * glm::dot(Light_Direction, normal);
glColor3f(I, I, I);
glVertex3d(x[i][j], y[i][j], z[i][j]);
glVertex3d(x[i][j + 1], y[i][j + 1], z[i][j + 1]);
glVertex3d(x[i + 1][j], y[i + 1][j], z[i + 1][j]);
glVertex3d(x[i][j+1], y[i][j+1], z[i][j+1]);
glVertex3d(x[i + 1][j + 1], y[i + 1][j + 1], z[i + 1][j + 1]);
glVertex3d(x[i + 1][j], y[i + 1][j], z[i + 1][j]);
}
}
}
}
glEnd();
glFlush();
glfwSwapBuffers(window);
glfwPollEvents();
}
ifs.close();
}
return 0;
}
This is my result.
And I want this result.
Second result is an example for this work, but using c#. Sourse code here:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
double[,] depth;
int[,] brightness;
bool glConrerolIsLoaded;
float coord = 501.5f;
float coord1 = -17.5f;
float coord2 = -2979.5f;
float coord4 = -73.0f;
float coord5 = 1269.0f;
float coord6 = 413.5f;
int resNum = 0;
private void glControl1_Load(object sender, EventArgs e)
{
glConrerolIsLoaded = true;
GL.ClearColor(Color.Black);
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
glControl1.Invalidate();
panel1.Invalidate();
}
private void numericUpDown2_ValueChanged(object sender, EventArgs e)
{
glControl1.Invalidate();
panel1.Invalidate();
}
private void numericUpDown3_ValueChanged(object sender, EventArgs e)
{
glControl1.Invalidate();
panel1.Invalidate();
}
private void glControl1_Paint(object sender, PaintEventArgs e)
{
GL.LoadIdentity();
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Viewport(0, 0, glControl1.Width, glControl1.Height);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
Matrix4 perspectiveMatrix = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45), glControl1.Width / glControl1.Height, 1.0f, 100.0f);
GL.LoadMatrix(ref perspectiveMatrix);
GL.MatrixMode(MatrixMode.Modelview);
GL.Translate(-25.0, -9.0, -45.0);
GL.Scale(0.04, 0.04, 0.04);
GL.Begin(BeginMode.Points);
for (int i = 0; i < depth.GetLength(0) - 1 ; i++)
{
for (int j = 0; j < depth.GetLength(1) - 1 ; j++)
{
if (depth[i, j] != 0 && depth[i + 1, j] != 0 && /*depth[i + 1, j + 1] != 0 &&*/ depth[i, j + 1] != 0)
{
Vector3 left = new Vector3(0, 1, Convert.ToSingle(depth[i, j + 1]) - Convert.ToSingle(depth[i, j]));
Vector3 right = new Vector3(1, 0, Convert.ToSingle(depth[i + 1, j]) - Convert.ToSingle(depth[i, j]));
Vector3 Normal = Vector3.Normalize(Vector3.Cross(left, right));
Vector3 Position_Light = new Vector3(coord + Convert.ToSingle(numericUpDown1.Value), coord1
+ Convert.ToSingle(numericUpDown2.Value), coord2 + Convert.ToSingle(numericUpDown3.Value));
Vector3 Position_View = new Vector3(coord4, coord5, coord6);
Vector3 Position_Point = new Vector3(i, j, Convert.ToSingle(depth[i, j]));
Vector3 Light_Direction = Vector3.Normalize(Position_Light - Position_Point);
Vector3 View_Direction = Vector3.Normalize(Position_View - Position_Point);
Vector3 HalfWay_Direction = Vector3.Normalize(Light_Direction + View_Direction);
double kd = 1;
double I = 0;
I = kd * Vector3.Dot(Light_Direction, Normal);
GL.Color3(I, I, I);
GL.Vertex3(i, j, depth[i, j]);
}
}
GL.End();
glControl1.SwapBuffers();
}
private void Form1_Load(object sender, EventArgs e)//Считывание карты глубины
{
string path = #"DepthMap_1.dat";
BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open));
double Height1 = reader.ReadDouble();
double Width1 = reader.ReadDouble();
depth = new double[Convert.ToInt16(Height1), Convert.ToInt16(Width1)];
brightness = new int[Convert.ToInt16(Height1), Convert.ToInt16(Width1)];
for (int i = 0; i < depth.GetLength(0); i++)
{
for (int j = 0; j < depth.GetLength(1); j++)
{
depth[i, j] = reader.ReadDouble();
}
}
reader.BaseStream.Close();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
}
}
So my question is what is incorrect in my code? If it light position could you please help me to fix it.
Color is composed of ambient + diffuse + specular. The specular component will add reflection which I think is what you are expecting. The calculations you are doing for color
I_diffuse = kd * glm::dot(Light_Direction, normal);
is just diffuse component.
So what you need will be
I_total = I_diffuse + I_specular;
You already have I_diffuse and you can get I_specular as below,
vec3 viewDir = normalize(viewPos - pointPos);
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 I_specular = specularStrength * spec * Ks;
specularStrength can be used to control the strength of reflection.
Note :
The code you are using looks like in a fixed-function pipeline which is way deprecated. If possible please move it to the programmable pipeline with shaders.
You can follow: https://learnopengl.com/Lighting/Basic-Lighting
I found answer, I made mistake here:
//Determination of the normal
glm::vec3 left = glm::vec3(0, 1, (z[i][j + 1] - z[i][j+1]));
glm::vec3 right = glm::vec3(1, 0, (z[i + 1][j] - z[i + 1][j]));
It should be like this:
//Determination of the normal
glm::vec3 left = glm::vec3(0, 1, (z[i][j + 1] - z[i][j]));
glm::vec3 right = glm::vec3(1, 0, (z[i + 1][j] - z[i][j]));

How to draw a 45x45 grid with SDL

I am trying to make a grid of 45x45 in SDL but I am not so sure how to do it. Should I use SDL_RenderDrawLine? If so how should I use it inside my void ParticleManager::renderGrid(SDL_Renderer* renderer) function?
#include <iostream>
#include <vector>
#include <string>
#include <cassert>
#include <SDL.h>
#include "Constants.h"
#include "ParticleManager.h"
using namespace std;
Particle::Particle(double _x, double _y) :
x(_x), y(_y),
vx(0.f), vy(0.f),
fx(0.f), fy(0.f),
rho(0.f), p(0.f)
{
}
ParticleManager::ParticleManager()
{
ax = 0;
ay = GRAVITY;
renderMode = "particles";
}
void ParticleManager::init(unsigned long n)
{
cout << "Init with " << n << " particles" << endl;
particles.clear();
particles.reserve(n);
while (particles.size() < n) {
double x = rand() / (double)(RAND_MAX)*SCREEN_WIDTH;
double y = rand() / (double)(RAND_MAX)*SCREEN_HEIGHT;
double centerDist = sqrt(
pow(x - SCREEN_WIDTH / 2.0, 2) +
pow(y - SCREEN_HEIGHT / 2.0, 2));
if (centerDist < fmin(SCREEN_WIDTH, SCREEN_HEIGHT) * 0.25)
particles.push_back(Particle(x, y));
}
}
void ParticleManager::addBlock(double center_x, double center_y)
{
for (int i = 0; i <= 4; i++) {
for (int j = 0; j <= 4; j++) {
double x = center_x + (j - 2) * SCREEN_WIDTH * 0.04f + (rand() / (double)(RAND_MAX)) * H;
double y = center_y + (i - 2) * SCREEN_HEIGHT * 0.04f + (rand() / (double)(RAND_MAX)) * H;
if (x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT)
particles.push_back(Particle(x, y));
}
}
cout << particles.size() << " particles" << endl;
}
void ParticleManager::addOne(double x, double y)
{
particles.push_back(Particle(x, y));
cout << particles.size() << " particles" << endl;
}
void ParticleManager::setGravity(int direction)
{
switch (direction) {
case DOWN:
ax = 0;
ay = +GRAVITY;
break;
case UP:
ax = 0;
ay = -GRAVITY;
break;
case RIGHT:
ax = +GRAVITY;
ay = 0;
break;
default:
ax = -GRAVITY;
ay = 0;
}
}
void ParticleManager::explode() {
for (auto& p : particles) {
p.vx = rand() / (double)RAND_MAX * 10000 - 5000;
p.vy = rand() / (double)RAND_MAX * 10000 - 5000;
}
}
void ParticleManager::integrate(double dt)
{
for (auto& p : particles)
{
// forward Euler integration
if (p.rho != 0 && p.fx == p.fx && p.fy == p.fy) {
p.vx += dt * p.fx / p.rho;
p.vy += dt * p.fy / p.rho;
}
p.x += dt * p.vx;
p.y += dt * p.vy;
// enforce boundary conditions
if (p.x - PARTICLE_RADIUS < 0.0f)
{
p.vx *= BOUND_DAMPING;
p.x = PARTICLE_RADIUS;
}
if (p.x + PARTICLE_RADIUS > SCREEN_WIDTH)
{
p.vx *= BOUND_DAMPING;
p.x = SCREEN_WIDTH - PARTICLE_RADIUS;
}
if (p.y - PARTICLE_RADIUS < 0.0f)
{
p.vy *= BOUND_DAMPING;
p.y = PARTICLE_RADIUS;
}
if (p.y + PARTICLE_RADIUS > SCREEN_HEIGHT)
{
p.vy *= BOUND_DAMPING;
p.y = SCREEN_HEIGHT - PARTICLE_RADIUS;
}
}
}
void ParticleManager::computeDensityPressure()
{
// for each particles
for (auto& pi : particles)
{
pi.rho = 0.f;
// Find all the particles that contribute to the
// pressure / density
for (auto& pj : particles)
{
double distance = sqrt(
pow(pj.x - pi.x, 2) +
pow(pj.y - pi.y, 2));
if (distance < H)
{
// this computation is symmetric
pi.rho += MASS * POLY6 * pow(pow(H, 2) - pow(distance, 2), 3.f);
}
}
pi.p = GAS_CONST * (pi.rho - REST_DENS);
}
}
void ParticleManager::computeForces()
{
// For each particle
for (auto& pi : particles) {
double pressure_x = 0.f;
double pressure_y = 0.f;
double viscosity_x = 0.f;
double viscosity_y = 0.f;
// Calculate the sum of the viscosity and pressure forces
// applied by the other particles
for (auto& pj : particles) {
if (&pi == &pj)
continue;
double r = sqrt(
pow(pj.x - pi.x, 2) +
pow(pj.y - pi.y, 2));
if (r < H) {
// compute pressure force contribution
double fpress = MASS * (pi.p + pj.p) / (2.0 * pj.rho) * SPIKY_GRAD * pow(H - r, 2.0);
pressure_x += (pi.x - pj.x) / r * fpress;
pressure_y += (pi.y - pj.y) / r * fpress;
// compute viscosity force contribution
viscosity_x += VISC * MASS * (pj.vx - pi.vx) / pj.rho * VISC_LAP * (H - r);
viscosity_y += VISC * MASS * (pj.vy - pi.vy) / pj.rho * VISC_LAP * (H - r);
}
}
pi.fx = pressure_x + viscosity_x + ax * pi.rho;
pi.fy = pressure_y + viscosity_y + ay * pi.rho;
}
}
void ParticleManager::update(unsigned long dt)
{
// TODO: calculate the grid here
computeDensityPressure();
computeForces();
integrate(dt / 10000.0f);
}
void ParticleManager::renderParticles(SDL_Renderer* renderer) {
SDL_SetRenderDrawColor(renderer, 230, 120, 0, 100);
SDL_Rect r;
// Draw particles
for (long unsigned int i = 0; i < particles.size(); i++) {
r.x = (int)(particles[i].x - PARTICLE_RADIUS);
r.y = (int)(particles[i].y - PARTICLE_RADIUS);
r.w = (int)(PARTICLE_RADIUS * 2);
r.h = (int)(PARTICLE_RADIUS * 2);
SDL_RenderFillRect(renderer, &r);
}
}
void ParticleManager::renderGrid(SDL_Renderer* renderer) {
// TODO: Draw the lines that form the grid
cout << "Affichage de la grile (TODO)" << endl;
}
void ParticleManager::renderCells(SDL_Renderer* renderer) {
// TODO: Draw the boxes in different colors to
// represent the number of particles in each cell
//
// Use the calculation:
// int alpha = nb_particles * 255/5;
// if (alpha> 255) alpha = 255;
// SDL_SetRenderDrawColor (renderer, 0, 0, 255, alpha);
//
// To assign the color to the cell
cout << "Affichage des cellules (TODO)" << endl;
}
void ParticleManager::render(SDL_Renderer* renderer)
{
if (renderMode.find("particle") != string::npos)
renderParticles(renderer);
if (renderMode.find("grid") != string::npos) {
renderCells(renderer);
renderGrid(renderer);
}
}
The end result should look like this:

OpenGL: Bezier surface with triangulation

I tried to draw Bezier surface using OpenGL. My program reads an input file with number of sample points for plot, control points and color palette for surface coloring. It must output a new window with surface plot where I can manipulate properties of surface and control points.
Points generated from Bernstein polynomial are triangulated and assigned a color by color palette by mapping it from minimum and maximum height of triangles.
When I execute it, one row of triangles is assigned with a wrong color. I thought that I have an error in one of my loops but changing values proved nothing.
Here is the code:
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <cmath>
using namespace std;
struct vertex
{
float x;
float y;
float z;
};
struct RGB
{
float r;
float g;
float b;
};
int main_window;
bool TM = true;
vertex surfaceTranslate;
float surfaceRotate = 0;
vertex camera;
vertex up;
int currentPointX = 0, currentPointY = 0;
vertex toY;
int SampleR, SampleC;
int M, N;
int K;
vector < vector <vertex> > points;
vector <RGB> palette;
vector < vector <vertex> > control;
float minH, maxH;
int fact (int n)
{
if (!n || n == 1)
{
return 1;
}
return n * fact (n - 1);
}
int C (int n, int i)
{
return fact (n) / (fact (i) * fact (n - i));
}
void initialDisplay(void)
{
glClearColor (1.0, 1.0, 1.0, 1.0);
glDisable (GL_LIGHTING);
glEnable (GL_RESCALE_NORMAL);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective (60, 1, 1, 1000000);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
}
void updateControl()
{
control.clear();
for (int i = 0; i < SampleR; ++i)
{
vector <vertex> temp;
for (int j = 0; j < SampleC; ++j)
{
float u = (float)(i) / (SampleR - 1);
float v = (float)(j) / (SampleC - 1);
vertex p;
p.x = p.y = p.z = 0;
for (int k = 0; k < M; ++k)
{
for (int m = 0; m < N; ++m)
{
float B_u = C (M - 1, k) * pow (u, k) * pow (1 - u, M - 1 - k);
float B_v = C (N - 1, m) * pow (v, m) * pow (1 - v, N - 1 - m);
p.x += B_u * B_v * points[k][m].x;
p.y += B_u * B_v * points[k][m].y;
p.z += B_u * B_v * points[k][m].z;
}
}
temp.push_back (p);
}
control.push_back (temp);
}
maxH = 1 << ((sizeof(float) * 8) - 1);
minH = -maxH;
for (int i = 0; i < SampleR - 1; ++i)
{
for (int j = 0; j < SampleC - 1; ++j)
{
float h = (control[i][j].y + control[i + 1][j].y + control[i][j + 1].y) / 3;
if (h > maxH)
{
maxH = h;
}
if (h < minH)
{
minH = h;
}
h = (control[i + 1][j].y + control[i][j + 1].y + control[i + 1][j + 1].y) / 3;
if (h > maxH)
{
maxH = h;
}
if (h < minH)
{
minH = h;
}
}
}
for (int i = 0; i < SampleR; ++i)
{
for (int j = 0; j < SampleC; ++j)
{
toY.x += control[i][j].x;
toY.z += control[i][j].z;
}
toY.x /= SampleR * SampleC;
toY.z /= SampleR * SampleC;
}
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt (camera.x, camera.y, camera.z, 0, 0, 0, up.x, up.y, up.z);
glTranslatef (surfaceTranslate.x, surfaceTranslate.y, surfaceTranslate.z);
glTranslatef (toY.x, toY.y, toY.z);
glRotatef (surfaceRotate, 0, 1, 0);
glTranslatef (- toY.x, -toY.y, -toY.z);
if (!TM)
{
glPointSize (10);
glBegin (GL_POINTS);
for (int i = 0; i < M; ++i)
{
for (int j = 0; j < N; ++j)
{
if (i == currentPointX && j == currentPointY)
{
glColor3f (1.0, 0.0, 0.0);
}
else
{
glColor3f (0.0, 0.0, 1.0);
}
glVertex3f (points[i][j].x, points[i][j].y, points[i][j].z);
}
}
glEnd();
}
glBegin (GL_TRIANGLES);
for (int i = 0; i < SampleR - 1; ++i)
{
for (int j = 0; j < SampleC - 1; ++j)
{
glVertex3f (control[i][j].x, control[i][j].y, control[i][j].z);
glVertex3f (control[i + 1][j].x, control[i + 1][j].y, control[i + 1][j].z);
glVertex3f (control[i][j + 1].x, control[i][j + 1].y, control[i][j + 1].z);
float h = (control[i][j].y + control[i + 1][j].y + control[i][j + 1].y) / 3;
int index = K * (h - minH) / (maxH - minH);
glColor3f (palette[index].r / 255, palette[index].g / 255, palette[index].b / 255);
glVertex3f (control[i + 1][j].x, control[i + 1][j].y, control[i + 1][j].z);
glVertex3f (control[i][j + 1].x, control[i][j + 1].y, control[i][j + 1].z);
glVertex3f (control[i + 1][j + 1].x, control[i + 1][j + 1].y, control[i + 1][j + 1].z);
h = (control[i + 1][j].y + control[i][j + 1].y + control[i + 1][j + 1].y) / 3;
index = K * (h - minH) / (maxH - minH);
glColor3f (palette[index].r / 255, palette[index].g / 255, palette[index].b / 255);
}
}
glEnd();
glutSwapBuffers();
}
void keyboardEvent (unsigned char key, int x, int y)
{
if (TM)
{
switch (key)
{
case ('2'):
TM = false;
glutSetWindowTitle ("Surface Editing Mode");
break;
case ('q'):
--surfaceTranslate.x;
break;
case ('w'):
++surfaceTranslate.x;
break;
case ('a'):
--surfaceTranslate.y;
break;
case ('s'):
++surfaceTranslate.y;
break;
case ('z'):
--surfaceTranslate.z;
break;
case ('x'):
++surfaceTranslate.z;
break;
case ('r'):
++surfaceRotate;
break;
case ('t'):
--surfaceRotate;
break;
}
}
else
{
switch (key)
{
case ('1'):
TM = true;
glutSetWindowTitle ("Transformation Mode");
break;
case ('q'):
--points[currentPointX][currentPointY].x;
updateControl();
break;
case ('w'):
++points[currentPointX][currentPointY].x;
updateControl();
break;
case ('a'):
--points[currentPointX][currentPointY].y;
updateControl();
break;
case ('s'):
++points[currentPointX][currentPointY].y;
updateControl();
break;
case ('z'):
--points[currentPointX][currentPointY].z;
updateControl();
break;
case ('x'):
++points[currentPointX][currentPointY].z;
updateControl();
break;
case ('i'):
if (!(SampleR % 2))
{
SampleR /= 2;
updateControl();
}
break;
case ('o'):
SampleR *= 2;
updateControl();
break;
case ('k'):
if (!(SampleC % 2))
{
SampleC /= 2;
updateControl();
}
break;
case ('l'):
SampleC *= 2;
updateControl();
break;
}
}
glutPostRedisplay();
}
void arrowKeys (int key, int x, int y)
{
if (!TM)
{
switch (key)
{
case (GLUT_KEY_UP):
if (currentPointY < N - 1)
{
++currentPointY;
}
break;
case (GLUT_KEY_DOWN):
if (currentPointY)
{
--currentPointY;
}
break;
case (GLUT_KEY_LEFT):
if (currentPointX)
{
--currentPointX;
}
break;
case (GLUT_KEY_RIGHT):
if (currentPointX < M - 1)
{
++currentPointX;
}
break;
}
glutPostRedisplay();
}
}
void changeDirection (int x, int y)
{
float dist = sqrt (pow (camera.x, 2) + pow (camera.y, 2) + pow (camera.z, 2));
camera.x = dist * sin (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532);
camera.y = dist * cos (360.0 / 800 * y * 0.0174532);
camera.z = dist * cos (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532);
up.x = dist * sin (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532 - 1) - camera.x;
up.y = dist * cos (360.0 / 800 * y * 0.0174532 - 1) - camera.y;
up.z = dist * cos (360.0 / 800 * x * 0.0174532) * sin (360.0 / 800 * y * 0.0174532 - 1) - camera.z;
glutPostRedisplay();
}
void mouseEvent (int key, int state, int x, int y)
{
if (key == GLUT_KEY_LEFT)
{
changeDirection (x, y);
}
}
void readFile (char *fname)
{
ifstream file (fname);
if (file.is_open())
{
file >> SampleR >> SampleC;
file >> M >> N;
for (int i = 0; i < M; ++i)
{
vector <vertex> tempv;
for (int j = 0; j < N; ++j)
{
vertex temp;
file >> temp.x >> temp.y >> temp.z;
tempv.push_back (temp);
}
points.push_back (tempv);
}
file >> K;
for (int i = 0; i < K; ++i)
{
RGB temp;
file >> temp.r >> temp.g >> temp.b;
palette.push_back (temp);
}
}
file.close();
}
int main (int argc, char *argv[])
{
surfaceTranslate.x = surfaceTranslate.y = surfaceTranslate.z = toY.x = toY.y = toY.z = up.x = up.z = 0;
up.y = 1;
camera.x = camera.y = camera.z = 100;
readFile (argv[1]);
updateControl();
glutInit (&argc,argv);
glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition (50, 50);
glutInitWindowSize (800, 800);
main_window = glutCreateWindow ("Transformation Mode");
glutDisplayFunc (display);
glutKeyboardFunc (keyboardEvent);
glutSpecialFunc (arrowKeys);
glutMouseFunc (mouseEvent);
glutMotionFunc (changeDirection);
initialDisplay();
glutMainLoop();
}
Two things are problematic in display():
glColor3f should be called before the calls to glVertex3f to color them
your palette index calculation is wrong when h == maxH, it makes an out of bounds access
When h == maxH, (h - minH)/(maxH - minH) equals 1.0f, which means the line:
index = K * (h - minH) / (maxH - minH);
simplifies into:
index = K;
and K is the size of the palette. An easy fix would be to add a call to min(), like that:
index = min(K-1, K * (h - minH) / (maxH - minH));

Opencv Mat - Access violation error c++

I'm implementing an algorithm, I excuse myself for the extreme for looping, haven't found a better way yet.
The problem is that at the second iteration at line 81 it gives a First-chance exception at 0x000000007707320E (ntdll.dll) in Test.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
void co_hog(Mat image, int offset, int blockSize, int nrBins, int cat) {
Mat img_x;
Mat img_y;
IplImage img = image;
Mat kern_x = (Mat_<char>(1, 3) << -1, 0, 1);
Mat kern_y = (Mat_<char>(3, 1) << -1, 0, 1);
filter2D(image, img_x, image.depth(), kern_x);
filter2D(image, img_y, image.depth(), kern_y);
Size imageSize = image.size();
int nrBlocksY = imageSize.height / blockSize;
int nrBlocksX = imageSize.width / blockSize;
int degreePerBin = 180 / nrBins;
Mat gradients = Mat(image.size(), CV_32FC1);
Mat magnitudes = Mat(image.size(), CV_32FC1);
for(int y = 0; y < image.rows; y++) {
for(int x = 0; x < image.cols; x++) {
float grad_x = (float)img_x.at<uchar>(y, x);
float grad_y = (float)img_y.at<uchar>(y, x);
gradients.at<float>(y, x) = abs(atan2(grad_y, grad_x) * 180 / PI);
magnitudes.at<float>(y, x) = sqrt(pow(grad_x, 2) + pow(grad_y, 2));
}
}
int bin_1, bin_2, bin_3, bin_4;
double theta_1, theta_2, theta_3, theta_4;
Mat H;
stringstream line(stringstream::in | stringstream::out);
line << cat << " ";
int index = 1;
for(int i = 0; i < nrBlocksY; i++) {
for(int j = 0; j < nrBlocksX; j++) {
Mat coOccMat = Mat::zeros(nrBins, nrBins, CV_32FC1);
for(int q = i * blockSize; q < (i * blockSize) + blockSize; q++) {
for(int p = j * blockSize; p < (j * blockSize) + blockSize; p++) {
for(int offy = -offset; offy < offset; offy++) {
for(int offx = -offset; offx < offset; offx++) {
if((q + offy) >= imageSize.height || (p + offx) >= imageSize.width || (q + offy) < 0 || (p + offx) < 0) {
continue;
}
float m_1 = magnitudes.at<float>(q, p);
float m_2 = magnitudes.at<float>(q + offy, p + offx);
float alpha = gradients.at<float>(q, p);
float beta = gradients.at<float>(q + offy, p + offx);
if(fmod(alpha / degreePerBin, 1) > 0.5) {
bin_1 = floor(alpha / degreePerBin);
bin_2 = bin_1 + 1;
} else {
bin_2 = floor(alpha / degreePerBin);
bin_1 = bin_2 - 1;
}
if(fmod(beta / degreePerBin, 1) > 0.5) {
bin_3 = floor(beta / degreePerBin);
bin_4 = bin_3 + 1;
} else {
bin_4 = floor(beta / degreePerBin);
bin_3 = bin_4 - 1;
}
theta_1 = (bin_1 * degreePerBin) + (degreePerBin / 2);
theta_2 = (bin_2 * degreePerBin) + (degreePerBin / 2);
theta_3 = (bin_3 * degreePerBin) + (degreePerBin / 2);
theta_4 = (bin_4 * degreePerBin) + (degreePerBin / 2);
coOccMat.at<float>(bin_1, bin_3) += (m_1 * (1 - (alpha - theta_1) / (theta_2 - theta_1))) + (m_2 * (1 - (beta - theta_3) / (theta_4 - theta_1)));
coOccMat.at<float>(bin_1, bin_4) += (m_1 * (1 - (alpha - theta_1) / (theta_2 - theta_1))) + (m_2 * ((beta - theta_3) / (theta_4 - theta_1)));
coOccMat.at<float>(bin_2, bin_3) += (m_1 * ((alpha - theta_1) / (theta_2 - theta_1))) + (m_2 * (1 - (beta - theta_3) / (theta_4 - theta_1)));
coOccMat.at<float>(bin_2, bin_4) += (m_1 * ((alpha - theta_1) / (theta_2 - theta_1))) + (m_2 * ((beta - theta_3) / (theta_4 - theta_1)));
}
}
}
}
cout << coOccMat << endl;
-> Next statement to be called *passes the first time* H = coOccMat.reshape(0, 1);
normalize(H, H);
cout << H.size() << endl;
for(int i = 0; i < H.cols; ++i) {
for(int j = 0; j < H.rows; ++j) {
if(H.at<float>(j, i) > 0) {
line << index << ":" << H.at<float>(j, i) << " ";
}
index++;
}
}
cout << "Done" << index << endl;
}
}
}
Problem has been fixed, sometimes the value for a bin was set on -1 so it couldn't access it, debugging tools of visual studio couldn't point out where it went wrong.