Skip to content Skip to sidebar Skip to footer

drawing 3d table in opengl code

With the availability of tools like DirectX and OpenGL, writing a desktop application that renders 3D elements is not very difficult present. Nonetheless, like many technologies, there are sometimes obstacles making it difficult for developers trying to enter into this niche. Over time, the race betwixt DirectX and OpenGL has caused these technologies to get more attainable to developers, along with meliorate documentation and an easier process of becoming a skilled DirectX or OpenGL developer.

DirectX, introduced and maintained by Microsoft, is a applied science specific to the Windows platform. On the other mitt, OpenGL is a cantankerous-platform API for the 3D graphics arena whose specification is maintained by the Khronos Group.

introduction to opengl

In this introduction to OpenGL, I will explicate how to write a very simple application to return 3D text models. Nosotros will exist using Qt/Qt Creator to implement the UI, making information technology easy to compile and run this awarding on multiple platforms. The source code of the epitome built for this article is bachelor on GitHub.

The goal of this simple awarding is to generate 3D models, salvage them to a file with a simple format, and to open and render them on screen. The 3D model in the rendered scene volition be rotatable and zoomable, to give a better sense of depth and dimension.

Prerequisites

Before getting started, nosotros will need to prepare our development environment with some useful tools for this project. The very first thing nosotros need is the Qt framework and relevant utilities, which can be downloaded from www.qt.io. It may also be available through your operating arrangement'south standard package manager; if that is the instance, you might want to try with it first. This article requires some familiarity with the Qt framework. Even so, if you are not familiar with the framework, delight do non experience discouraged to follow along, as the prototype relies on some fairly trivial features of the framework.

You tin can too apply Microsoft Visual Studio 2013 on Windows. In that case, please make certain you are using the appropriate Qt Addin for Visual Studio.

At this point, you might want to clone the repository from GitHub and follow it as y'all read through this article.

OpenGL Overview

Nosotros will brainstorm past creating a elementary Qt application projection with a single document widget. Since information technology is a bare-bones widget, compiling and running it will non produce anything useful. With Qt designer, we volition add a "File" menu with four items: "New…", "Open…", "Close", and "Exit". Y'all can find the code that binds these carte du jour items to their corresponding deportment in the repository.

Clicking on "New…" should popup a dialog that will look something like this:

opengl popup

Here, the user may enter some text, choose a font, tweak the resulting model meridian, and generate a 3D model. Clicking on "Create" should salvage the model, and should likewise open it if the user chooses the appropriate choice from the lower-left corner. Every bit you lot can tell, the goal here is to convert some user inputted text into a 3D model and return information technology on the display.

The project will accept a simple structure, and the components will be broken down into a handful of C++ and header files:

c++ and header files

createcharmodeldlg.h/cpp

Files incorporate QDialog derived object. This implements the dialog widget which allows the user to blazon text, select font, and choose whether to salvage the result into a file and/or display information technology in 3D.

gl_widget.h/cpp

Contains implementation of QOpenGLWidget derived object. This widget is used to render the 3D scene.

mainwindow.h/cpp

Contains implementation of the master awarding widget. These files were left unchanged since they were created by Qt Creator wizard.

main.cpp

Contains the principal(…) function, which creates the main application widget and shows it on screen.

model2d_processing.h/cpp

Contains functionality of creation of 2nd scene.

model3d.h/cpp

Contains structures which shop 3D model objects and allow operations to work on them (save, load etc.).

model_creator.h/cpp

Contains implementation of grade which allows cosmos of 3D scene model object.

OpenGL Implementation

For brevity, we will skip the obvious details of implementing the user interface with Qt Designer, and the code defining the behaviors of the interactive elements. There are certainly some more interesting aspects of this image awarding, ones that are not simply important only besides relevant to 3D model encoding and rendering that we want to cover. For example, the first step of converting text to a 3D model in this prototype involves converting the text to a 2D monochrome image. Once this image is generated, it is possible to know which pixel of the image forms the text, and which ones are only "empty" infinite. At that place are some simpler ways of rendering basic text using OpenGL, simply we are taking this approach in society to cover some nitty-gritty details of 3D rendering with OpenGL.

To generate this image, we instantiate a QImage object with the QImage::Format_Mono flag. Since all we demand to know is which pixels are function of the text and which ones are not, a monochrome epitome should piece of work just fine. When the user enters some text, we synchronously update this QImage object. Based on the font size and image width, we try our best to fit the text within the user defined height.

Adjacent, we enumerate all the pixels which are part of the text - in this example, the black pixels. Each pixel here is treated as separate square-ish units. Based on this, we tin generate a list of triangles, computing the coordinates of their vertices, and store them in our 3D model file.

At present that we have our own simple 3D model file format, nosotros tin kickoff focusing on rendering it. For OpenGL based 3D rendering, Qt provides a widget called QOpenGLWidget. To use this widget, three functions may exist overridden:

  • initializeGl() - this is where the initialization code goes
  • paintGl() - this method is called everytime the widget is redrawn
  • resizeGl(int w, int h) - this method is called with the widget's width and peak every time information technology is resized
