How do i draw Lines in a 3D Coordinate system - c

i want to draw lines in a 3D Coordinate System but in 2D in C. I know that i have to do an interpolation
Or can i just draw Vectors?
I read online some facts about interpolation but it didnt work because i have some Coordinates lower than zero. (https://math.stackexchange.com/questions/2305792/3d-projection-on-a-2d-plane-weak-maths-ressources)
Thats why i get so tiny lines.
Here are some of the coordinates of an data i want to draw lines with.
i already read the date and saved the points in an Array (coor).
from x: -10.0
from y: -10.0
from z: -10.0
to x : 200.0
to y: -5.0
to z: 20.0
[#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include "project3res.h"][1]
double coor [4][6];
///////////// KOORDINATENSYSTEM ZEICHNEN//////////////////////
BOOL zeichnen (HWND hwnd)
//double x0=650,y0=350;
//double d= 100; //Hilfsvariable zum Interpolieren von 2D zu 3D
//Vorbereitung
{
double x0=650,y0=350; //KOORDINATENSYSTEM URSPRUNG
double d= 2; //Hilfsvariable für Umwandlung von 3D in 2D
HDC hdc;
PAINTSTRUCT ps;
InvalidateRect (hwnd, NULL, TRUE);
hdc = BeginPaint (hwnd, &ps);
//Zeichenbefehle
//KOORDINATENSYSTEM//
SetViewportOrgEx(hdc,x0,y0,NULL);
MoveToEx (hdc, 0, 0, NULL);
LineTo (hdc, 100, 0); //X-ACHSE
MoveToEx (hdc, 0, 0, NULL);
LineTo (hdc, -100, 0);
MoveToEx (hdc, 0, 0, NULL);
LineTo (hdc, 0, 100); //Y-ACHSE
MoveToEx (hdc, 0, 0, NULL);
LineTo (hdc, 0, -100);
MoveToEx (hdc, 0, 0, NULL);
LineTo (hdc, 100, -100); //Z-ACHSE
MoveToEx (hdc, 0, 0, NULL);
LineTo (hdc, -100, 100);
MoveToEx (hdc,coor[0][0]*(d/coor[0][2]), coor[0][1]*(d/coor[0][2]), NULL);
LineTo (hdc, coor[0][3]*(d/coor[0][5]), coor[0][4]*(d/coor[0][5]));
EndPaint (hwnd, &ps);
UpdateWindow(hwnd);
return 0;
}

Recap:
x' = x * d / z;
y' = y * d / z;
Based on your linked post, the positive z-axis points away from you and the center of the projection plane is at (0, 0, d).
Now, if any z-coordinate is less than d (between eye and the plane), as described, clipping will occur.
There are two possibilities to adjust your render output:
move the camera away from the scene
d remains unchanged
add a (positive) distance factor to every z-coordinate (move the objects in the scene along the positive z-axis)
advantage: every point gets projected
disadvantage: scene gets smaller, the more you move away
change the field of view
alter the d value
decrease: wide lens effect
increase: narrow lens, zoom in effect, more clipping will occur
The best approach would be, to find the bounding box of your scene (lines) and fit that box into the frustum of the view (trigonometry required).
The frustum is the cutoff part of the pyramid (the one from your eye to the zfar plane). You need the znear plane (which is d) and the zfar plane, which could be the depth (farthest z-coordinate) of your bounding box.
More Info:
Viewing frustum
The Size of the Frustum at a Given Distance from the Camera
Perspective projection
Camera matrix

Related

OpenGL Try to draw square but its display a rectangle

I try to draw a simple square by OpenGL but the result its display a rectangle. I guess that the problem is in the reshape function but I have no idea why (I'm new to OpenGL).
I what to keep aspect when I resize the window, that is not to stretch or shrink my image.
image screenshot
my reshape function
#define WINDOW_W 640
#define WINDOW_H 480
void reshape(int width, int height) {
if (height == 0)
height = 1;
GLfloat aspect = (GLfloat)width / (GLfloat)height;
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (width >= height)
gluOrtho2D(0.0f, (GLdouble)WINDOW_W * aspect, (GLdouble)WINDOW_H, 0.0f);
else
gluOrtho2D(0.0f, (GLdouble)WINDOW_W, (GLdouble)WINDOW_H / aspect, 0.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
my draw function
void display(void) {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
// x=50 y=50 w=100 h=100 a square
glBegin(GL_QUADS);
glVertex2i(50, 50);
glVertex2i(50, 150);
glVertex2i(150, 150);
glVertex2i(150, 50);
glEnd();
glutSwapBuffers();
}
Right now, your "square" will always be exactly 1.3333 (640 / 480) times as tall as it is wide, because while you do take the actual window size into account and compute the actual aspect ratio given the actual window size, you multiply that with 640 for the width and 480 for the height, for whatever reason.
And that won't work since that will always stretch your actual aspect ratio by a factor of 1.3333 making your square always 1.3333 as tall as it is wide.
To solve this, just multiply the arguments to the gluOrtho2D() call with the same value, depending on what the extent in your world space or "view space" should be for a square view space with a square aspect ratio.

Object rendering strangely after adding transformations

I'm adding transformations to my C OpenGL program. I'm using CGLM as my maths library. The program has no warnings or errors. Still however, when I compile and run the program, I get a distorted version of my intended image (it was not distorted before adding transformations).
The following is my program's main loop:
// Initialize variables for framerate counting
double lastTime = glfwGetTime();
int frameCount = 0;
// Program loop
while (!glfwWindowShouldClose(window)) {
// Calculate framerate
double thisTime = glfwGetTime();
frameCount++;
// If a second has passed.
if (thisTime - lastTime >= 1.0) {
printf("%i FPS\n", frameCount);
frameCount = 0;
lastTime = thisTime;
}
processInput(window);
// Clear the window
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Bind textures on texture units
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
// Create transformations
mat4 transform = {{1.0f}};
glm_mat4_identity(transform);
glm_translate(transform, (vec3){0.5f, -0.5f, 0.0f});
glm_rotate(transform, (float)glfwGetTime(), (vec3){0.0f, 0.0f, 1.0f});
// Get matrix's uniform location and set matrix
shaderUse(myShaderPtr);
GLint transformLoc = glGetUniformLocation(myShaderPtr->shaderID, "transform");
// mat4 transform;
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, (float*)transform);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window); // Swap the front and back buffers
glfwPollEvents(); // Check for events (mouse movement, mouse click, keyboard press, keyboard release etc.)
}
The Program is up on github here if you'd like to check out the full code.
The Output of the program is this (The square also rotates):
However, the intended output of the program is the penguin at 20% opacity on top and the box at 100% opacity underneath the penguin.
In the vertex shader, the location of the texture coordinate is 1:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
However, when you specify the vertices, location 1 is used for the color attribute and position 2 for the text coordinates:
// Colour attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// Texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
Remove the color attribute and use location 1 for the texture coordinates. e.g.:
// Texture coord attribute
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(1);
Looking at your source code, you're passing in three attributes (position, color and texture coordinates), but your vertex shader only takes two.
Removing the color attribute and instead passing the texture coordinates as attribute #1 instead of #2 should make it look like intended.

Empty output png file form Cairo

I've render the hello example for C. I mean, the minimal C program using Cairo showing Here.
However when I try to render this:
#include <cairo.h>
int main(void){
/* Where we gonna draw. The image to print. */
cairo_surface_t *surface;
/* The context. The printed layer by a surface */
cairo_t *cr;
/* The format (in this case ARGB), width and height of surface */
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 120, 120);
/* The context behind of surface */
cr = cairo_create(surface);
/* void cairo_set_source_rgb(cairo_t *cr, double red, double green, double blue); */
cairo_set_source_rgb(cr, 0, 0, 0);
/* void cairo_move_to(cairo_t *cr, double x, double y); */
/* After this call the current point will be (x,y). */
cairo_move_to (cr, 0, 0);
/* void cairo_line_to(cairo_t *cr, double x, double y); */
/* Adds a line to the path from the current position (x,y). After this call the current point will be (x,y). */
/* Must be a current point, otherwise the beahavior gonna be like move_to */
cairo_line_to (cr, 1, 1);
cairo_move_to (cr, 1, 0);
cairo_line_to (cr, 0, 1);
/* void cairo_set_line_width(cairo_t *cr, double width); */
/* Sets the current line width within the cairo context. The line width value specifies the diameter of a pen is circular */
cairo_set_line_width (cr, 0.2);
/* void cairo_stroke(cairo_t *cr); */
/* A drawing operator that strokes the current path according to the current line width, line join, line cap, and dash settings. */
cairo_stroke (cr);
/* void cairo_rectangle(cairo_t *cr, double x, double y, double width, double height); */
/* Adds a closed sub-path rectangle of the given size to the current path at position (x,y) in user-space coordinates. */
/* This function is logically equivalent to:
* cairo_move_to (cr, x, y);
* cairo_rel_line_to (cr, width, 0);
* cairo_rel_line_to (cr, 0, height);
* cairo_rel_line_to (cr, -width, 0);
* cairo_close_path (cr);
* *************************************/
cairo_rectangle (cr, 0, 0, 0.5, 0.5);
/* cairo_set_source_rgba(cairo_t *cr, double red, double green, double blue, double alpha); */
/* Sets the source pattern within cr to a translucent color. This color will then be used for any subsequent drawing operation
* until a new source pattern is set.
* The color and alpha components are floating point numbers in the range 0 to 1. If the values passed in are outside that range,
* they will be clamped.
* The default source pattern is opaque black, (that is, it is equivalent to cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0)).
* *****************************************************************************************************************************/
cairo_set_source_rgba (cr, 1, 0, 0, 0.80);
/* void cairo_fill(cairo_t *cr); */
/* A drawing operator that fills the current path according to the current fill rule, (each sub-path is implicitly closed before
* being filled). After cairo_fill(), the current path will be cleared from the cairo context.
* *****************************************************************************************************************************/
cairo_fill (cr);
cairo_rectangle (cr, 0, 0.5, 0.5, 0.5);
cairo_set_source_rgba (cr, 0, 1, 0, 0.60);
cairo_fill (cr);
cairo_rectangle (cr, 0.5, 0, 0.5, 0.5);
cairo_set_source_rgba (cr, 0, 0, 1, 0.40);
cairo_fill (cr);
cairo_surface_write_to_png(surface, "image.png");
cairo_destroy(cr);
cairo_surface_destroy(surface);
return 0;
}
I obtain an empty png. It looks like there's something there but it doesn't paint it.
I compile with:
cc -o file $(pkg-config --cflags --libs cairo) file.c
My brew info Cairo outs this:
cairo: stable 1.16.0 (bottled), HEAD
Vector graphics library with cross-device output support
https://cairographics.org/
/usr/local/Cellar/cairo/1.16.0_3 (117 files, 5.7MB) *
Poured from bottle on 2020-10-12 at 00:17:34
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/cairo.rb
License: LGPL-2.1
==> Dependencies
Build: pkg-config ✔
Required: fontconfig ✔, freetype ✔, glib ✔, libpng ✔, lzo ✔, pixman ✔
==> Options
--HEAD
Install HEAD version
==> Analytics
install: 110,282 (30 days), 348,240 (90 days), 1,254,903 (365 days)
install-on-request: 13,651 (30 days), 54,037 (90 days), 132,345 (365 days)
build-error: 0 (30 days)
The pkg-config libs outs this:
-L/usr/local/Cellar/cairo/1.16.0_3/lib -lcairo
And pkg-config Cflags:
-I/usr/local/Cellar/libffi/3.3/include -I/usr/local/Cellar/cairo/1.16.0_3/include/cairo
-I/usr/local/Cellar/glib/2.66.1/include -I/usr/local/Cellar/glib/2.66.1/include/glib-2.0
-I/usr/local/Cellar/glib/2.66.1/lib/glib-2.0/include -I/usr/local/opt/gettext/include
-I/usr/local/Cellar/pcre/8.44/include -I/usr/local/Cellar/pixman/0.40.0/include/pixman-1
-I/usr/local/Cellar/fontconfig/2.13.1/include -I/usr/local/opt/freetype/include/freetype2
-I/usr/local/Cellar/libpng/1.6.37/include/libpng16
Is there something wrong that I can't see? Everything looks great. I don't know what happen.
cairo_rectangle (cr, 0, 0, 0.5, 0.5);
You seem to assume the coordinates are within a range of 0..1 to cover the whole surface.
This is not true. Instead the coordinates ragnes are from 0..width and 0..height.
Your instruction will create a rectangle with half a pixel in each direction and the line width was set to 1/5 pixel before. You will not see much with those coordinates.
The sample you linked, uses much larger values. Try them.

GLFW3/GLU 3D world space using static pipeline

In previous projects, I enabled depth testing used gluPerspective called once on startup to set up a 3D space. Currently, I am rendering a square between -0.5 and 0.5 with 0.0 as its origin after the 3D world has initialised with code below will cause a square to cover the entire screen:
glBegin(GL_QUADS);
{
glVertex3f(-0.5, -0.5, 0);
glVertex3f(-0.5, 0.5, 0);
glVertex3f(0.5, 0.5, 0);
glVertex3f(0.5, -0.5, 0);
}
glEnd();
What I am looking is a way to set the perspective so that shapes are rendered in world space. For example, the snippet below should cause a square of 200x200 to be rendered:
glBegin(GL_QUADS);
{
glVertex3f(-100, -100, 0);
glVertex3f(-100, 100, 0);
glVertex3f(100, 100, 0);
glVertex3f(100, -100, 0);
}
glEnd();
The code below is what I am currently using to initialise a 3D world.
// WINDOW_WIDTH = 1600, WINDOW_HEIGHT = 900
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(47, WINDOW_WIDTH / WINDOW_HEIGHT, 0.01, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
Have I missed any steps in setting up a 3D space and if gluPerspective is used to do this any suggestions why it is not working?
I am able to achieve this in 2D using ortho, it is important that the world is 3D.
Everything is being written in C using OpenGL and GLU up to 1.3 with my GLFW set up identical to this. Due to technical restraints, I am unable to use the modern pipeline.
First of all, the result of WINDOW_WIDTH / WINDOW_HEIGHT is 1, because WINDOW_WIDTH and WINDOW_HEIGHT are integral values. You have to perform a floating point division ((float)WINDOW_WIDTH / WINDOW_HEIGHT) to compute the correct aspect ratio.
At Perspective Projection the projection matrix describes the mapping from 3D points in the world as they are seen from of a pinhole camera, to 2D points of the viewport.
The projected size of an object on the viewport depends on its distance to the camera. The different size at different distances (depths) causes the perspective effect. The perspective projection matrix defines a Viewing frustum
The ratio of projected size and the distance to the camera depends on the field of view angle:
maxDim / cameraZ = tan(FOV / 2) * 2
So there is exactly 1 distance where an object with a length of 200 covers 200 pixel. For instance, If you have a filed of view angle of 90° then an object with a z distance of half the window height (height /2) and a vertical size of 200 covers 200 pixel (vertical) because tan(90° / 2) * 2 = 2.
When you use gluPerspective, then you define the field of view angle along the y axis. The field of view along the x axis depends on the aspect ratio. If the aspect ratio is set correctly, then the projection of a square which is parallel to the xy plane of the view is still a square.
Note, if you would use orthographic projection, then the size of the object is independent on the distance.

How do I fill the screen with a rectangle in OpenGL ortho mode?

I have a single 640x480 texture that needs to fill the screen. So far, I can make it work with a square texture, but not a rectangular one.
glViewport(0, 0, display->w, display->h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double aspectRatio = (double)display->w / (double)display->h;
if (display->w <= display->h)
glOrtho(-1, 1, -1 / aspectRatio, 1 / aspectRatio, -1, 1);
else
glOrtho(-1 * aspectRatio, 1 * aspectRatio, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
What modifications do I need to make so that it will fit any texture to the screen, regardless of its aspect ratio?
This may have some relevance.
Tiling texture bmp file as texture onto a rectangle in OpenGL?
You may wish to consider ARB extension texture rectangle as an alternative approach to (assuming glTexImage2D?) http://glprogramming.com/red/chapter09.html

Resources