Related
It is necessary to create N rectangles using two upper left and bottom right points. Then find the area of the largest rectangle (rectangle with the largest area = biggest rectangle) and determine whether other rectangles are inside the largest one if not, then display the appropriate message.
I've already have code which generates N rectangles and determines the largest area among them, but the main problem is to find out if there are smaller rectangles in the biggest one.
Let's simulate the situation:
Rectangle 1 A - (topLeft.x topLeft.y) , B - (botRight.x botRight.y)
Rectangle 2 C - (topLeft.x topLeft.y) , D - (botRight.x botRight.y)
If a rectangle contains another rectangle, then
A(y)>C(y) && A(x)<C(x) && B(y)<D(y) && B(x)>D(y)
Looks easy, but how to implement this algorithm for 20 rectangles, for instance?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 20
struct Point {
int x;
int y;
};
struct Rectangle {
struct Point topLeft;
struct Point botRight;
int area;
};
int Area(const struct Rectangle* r)
{
int length, breadth;
length = r->botRight.x - r->topLeft.x;
if (length <= 0)
exit(1);
breadth = r->topLeft.y - r->botRight.y;
if (breadth <= 0)
exit(2);
return length * breadth;
}
int genRec(struct Rectangle* rec);
int main(void)
{
srand(time(NULL));
int maxarea = 0;
int maxidx = 0;
struct Rectangle rec[N];
for (int i = 0; i < N; i++) {
printf("\n");
printf("\t----------RECTANGLE %d----------\n", i + 1);
int area = genRec(&rec[i]);
if (area > maxarea) {
maxarea = area;
maxidx = i;
}
}
printf("\n");
printf("\tMaximum area is %d in Rectangle %d\n", maxarea, maxidx + 1);
return 0;
}
void genPair(int* lo, int* hi)
{
while (1) {
*lo = -50 + rand() % 101;
*hi = -50 + rand() % 101;
if (*lo < *hi)
break;
}
}
int genRec(struct Rectangle* rec)
{
genPair(&rec->topLeft.x, &rec->botRight.x);
genPair(&rec->botRight.y, &rec->topLeft.y);
printf("\tTop left point is x = %d y = %d\n",
rec->topLeft.x, rec->topLeft.y);
printf("\tBottom right point is x = %d y = %d\n",
rec->botRight.x, rec->botRight.y);
int area = Area(rec);
printf("\tArea is %d\n", area);
return area;
}
I'm trying to implement Hough algorithm using C programming language and 2D raw image.
I have written the code in order to get separate output image for edge detection and Hough transform. When I do edge detection only I'm getting the proper edge detected output image. But here I'm getting the output raw image of size 0KB.I'm not getting where I made mistake.
Can anybody please help me to rectify this problem and give idea for further development such as draw line based on Hough space for the below code.
Thank you in advance.
#include <stdio.h>
#include <math.h>
#define PI 3.14159265
void
hough_transform(unsigned char out[256][256], unsigned char h_out[][256],
int w, int h)
{
int i, j;
int thetaDeg;
float thetaRad;
int rho;
int distMax;
int thetamax;
distMax = sqrt((h * h) + (w * w));
thetamax = 360;
int Acc[180][180];
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
if (out[i][j] > 0) {
for (thetaDeg = 0; thetaDeg < thetamax; ++thetaDeg) {
thetaRad = thetaDeg * (PI / 180);
rho = i * cos(thetaRad) + j * sin(thetaRad);
// find rho value that is closest to this
if (distMax < rho) {
int min = abs(rho - distMax);
}
if (distMax <= 1) {
// Increment a value in an accumulator array
Acc[rho][thetaDeg] += 1;
}
}
}
}
}
for (rho = 0; rho < distMax; rho++) {
for (thetaDeg = 0; thetaDeg < thetamax; thetaDeg++) {
h_out[rho][thetaDeg] = Acc[rho][thetaDeg];
}
}
}
void
edge_detect(unsigned char input[256][256], unsigned char out[][256],
int width, int height)
{
int in[3][3] = { {1, 2, 1}, {0, 0, 0}, {-1, -2, -1} };
int pixel;
int i;
int j;
int x;
int y;
for (y = 1; y < height - 1; y++) {
for (x = 1; x < width - 1; x++) {
pixel = 0;
for (j = -1; j <= 1; j++) {
for (i = -1; i <= 1; i++) {
pixel += in[j + 1][i + 1] * input[y + j][x + i];
}
}
out[y][x] = (unsigned char) abs(pixel);
}
}
}
int
main()
{
FILE *fp;
FILE *fp1;
FILE *fp2;
unsigned char input[256][256];
unsigned char out[256][256];
unsigned char h_out[256][256];
int width = 256;
int height = 256;
fp = fopen("Image.raw", "rb");
fp1 = fopen("output.raw", "wb");
fp2 = fopen("h_output.raw", "wb");
fread(input, 256 * 256, 1, fp);
edge_detect(input, out, width, height);
hough_transform(out, h_out, width, height);
fwrite(out, 256 * 256, 1, fp1);
fwrite(h_out, 256 * 256, 1, fp2);
fclose(fp);
fclose(fp1);
fclose(fp2);
return (0);
}
I have the following sobel filter code that runs correctly.
I want to transform it in code with 1D arrays and without structs. My attempt runs but the output image is not the right one...
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <string.h>
#include "Image.h"
RGBQUAD image[2048][2048]; // Image as input
int main(int argc, char *argv[])
{
char *filename = 0;
FILE *fp;
FILE *wp;
int width, height;
int i, j, x, y, T;
BitmapFileHeader bmfh;
BitmapInfoHeader bmih;
unsigned char ee_image[2048][2048];
// Reading inputs: bayer image and threshold
if (argc == 3){
filename = argv[1];
T = atoi(argv[2]);
} else{
printf("Give a bmp image and a threshold as input\n");
exit(0);
}
// Opening the file: using "rb" mode to read this *binary* file
printf("Opening filename: %s\n", filename);
fp = fopen(filename, "rb");
// Reading the file header and any following bitmap information...
fread(&bmfh, sizeof(BitmapFileHeader), 1, fp);
fread(&bmih, sizeof(BitmapInfoHeader), 1, fp);
printf("Header Info\n");
printf("--------------------\n");
printf("Size:%i\n", bmfh.bfSize);
printf("Offset:%i\n", bmfh.bfOffBits);
printf("--------------------\n");
printf("Size:%i\n", bmih.biSize);
printf("biWidth:%i\n", bmih.biWidth);
printf("biHeight:%i\n", bmih.biHeight);
printf("biPlanes:%i\n", bmih.biPlanes);
printf("biBitCount:%i\n", bmih.biBitCount);
printf("biCompression:%i\n", bmih.biCompression);
printf("biSizeImage:%i\n", bmih.biSizeImage);
printf("biXPelsPerMeter:%i\n", bmih.biXPelsPerMeter);
printf("biYPelsPerMeter:%i\n", bmih.biYPelsPerMeter);
printf("biClrUsed:%i\n", bmih.biClrUsed);
printf("biClrImportant:%i\n", bmih.biClrImportant);
printf("--------------------\n");
// Reading the pixels of input image
width = bmih.biWidth; if (width%4 != 0) width += (4-width%4);
height = bmih.biHeight;
for (y=0; y<height; y++)
for (x=0; x<width; x++){
image[x][y].rgbBlue = fgetc(fp);
image[x][y].rgbGreen = fgetc(fp);
image[x][y].rgbRed = fgetc(fp);
}
fclose(fp);
// Converting from RGB to Grayscale
int gray_image[width][height];
memset(gray_image, 0, width*height*sizeof(int));
for (y=0; y<height; y++)
for (x=0; x<width; x++){
gray_image[x][y] = 0.2989*image[x][y].rgbRed + 0.5870*image[x][y].rgbGreen + 0.1140*image[x][y].rgbBlue;
}
// mask for x direction
double S1[3][3] = {{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1}};
// mask for y direction
double S2[3][3] = {{-1, -2, -1},
{0, 0, 0},
{1, 2, 1}};
// Scanning the image
for (x=1; x<width-1; x++)
for (y=1; y<height-1; y++){
double Gx = S1[0][0]*gray_image[x-1][y-1] + S1[0][1]*gray_image[x-1][y] + S1[0][2]*gray_image[x-1][y+1] +
S1[1][0]*gray_image[x][y-1] + S1[1][1]*gray_image[x][y] + S1[1][2]*gray_image[x][y+1] +
S1[2][0]*gray_image[x+1][y-1] + S1[2][1]*gray_image[x+1][y] + S1[2][2]*gray_image[x+1][y+1];
double Gy = S2[0][0]*gray_image[x-1][y-1] + S2[0][1]*gray_image[x-1][y] + S2[0][2]*gray_image[x-1][y+1] +
S2[1][0]*gray_image[x][y-1] + S2[1][1]*gray_image[x][y] + S2[1][2]*gray_image[x][y+1] +
S2[2][0]*gray_image[x+1][y-1] + S2[2][1]*gray_image[x+1][y] + S2[2][2]*gray_image[x+1][y+1];
double e = sqrt(Gx*Gx + Gy*Gy);
// Thresholding
if (e <= T) ee_image[x][y] = 0;
if (e > T) ee_image[x][y] = 255;
} // End of image scanning
// Calculating the border pixels with replication
for (y=1; y<height-1; y++){
ee_image[0][y] = ee_image[1][y];
ee_image[width-1][y] = ee_image[width-2][y];
}
for (x=0; x<width; x++){
ee_image[x][0] = ee_image[x][1];
ee_image[x][height-1] = ee_image[x][height-2];
}
printf("The edges of the image have been detected with Sobel and a Threshold: %d\n", T);
// Constructing output image name
char dst_name[80];
// Converting input threshold to string
char str_T[3];
sprintf(str_T, "%d", T);
strcpy(dst_name, "Sobel_");
strcat(dst_name, str_T);
strcat(dst_name, ".bmp");
// Writing new image
wp = fopen(dst_name, "wb");
fwrite(&bmfh, 1, sizeof(BitmapFileHeader), wp);
fwrite(&bmih, 1, sizeof(BitmapInfoHeader), wp);
for (y=0; y<height; y++)
for (x=0; x<width; x++){
fputc(ee_image[x][y], wp);
fputc(ee_image[x][y], wp);
fputc(ee_image[x][y], wp);
}
fclose(wp);
}
My Code attempt is...
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <string.h>
#include "Image.h"
image[2048*2048]; // Image as input
int main(int argc, char *argv[])
{
char *filename = 0;
FILE *fp;
FILE *wp;
int width, height;
int i, j, x, y, T;
BitmapFileHeader bmfh;
BitmapInfoHeader bmih;
unsigned char ee_image[2048*2048];
// Reading inputs: bayer image and threshold
if (argc == 3){
filename = argv[1];
T = atoi(argv[2]);
} else{
printf("Give a bmp image and a threshold as input\n");
exit(0);
}
// Opening the file: using "rb" mode to read this *binary* file
printf("Opening filename: %s\n", filename);
fp = fopen(filename, "rb");
// Reading the file header and any following bitmap information...
fread(&bmfh, sizeof(BitmapFileHeader), 1, fp);
fread(&bmih, sizeof(BitmapInfoHeader), 1, fp);
printf("Header Info\n");
printf("--------------------\n");
printf("Size:%i\n", bmfh.bfSize);
printf("Offset:%i\n", bmfh.bfOffBits);
printf("--------------------\n");
printf("Size:%i\n", bmih.biSize);
printf("biWidth:%i\n", bmih.biWidth);
printf("biHeight:%i\n", bmih.biHeight);
printf("biPlanes:%i\n", bmih.biPlanes);
printf("biBitCount:%i\n", bmih.biBitCount);
printf("biCompression:%i\n", bmih.biCompression);
printf("biSizeImage:%i\n", bmih.biSizeImage);
printf("biXPelsPerMeter:%i\n", bmih.biXPelsPerMeter);
printf("biYPelsPerMeter:%i\n", bmih.biYPelsPerMeter);
printf("biClrUsed:%i\n", bmih.biClrUsed);
printf("biClrImportant:%i\n", bmih.biClrImportant);
printf("--------------------\n");
// Reading the pixels of input image
width = bmih.biWidth; if (width%4 != 0) width += (4-width%4);
height = bmih.biHeight;
for (y=0; y<height; y++)
for (x=0; x<width; x++){
image[x + y * width] = fgetc(fp);
image[x + y * width] = fgetc(fp);
image[x + y * width] = fgetc(fp);
}
fclose(fp);
// Converting from RGB to Grayscale
int gray_image[width*height];
memset(gray_image, 0, width*height*sizeof(int));
for (y=0; y<height; y++)
for (x=0; x<width; x++){
gray_image[x + y * width] = 0.2989*image[x + y * width] + 0.5870*image[x + y * width] + 0.1140*image[x + y * width];
}
// Sobel kernels
// mask for x direction
double S1[3][3] = {{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1}};
// mask for y direction
double S2[3][3] = {{-1, -2, -1},
{0, 0, 0},
{1, 2, 1}};
// Scanning the image
for (x=1; x<width-1; x++)
for (y=1; y<height-1; y++){
double Gx = S1[0][0]*gray_image[(x-1)*(y-1)] + S1[0][1]*gray_image[(x-1)*(y)] + S1[0][2]*gray_image[(x-1)*(y+1)] +
S1[1][0]*gray_image[x*(y-1)] + S1[1][1]*gray_image[x + y * width] + S1[1][2]*gray_image[x*(y+1)] +
S1[2][0]*gray_image[(x+1)*(y-1)] + S1[2][1]*gray_image[(x+1)*y] + S1[2][2]*gray_image[(x+1)*(y+1)];
double Gy = S2[0][0]*gray_image[(x-1)*(y-1)] + S2[0][1]*gray_image[(x-1)*(y)] + S2[0][2]*gray_image[(x-1)*(y+1)] +
S2[1][0]*gray_image[x*(y-1)] + S2[1][1]*gray_image[x + y * width] + S2[1][2]*gray_image[x*(y+1)] +
S2[2][0]*gray_image[(x+1)*(y-1)] + S2[2][1]*gray_image[(x+1)*y] + S2[2][2]*gray_image[(x+1)*(y+1)];
double e = sqrt(Gx*Gx + Gy*Gy);
// Thresholding
if (e <= T) ee_image[x + y * width] = 0;
if (e > T) ee_image[x + y * width] = 255;
} // End of image scanning
// Calculating the border pixels with replication
for (y=1; y<height-1; y++){
ee_image[0*y] = ee_image[1*y];
ee_image[(width-1)*y] = ee_image[(width-2)*y];
}
for (x=0; x<width; x++){
ee_image[x*0] = ee_image[x*1];
ee_image[x*(height-1)] = ee_image[x*(height-2)];
}
printf("The edges of the image have been detected with Sobel and a Threshold: %d\n", T);
// Constructing output image name
char dst_name[80];
// Converting input threshold to string
char str_T[3];
sprintf(str_T, "%d", T);
strcpy(dst_name, "Sobel_");
strcat(dst_name, str_T);
strcat(dst_name, ".bmp");
// Writing new image
wp = fopen(dst_name, "wb");
fwrite(&bmfh, 1, sizeof(BitmapFileHeader), wp);
fwrite(&bmih, 1, sizeof(BitmapInfoHeader), wp);
for (y=0; y<height; y++)
for (x=0; x<width; x++){
fputc(ee_image[x + y * width], wp);
fputc(ee_image[x + y * width], wp);
fputc(ee_image[x + y * width], wp);}
fclose(wp);
}
I have understand that sonething is wrong when i reaf the original image...
Any help would be precious.
Regards
"Image.h"
typedef struct tagBitmapFileHeader{
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
} __attribute__((packed)) BitmapFileHeader;
typedef struct tagBitmapInfoHeader{
unsigned int biSize;
int biWidth;
int biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} __attribute__((packed)) BitmapInfoHeader;
typedef struct{ /**** Colormap entry structure ****/
unsigned char rgbBlue; /* Blue value */
unsigned char rgbGreen; /* Green value */
unsigned char rgbRed; /* Red value */
unsigned char rgbReserved; /* Reserved */
} RGBQUAD;
typedef struct{ /**** Colormap entry structure ****/
unsigned char yccY; /* Y value */
unsigned char yccCb; /* Cb value */
unsigned char yccCr; /* Cr value */
unsigned char yccReserved; /* Reserved */
} YCCQUAD;
Goal: I am trying to create a ray tracer in C. I just added in a light source that should give each of my three spheres a shading effect based on where the light is. If the light is to the left of all of them, a shadow should be cased on the right.
Problem: When changing the light intensities and position of the light, all the spheres are changed uniformly. The spheres will be more or less lit equally and there is no variation of lighting on individual pixels on the sphere.
My debugging attempts: I have tried looking through the variable outputs by printing out a lot of different info and I think the source comes from my variable
diffuse_light_intensity
which does not change much (through all the iterations on the screen the value changes twice when it should be changing quite often due to the angles of the light on the surface changing quite a bit)
My Code: (my theory is the problem lies in scene_intersect() or cast_ray())
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <limits.h>
typedef struct {
float position[3];
float intensity;
} Light;
typedef struct {
float diffuse_color[3];
} Material;
typedef struct {
float center[3];
float radius;
Material material;
} Sphere;
int arrSub(const float arr1[], const float arr2[], float subArr[], int length) {
/*
Requires 3 equally sized arrays (denoted as length),
arr1 - arr2 will result in the third array subArr
*/
for (int i = 0; i < length; i++) {
subArr[i] = arr1[i] - arr2[i];
}
return 0;
}
int arrAdd(const float arr1[], const float arr2[], float addArr[], int length) {
/*
Requires 3 equally sized arrays (denoted as length),
arr1 + arr2 will result in the third array subArr
*/
for (int i = 0; i < length; i++) {
addArr[i] = arr1[i] + arr2[i];
}
return 0;
}
int arrScalarMult(const float arr1[], float scalar, float newArr[], int length) {
/*
Requires 3 equally sized arrays (denoted as length),
arr1 - arr2 will result in the third array subArr
*/
for (int i = 0; i < length; i++) {
newArr[i] = arr1[i] * scalar;
}
return 0;
}
float dotProduct(const float arr1[], const float arr2[], int length) {
/*
Returns the dot product of two equal sized arrays
(treated as vectors)
a (dot) b = a1b1 + a2b2 + ... anbn
*/
float result = 0;
for (int i = 0; i < length; i++) {
result += arr1[i] * arr2[i];
}
return result;
}
int normalize(float arr[], int len) {
//Normalize a vector (array)
float sumSqr;
float norm;
for (int i = 0; i < len; i++) {
sumSqr += arr[i] * arr[i];
}
norm = sqrt(sumSqr);
for (int i = 0; i < len; i++) {
arr[i] = arr[i] / norm;
}
return 0;
}
bool ray_intersect(const float origin[], const float dir[], float t0, Sphere s) {
/*
Ray-Sphere Intersection
Vectors:
origin (the zero vector)
dir (direction vector)
L (vector from origin to center of sphere)
Scalars:
tca
d2
thc
t0
t1
*/
float L[3] = {0,0,0}; //The zero vector
arrSub(s.center, origin, L, 3); //L is now the vector from origin to the sphere's center
float tca = dotProduct(L, dir, 3); //Projection of L onto dir
float d2 = dotProduct(L, L, 3) - tca*tca;
if (d2 > s.radius * s.radius) return false; //There is no intersection, so return false.
float thc = sqrtf((s.radius*s.radius - d2));
t0 = tca - thc;
float t1 = tca + thc;
if (t0 < 0) {
t0 = t1;
}
if (t0 < 0) return false;
return true;
}
bool scene_intersect(const float origin[], const float dir[], const Sphere s[], int len, float hit[], float N[], Material * ptr_m) {
float sphere_dist = INT_MAX;
for (size_t i=0; i < len; i++) {
float dist_i;
if (ray_intersect(origin, dir, dist_i, s[i]) && dist_i < sphere_dist) {
sphere_dist = dist_i;
float dirDist[3];
arrScalarMult(dir, dist_i, dirDist, 3);
arrAdd(origin, dirDist, hit, 3);
float hitMinusCenter[3];
arrSub(hit, s[i].center, hitMinusCenter, 3);
normalize(hitMinusCenter, 3);
N[0] = hitMinusCenter[0];
N[1] = hitMinusCenter[1];
N[2] = hitMinusCenter[2];
* ptr_m = s[i].material;
}
}
return sphere_dist<1000;
}
int cast_ray(const float origin[], const float dir[], const Sphere s[], const Light l[], int l_size, unsigned char colorArr[]) {
float point[3], N[3];
Material m;
Material * ptr_m = &m;
if (!scene_intersect(origin, dir, s, 3, point, N, ptr_m)) {
//background
colorArr[0] = 5; //red
colorArr[1] = 100; //green
colorArr[2] = 250; //blue
} else {
float diffuse_light_intensity = 0;
float light_dir[3];
for (size_t i = 0; i < l_size; i++) {
arrSub(l[i].position, point, light_dir, 3);
normalize(light_dir, 3);
diffuse_light_intensity += l[i].intensity * ((0.f >= dotProduct(light_dir, N, 3) ? (0.f) : (dotProduct(light_dir, N, 3))));
}
//light up pixel
colorArr[0] = m.diffuse_color[0] * diffuse_light_intensity;
colorArr[1] = m.diffuse_color[1] * diffuse_light_intensity;
colorArr[2] = m.diffuse_color[2] * diffuse_light_intensity;
}
return 0;
}
int render(const Sphere s[], const Light l[], int l_length) {
/*
Creates image in a new color each step.
*/
const int width = 1024;
const int height = 768;
FILE *fp = fopen("fourth.ppm", "wb"); // Write in binary mode
(void) fprintf(fp, "P6\n%d %d\n255\n", width, height);
float fov = 3.1415926535/2.; // Field of View
#pragma omp parallel for
for (size_t j = 0; j < height; j++) {
for (size_t i = 0; i < width; i++) {
float x = (2*(i+.5)/(float)width - 1)*tan(fov/2.)*width/(float)height;
float y = -(2*(j+.5)/(float)height - 1)*tan(fov/2.);
float dir[] = {x,y,-1};
normalize(dir, 3);
unsigned char color[3];
const float origin[] = {0,0,0};
cast_ray(origin, dir, s, l, l_length, color);
(void) fwrite(color, 1, 3, fp);
}
}
(void) fclose(fp);
return 0;
}
int main(void) {
Material red = {255,0,0};
Material pink = {150,10,150};
Material gold = {255, 195, 0};
//Populate with spheres
Sphere s[3];
Sphere originalS = {{-3,0,-16},2,gold};
Sphere bigS = {{-1.0, -1.5, -12}, 3, red};
Sphere anotherS = {{7,5,-18},2,pink};
s[0] = originalS;
s[1] = bigS;
s[2] = anotherS;
//Add light source
Light l[1];
Light test_light = {{-20,20,20}, 1.5};
l[0] = test_light;
render(s,l, 1);
printf("Run success!\n");
return 0;
}
If any clarification is needed on my code please let me know, I am quite new to both C and stackoverflow.
There's a fundamental error in ray_intersect where you're passing the t0 variable by value, and not as a pointer, and therefore in the scene_intersect function its value is always zero.
The other problem is that you don't initialize the sumSqr in the normalize function, resulting in that function returning NaN for each vector component.
With those two fixed I get something approximating shaded balls. The errors in that image are caused by failing to ensure that your output pixel values fall in the range [0, 255].
NB: both of these first errors are detected if you turn on full compiler error checking, warning you of uninitialised variables being used.
I'm new to OpenGL and I am trying to get a mandelbrot set computed with OpenGL and GLFW.
I found the code here but freeglut is broken on my system and for some reason complains about no callback being set even though it clearly is being set. It does however flash one frame and then crash, in that frame I can see the mandelbrot set so I know the math is correct.
I figured this would be a good opportunity to learn more about OpenGL and GLFW, so I set to work making this happen.
After double checking everything, I can see that it definitely calculates the values then switches the buffers properly.
However, I think I'm missing two things:
A vertex which the texture can actually be applied to
EDIT: (from learnopengl.com) "Once glTexImage2D is called, the currently bound texture object now has the texture image attached to it.", so it can't be #2
not sure what's happening with the calculation but it looks like it's binding a texture named 'texture' but then calculating the values in a struct array which don't seem to be associated in any way. I bind the texture with tex (texture) and then send the struct array to glTexImage2D
If someone could just point me in the right direction or confirm my suspicions that would be awesome.
My code is here:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define GLEW_STATIC
#include <GL/glew.h>
#include <pthread.h>
#include <GLFW/glfw3.h>
#include <GL/gl.h>
#define VAL 255
typedef struct {
uint8_t r;
uint8_t g;
uint8_t b;
}rgb_t;
rgb_t **tex_array = 0;
rgb_t *image;
int gwin;
int width = 640;
int height = 480;
int tex_w, tex_h;
double scale = 1./256;
double cx = -.6, cy = 0;
int color_rotate = 0;
int saturation = 1;
int invert = 0;
int max_iter = 256;
int dump = 1;
GLFWwindow* window;
int global_iterator = 0;
int conversion_iterator_x = 0;
int conversion_iterator_y = 0;
GLFWwindow* init_glfw();
void set_texture(GLuint tex);
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void render(GLuint tex);
void screen_dump();
void keypress(unsigned char key, int x, int y);
void hsv_to_rgb(int hue, int min, int max, rgb_t *p);
void calc_mandel(rgb_t* px);
void alloc_texture();
void set_texture();
void mouseclick(int button, int state, int x, int y);
void resize(int w, int h);
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
int main(int c, char **v)
{
GLFWwindow* win = init_glfw();
glfwSetWindowPos(win, 1000, 500);
GLuint texture;
glGenTextures(1, &texture);
set_texture(texture);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(win))
{
render(texture);
/* Swap front and back buffers */
glfwSwapBuffers(win);
/* Poll for and process events */
glfwPollEvents();
if(glfwGetKey(win, GLFW_KEY_ESCAPE) == GLFW_PRESS){
glfwSetWindowShouldClose(win, GL_TRUE);
}
}
return 0;
}
void set_texture(GLuint tex)
{
printf("Allocating space\n");
alloc_texture();
printf("Calculating mandel... %d\n", global_iterator);
++global_iterator;
calc_mandel(image);
printf("mandel calculation complete\n");
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_w, tex_h,
0, GL_RGB, GL_UNSIGNED_BYTE, tex_array[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
printf("Rendering to screen...\n");
render(tex);
}
void alloc_texture()
{
int i;
int ow = tex_w;
int oh = tex_h;
for (tex_w = 1; tex_w < width; tex_w <<= 1);
for (tex_h = 1; tex_h < height; tex_h <<= 1);
if (tex_h != oh || tex_w != ow){
tex_array = realloc(tex_array, tex_h * tex_w * 3 + tex_h * sizeof(rgb_t*));
}
for (tex_array[0] = (rgb_t *)(tex_array + tex_h), i = 1; i < tex_h; i++){
tex_array[i] = tex_array[i - 1] + tex_w;
}
}
void render(GLuint tex)
{
double x = (double)width /tex_w,
y = (double)height/tex_h;
glClear(GL_COLOR_BUFFER_BIT);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBindTexture(GL_TEXTURE_2D, tex);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2i(0, 0);
glTexCoord2f(x, 0); glVertex2i(width, 0);
glTexCoord2f(x, y); glVertex2i(width, height);
glTexCoord2f(0, y); glVertex2i(0, height);
glEnd();
glFlush();
glFinish();
}
GLFWwindow* init_glfw()
{
/* Initialize the library */
if (!glfwInit()){
return NULL;
}
/*
* Configure window options here if you so desire
*
* i.e.
*/
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
//glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
//the fourth parameter of glfwCreateWindow should be NULL for windowed mode and
//glfGetPrimaryMonitor() for full screen mode
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(width, height, "Mandelbrot", NULL, NULL);
if (!window)
{
glfwTerminate();
return NULL;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
/*
* Initialize glew here
*/
glewExperimental = GL_TRUE;
glewInit();
return window;
}
void calc_mandel(rgb_t* px)
{
int i, j, iter, min, max;
double x, y, zx, zy, zx2, zy2;
min = max_iter;
max = 0;
for (i = 0; i < height; i++) {
px = tex_array[i];
y = (i - height/2) * scale + cy;
for (j = 0; j < width; j++, px++) {
x = (j - width/2) * scale + cx;
iter = 0;
zx = hypot(x - .25, y);
if (x < zx - 2 * zx * zx + .25){
iter = max_iter;
}
if ((x + 1)*(x + 1) + y * y < 1/16){
iter = max_iter;
}
zx = zy = zx2 = zy2 = 0;
for (; iter < max_iter && zx2 + zy2 < 4; iter++) {
zy = 2 * zx * zy + y;
zx = zx2 - zy2 + x;
zx2 = zx * zx;
zy2 = zy * zy;
}
if (iter < min){
min = iter;
}
if (iter > max){
max = iter;
}
*(unsigned short *)px = iter;
}
}
for (i = 0; i < height; i++){
for (j = 0, px = tex_array[i]; j < width; j++, px++){
hsv_to_rgb(*(unsigned short*)px, min, max, px);
}
}
}
void hsv_to_rgb(int hue, int min, int max, rgb_t *p)
{
printf("Converting hsv to rbg... \n");
if (min == max){
max = min + 1;
}
if (invert){
hue = max - (hue - min);
}
if (!saturation) {
p->r = p->g = p->b = 255 * (max - hue) / (max - min);
printf("done! (!saturation)\n");
return;
}
double h = fmod(color_rotate + 1e-4 + 4.0 * (hue - min) / (max - min), 6);
double c = VAL * saturation;
double X = c * (1 - fabs(fmod(h, 2) - 1));
p->r = p->g = p->b = 0;
switch((int)h) {
case 0: p->r = c; p->g = X; break;
case 1: p->r = X; p->g = c; break;
case 2: p->g = c; p->b = X; break;
case 3: p->g = X; p->b = c; break;
case 4: p->r = X; p->b = c; break;
default:p->r = c; p->b = X; break;
}
printf("done! (sauration)\n");
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
glOrtho(0, width, 0, height, -1, 1);
//set_texture();
}
[1]: https://rosettacode.org/wiki/Mandelbrot_set#PPM_non_interactive