3dmodel file format

We will initialize the widget by setting the appropriate shader configuration in the initializeGl method.

          glEnable(GL_DEPTH_TEST); glShadeModel(GL_FLAT); glDisable(GL_CULL_FACE);                  

The offset line makes the program evidence only those rendered pixels that are closer to us, rather than the ones that are behind other pixels and out of sight. The second line specifies the apartment shading technique. The third line makes the programme render triangles regardless of which direction their normals signal to.

Once initialized, we return the model on the display every time paintGl is called. Before we override the paintGl method, we must set up the buffer. To do that, we first create a buffer handle. Nosotros then demark the handle to one of the binding points, copy the source data into the buffer, and finally nosotros tell the program to unbind the buffer:

          // Get the Qt object which allows to operate with buffers QOpenGLFunctions funcs(QOpenGLContext::currentContext()); // Create the buffer handle funcs.glGenBuffers(ane, &handle); // Select buffer past its handle (and so we'll use this buffer // further) funcs.glBindBuffer(GL_ARRAY_BUFFER, handle); // Copy data into the buffer. Being copied, // source information is not used any more and can be released funcs.glBufferData(GL_ARRAY_BUFFER, 	size_in_bytes, 	src_data, 	GL_STATIC_DRAW); // Tell the programme nosotros've finished with the handle funcs.glBindBuffer(GL_ARRAY_BUFFER, 0);                  

Inside the overriding paintGl method, nosotros utilize an array of vertices and an array of normal data to draw the triangles for each frame:

          QOpenGLFunctions funcs(QOpenGLContext::currentContext()); // Vertex data glEnableClientState(GL_VERTEX_ARRAY);// Work with VERTEX buffer funcs.glBindBuffer(GL_ARRAY_BUFFER, m_hVertexes);	// Utilize this 1 glVertexPointer(3, GL_FLOAT, 0, 0);		// Data format funcs.glVertexAttribPointer(m_coordVertex, three, GL_FLOAT, 	GL_FALSE, 0, 0);	// Provide into shader program   // Normal information glEnableClientState(GL_NORMAL_ARRAY);// Work with NORMAL buffer funcs.glBindBuffer(GL_ARRAY_BUFFER, m_hNormals);// Use this one glNormalPointer(GL_FLOAT, 0, 0);	// Data format funcs.glEnableVertexAttribArray(m_coordNormal);	// Shader attribute funcs.glVertexAttribPointer(m_coordNormal, three, GL_FLOAT, 	GL_FALSE, 0, 0);	// Provide into shader program   // Describe frame glDrawArrays(GL_TRIANGLES, 0, (3 * m_model.GetTriangleCount()));   // Rendering finished, buffers are not in use at present funcs.glDisableVertexAttribArray(m_coordNormal); funcs.glBindBuffer(GL_ARRAY_BUFFER, 0); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY);                  

For improved operation, nosotros used Vertex Buffer Object (VBO) in our prototype application. This lets u.s.a. store data in video memory and use it directly for rendering. An alternate method to this involves providing the data (vertex coordinates, normals and colors) from the rendering code:

          glBegin(GL_TRIANGLES); 	// Provide coordinates of triangle #1 	glVertex3f( x[0], y[0], z[0]); 	glVertex3f( 10[1], y[ane], z[1]); 	glVertex3f( 10[2], y[ii], z[2]); 	// Provide coordinates of other triangles 	... glEnd();                  

This may seem similar a simpler solution; however, it has serious performance implications, as this requires the information to travel through the video memory bus - a relatively slower process. After implementing the paintGl method, nosotros must pay attention to shaders:

          m_shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,     	QString::fromUtf8(         	"#version 400\r\due north"         	"\r\north"         	"layout (location = 0) in vec3 coordVertexes;\r\n"         	"layout (location = 1) in vec3 coordNormals;\r\due north"         	"flat out float lightIntensity;\r\n"         	"\r\n"         	"compatible mat4 matrixVertex;\r\n"         	"compatible mat4 matrixNormal;\r\n"         	"\r\n"         	"void chief()\r\n"  	       	"{\r\n"         	"   gl_Position = matrixVertex * vec4(coordVertexes, one.0);\r\n"         	"   lightIntensity = abs((matrixNormal * vec4(coordNormals, 1.0)).z);\r\n"         	"}")); m_shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,     	QString::fromUtf8(         	"#version 400\r\n"         	"\r\n"         	"flat in float lightIntensity;\r\n"         	"\r\north"         	"layout (location = 0) out vec4 FragColor;\r\n"         	"uniform vec3 fragmentColor;\r\n"         	"\r\n"         	"void main()\r\n"         	"{\r\n"         	"	FragColor = vec4(fragmentColor * lightIntensity, i.0);\r\northward"         	"}")); 	m_shaderProgram.link(); 	m_shaderProgram.bind();   	m_coordVertex =  		m_shaderProgram.attributeLocation(QString::fromUtf8("coordVertexes")); 	m_coordNormal = 		m_shaderProgram.attributeLocation(QString::fromUtf8("coordNormals")); 	m_matrixVertex = 		m_shaderProgram.uniformLocation(QString::fromUtf8("matrixVertex")); 	m_matrixNormal = 		m_shaderProgram.uniformLocation(QString::fromUtf8("matrixNormal")); 	m_colorFragment = 		m_shaderProgram.uniformLocation(QString::fromUtf8("fragmentColor"));                  

With OpenGL, shaders are implemented using a linguistic communication known every bit GLSL. The language is designed to go far easy to manipulate 3D data before it is rendered. Here, we volition need two shaders: vertex shader and fragment shader. In vertex shader, we will transform the coordinates with the transformation matrix to apply rotation and zoom, and to calculate color. In fragment shader, we will assign color to the fragment. These shader programs must so be compiled and linked with the context. OpenGL provides simple ways of bridging the ii environments so that parameters inside the program may exist accessed or assigned from outside:

          // Get model transformation matrix QMatrix4x4 matrixVertex; ... // Calculate the matrix hither // Gear up Shader Program object' parameters m_shaderProgram.setUniformValue(m_matrixVertex, matrixVertex);                  

In the vertex shader code, we calculate the new vertex position past applying the transformation matrix on the original vertices:

          gl_Position = matrixVertex * vec4(coordVertexes, 1.0);                  

To compute this transformation matrix, we compute a few split up matrices: screen scale, translate scene, calibration, rotate, and middle. Nosotros then find the production of these matrices in order to compute the final transformation matrix. Start by translating the model middle to the origin (0, 0, 0), which is the centre of the screen every bit well. Rotation is determined past the user's interaction with the scene using some pointing device. The user tin click on the scene and drag effectually to rotate. When the user clicks, we store the cursor position, and after a move we have the 2nd cursor position. Using these two coordinates, forth with the scene eye, nosotros form a triangle. Post-obit some simple calculations we can decide the rotation angle, and nosotros can update our rotation matrix to reflect this change. For scaling, we simply rely on the mouse cycle to change the scaling factor of the X and Y axes of the OpenGL widget. The model is translated dorsum by 0.5 to keep it behind the plane from which the scene is rendered. Finally, to maintain the natural aspect ratio we need to adjust the decrease of the model expansion forth the longer side (unlike the OpenGL scene, the widget where it is rendered may have different physical dimensions along either axes). Combining all these, we summate the final transformation matrix as follows:

          void GlWidget::GetMatrixTransform(QMatrix4x4& matrixVertex,                                  const Model3DEx& model) {    matrixVertex.setToIdentity();     QMatrix4x4 matrixScaleScreen;    double dimMin = static_cast<double>(qMin(width(), height()));    float scaleScreenVert = static_cast<float>(dimMin /        static_cast<double>(height()));    float scaleScreenHorz = static_cast<float>(dimMin /        static_cast<double>(width()));    matrixScaleScreen.scale(scaleScreenHorz, scaleScreenVert, 1.0f);     QMatrix4x4 matrixCenter;    float centerX, centerY, centerZ;    model.GetCenter(centerX, centerY, centerZ);    matrixCenter.translate(-centerX, -centerY, -centerZ);     QMatrix4x4 matrixScale;    float radius = 1.0;    model.GetRadius(radius);    float scale = static_cast<float>(m_scaleCoeff / radius);    matrixScale.scale(scale, calibration, 0.5f / radius);     QMatrix4x4 matrixTranslateScene;    matrixTranslateScene.translate(0.0f, 0.0f, -0.5f);     matrixVertex = matrixScaleScreen * matrixTranslateScene * matrixScale * m_matrixRotate * matrixCenter; }                  

Conclusion

In this introduction to OpenGL 3D rendering, we explored one of the technologies that allow ud to utilize our video card to return a 3D model. This is much more efficient than using CPU cycles for the aforementioned purpose. We used a very unproblematic shading technique, and made the scene interactive through the handling of user inputs from the mouse. We avoided using the video retention jitney to pass data back-and-forth betwixt the video memory and the programme. Even though we merely rendered a single line of text in 3D, more than complicated scenes can be rendered in very similar ways.

To be fair, this tutorial has barely scratched the surface of 3D modeling and rendering. This is a vast topic, and this OpenGL tutorial tin can't claim this is all yous demand to know to exist able to build 3D games or modeling softwares. However, the purpose of this article is to give y'all a peek into this realm, and show how easily you can go started with OpenGL to build 3D applications.

rosalesrimay1971.blogspot.com

Source: https://www.toptal.com/opengl/introduction-to-opengl-a-quick-tutorial

Post a Comment for "drawing 3d table in opengl code"