Closed 8bitbunny closed 4 years ago
Thank you for the idea!
Sorry for my late comment,
it would be usefull for minigames, but also ui elements, like pebble did with their smartwatches
A small gif https://developer.pebble.com/assets/images/tutorials/advanced/action-completed.gif
Will look up some repos up right now
Here's one: https://github.com/Nand-e/Tiny3D-engine-STM32
Thank you. It seems resource friendly. But unfortunately it is written in C++. :(
it would be usefull for minigames
Yes, it would be eye-catching to see a 3D demo game. But I'm not sure it worth the effort. In addition LittlevGL is GUI library, it rather looks a brand new project.
A small gif https://developer.pebble.com/assets/images/tutorials/advanced/action-completed.gif
I think it is a gif (or more images played) and not a 3D rendered model.
So in my opinion 3D like elements in an embedded GUI library could appear as an animation of pre rendered images. What do you think?
To be precise: it is not a sees of images on the Pebble hardware, those animations are rendered real time, with drawing paths, to let em look like 3D and animated like a gif.
So, yeah, since 3D won't be a standard feature, maybe make a extension to lvgl? Like a separate repo which is optional to have?
The seperated repo sounds better! A compatible 3D engine would be nice to play and to try/learn 3D.
Probably in v6 it could be in the library. (For v5 already has a lot of new things)
Do you have any experience in 3D field and would you like to contribute in this feature?
I sadly don't have experience with 3D rendering at all, so I can't help much at all
I have some codes with my custom Gui. It needs polygon drawing functions. 3d calculations are made with quaternion and/or Euler arithmetic (rotation matrices). It requires drawing object pixel size buffer. (may be it's better to use line buffers or sprites but I couldn't handle this yet.). You need to import 3d model as vertices and colors. But could be modified for 2d graphics. Library doesn't have z-buffering, lighting, shading and texturing feature, only rotation, scaling and flat shading is available now. I don't have much time but anyone want to contribute I could help.
I used this routines with Funkos' modified fooeyGUI framework. So It could run even on a sensor node (like ti's sensortag with a sharp memory display). that gui running as a thread with contiki operating system.
By the way library complately optimized with fixed point math library don't use any floating point numbers so it's fast enough If I have time I would upload an video soon...
@tevfik It sounds very well. However LittlevGL is not a 3D library an optional 3D extension can be useful in some cases. Maybe you already know LittelvGL has a buffered mode where we have a pixel buffer. You said there is no z-buffering now. Without it can you render models properly with overlapping triangles?.
I'm really looking forward to see the video :)
By the way we are talking about polygon drawing in this topic: #146
just a small thing i saw in the airplane last night in their entertainment systems. the plane and globe were both a 3D model, and you could do simple navigation around the plane and globe. this might be a optional, but useful thing.
Wow, it look great! Thank you! Once we will have 3D render extension creating a demo like this would be awesome.
I'm organizing the issues and however, it's an interesting one, I close it because adding a 3D engine is a very big work and here is not plans to add it in the near future.
Despite of it if you or somebody make some progress or experiment in this field feel free to comment here and reopen the issue.
Wow, that's amazing! Congratulations!
Would you mind sharing your code? We have lv_lib_...
repos for 3rd parts libs. TinyGL could be added similarly if you are open to it.
I am not finding the libraries repository. Also, i am not able to reopen this issue to discuss possible optimizations to this implementation.
I am not finding the libraries repository.
We would create a new external library repository. Here is the current list.
Wow, that's amazing! Congratulations!
Would you mind sharing your code? We have
lv_lib_...
repos for 3rd parts libs. TinyGL could be added similarly if you are open to it.
The solution is quite simple. Let TinyGL render to a canvas buffer... but I am having trouble getting the colors right with 16 and 32 bit colors.
First attempt had 2 buffers for GL and the canvas copying the frame after it was rendered.
The second rendered directly to the canvas buffer and invalidating it after.
While lvgl is 32: ARGB8888, TinyGL is RGBA8888. This troubles SDL... TinyGL has a RGB_TO_PIXEL(r, g, b) macro to handle the pixel format, but the alpha byte is not used. I set it to FF manually.
TinyGL rendering to 16: RGB565 fits the embedded systems, but the canvas does not seem to suport it yet.
The solution is quite simple. Let TinyGL render to a canvas buffer... but I am having trouble getting the colors right with 16 and 32 bit colors.
I'm not familiar with TinyGL so don't how difficult to make it work.
TinyGL rendering to 16: RGB565 fits the embedded systems, but the canvas does not seem to suport it yet.
The canvas should support RGB565 mode if LV_COLOR_DEPTH
is 16
in lv_conf.h
.
Could you add a link to your project? I could take look to see what can be the problem. Besides, I'm very curious and would like to try it :slightly_smiling_face:
The solution is quite simple. Let TinyGL render to a canvas buffer... but I am having trouble getting the colors right with 16 and 32 bit colors.
I'm not familiar with TinyGL so don't how difficult to make it work.
TinyGL rendering to 16: RGB565 fits the embedded systems, but the canvas does not seem to suport it yet.
The canvas should support RGB565 mode if
LV_COLOR_DEPTH
is16
inlv_conf.h
.Could you add a link to your project? I could take look to see what can be the problem. Besides, I'm very curious and would like to try it 🙂
TinyGL source code is written to be fast and with some hard to follow macros.
It can be used as it is, or maybe we can replace these pixel and line (zline.c) functions to use the anti aliased canvas functions.
Quickly copied over the necessary files and tested it on STM32. It appears to be running quite smoothly although I don't have time to check the frame rate tonight. :+1:
Thank you! I've tried it in the simulator and it works well here too.
@barbiani Do you know if there is a way to load model and its textures to TinyGL and set camera position?
Thank you! I've tried it in the simulator and it works well here too.
Do expect wrong colors in the rendering!
@barbiani Do you know if there is a way to load model and its textures to TinyGL and set camera position?
I will start here https://en.m.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Load_OBJ http://kixor.net/dev/objloader/ http://tfc.duke.free.fr/coding/src/obj.c
TinyGL can render at least triangle lists, light sources, textures and camera positioning. Says its readme.
I was able to make the last loader @barbiani sent work, with some modifications.
You need this OBJ file, this MTL file, and the code I've attached below. You can then replace the call to gears_update
with showmodel_update
and change gears_init
to showmodel_init (CANVAS_WIDTH, CANVAS_HEIGHT, cbuf, "test.obj")
.
At this point the viewport gets filled with color, so I assume I'm looking at a 3D model. However, I must admit that I have no idea how to move the camera with TinyGL, so I don't know whether this is actually being drawn properly or not.
/*
* showmodel.c -- obj model loader (modified for TinyGL+LittlevGL)
*
* Copyright (c) 2005-2007 David HENRY
* Modifications made by embeddedt
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "tinygl/gl.h"
#include "tinygl/zbuffer.h"
#include "tinygl/gears.h"
ZBuffer* frameBuffer;
/* Vectors */
typedef float vec3_t[3];
typedef float vec4_t[4];
/* Vertex */
struct obj_vertex_t
{
vec4_t xyzw;
};
/* Texture coordinates */
struct obj_texCoord_t
{
vec3_t uvw;
};
/* Normal vector */
struct obj_normal_t
{
vec3_t ijk;
};
/* Polygon */
struct obj_face_t
{
GLenum type; /* primitive type */
int num_elems; /* number of vertices */
int *vert_indices; /* vertex indices */
int *uvw_indices; /* texture coordinate indices */
int *norm_indices; /* normal vector indices */
};
/* OBJ model structure */
struct obj_model_t
{
int num_verts; /* number of vertices */
int num_texCoords; /* number of texture coords. */
int num_normals; /* number of normal vectors */
int num_faces; /* number of polygons */
int has_texCoords; /* has texture coordinates? */
int has_normals; /* has normal vectors? */
struct obj_vertex_t *vertices; /* vertex list */
struct obj_texCoord_t *texCoords; /* tex. coord. list */
struct obj_normal_t *normals; /* normal vector list */
struct obj_face_t *faces; /* model's polygons */
};
/*** An OBJ model ***/
struct obj_model_t objfile;
/**
* Free resources allocated for the model.
*/
void
FreeModel (struct obj_model_t *mdl)
{
int i;
if (mdl)
{
if (mdl->vertices)
{
free (mdl->vertices);
mdl->vertices = NULL;
}
if (mdl->texCoords)
{
free (mdl->texCoords);
mdl->texCoords = NULL;
}
if (mdl->normals)
{
free (mdl->normals);
mdl->normals = NULL;
}
if (mdl->faces)
{
for (i = 0; i < mdl->num_faces; ++i)
{
if (mdl->faces[i].vert_indices)
free (mdl->faces[i].vert_indices);
if (mdl->faces[i].uvw_indices)
free (mdl->faces[i].uvw_indices);
if (mdl->faces[i].norm_indices)
free (mdl->faces[i].norm_indices);
}
free (mdl->faces);
mdl->faces = NULL;
}
}
}
/**
* Allocate resources for the model after first pass.
*/
int
MallocModel (struct obj_model_t *mdl)
{
if (mdl->num_verts)
{
mdl->vertices = (struct obj_vertex_t *)
malloc (sizeof (struct obj_vertex_t) * mdl->num_verts);
if (!mdl->vertices)
return 0;
}
if (mdl->num_texCoords)
{
mdl->texCoords = (struct obj_texCoord_t *)
malloc (sizeof (struct obj_texCoord_t) * mdl->num_texCoords);
if (!mdl->texCoords)
return 0;
}
if (mdl->num_normals)
{
mdl->normals = (struct obj_normal_t *)
malloc (sizeof (struct obj_normal_t) * mdl->num_normals);
if (!mdl->normals)
return 0;
}
if (mdl->num_faces)
{
mdl->faces = (struct obj_face_t *)
calloc (mdl->num_faces, sizeof (struct obj_face_t));
if (!mdl->faces)
return 0;
}
return 1;
}
/**
* Load an OBJ model from file -- first pass.
* Get the number of triangles/vertices/texture coords for
* allocating buffers.
*/
int
FirstPass (FILE *fp, struct obj_model_t *mdl)
{
int v, t, n;
char buf[256];
while (!feof (fp))
{
/* Read whole line */
fgets (buf, sizeof (buf), fp);
switch (buf[0])
{
case 'v':
{
if (buf[1] == ' ')
{
/* Vertex */
mdl->num_verts++;
}
else if (buf[1] == 't')
{
/* Texture coords. */
mdl->num_texCoords++;
}
else if (buf[1] == 'n')
{
/* Normal vector */
mdl->num_normals++;
}
else
{
printf ("Warning: unknown token \"%s\"! (ignoring)\n", buf);
}
break;
}
case 'f':
{
/* Face */
if (sscanf (buf + 2, "%d/%d/%d", &v, &n, &t) == 3)
{
mdl->num_faces++;
mdl->has_texCoords = 1;
mdl->has_normals = 1;
}
else if (sscanf (buf + 2, "%d//%d", &v, &n) == 2)
{
mdl->num_faces++;
mdl->has_texCoords = 0;
mdl->has_normals = 1;
}
else if (sscanf (buf + 2, "%d/%d", &v, &t) == 2)
{
mdl->num_faces++;
mdl->has_texCoords = 1;
mdl->has_normals = 0;
}
else if (sscanf (buf + 2, "%d", &v) == 1)
{
mdl->num_faces++;
mdl->has_texCoords = 0;
mdl->has_normals = 0;
}
else
{
/* Should never be there or the model is very crappy */
fprintf(stderr,"Error: found face with no vertex!\n");
}
break;
}
case 'g':
{
/* Group */
/* fscanf (fp, "%s", buf); */
break;
}
default:
break;
}
}
/* Check if informations are valid */
if ((mdl->has_texCoords && !mdl->num_texCoords) ||
(mdl->has_normals && !mdl->num_normals))
{
fprintf(stderr,"error: contradiction between collected info!\n");
return 0;
}
if (!mdl->num_verts)
{
fprintf(stderr,"error: no vertex found!\n");
return 0;
}
printf ("first pass results: found\n");
printf (" * %i vertices\n", mdl->num_verts);
printf (" * %i texture coords.\n", mdl->num_texCoords);
printf (" * %i normal vectors\n", mdl->num_normals);
printf (" * %i faces\n", mdl->num_faces);
printf (" * has texture coords.: %s\n", mdl->has_texCoords ? "yes" : "no");
printf (" * has normals: %s\n", mdl->has_normals ? "yes" : "no");
return 1;
}
/**
* Load an OBJ model from file -- first pass.
* This time, read model data and feed buffers.
*/
int
SecondPass (FILE *fp, struct obj_model_t *mdl)
{
struct obj_vertex_t *pvert = mdl->vertices;
struct obj_texCoord_t *puvw = mdl->texCoords;
struct obj_normal_t *pnorm = mdl->normals;
struct obj_face_t *pface = mdl->faces;
char buf[128], *pbuf;
int i;
while (!feof (fp))
{
/* Read whole line */
fgets (buf, sizeof (buf), fp);
switch (buf[0])
{
case 'v':
{
if (buf[1] == ' ')
{
/* Vertex */
if (sscanf (buf + 2, "%f %f %f %f",
&pvert->xyzw[0], &pvert->xyzw[1],
&pvert->xyzw[2], &pvert->xyzw[3]) != 4)
{
if (sscanf (buf + 2, "%f %f %f", &pvert->xyzw[0],
&pvert->xyzw[1], &pvert->xyzw[2] ) != 3)
{
fprintf(stderr,"Error reading vertex data!\n");
return 0;
}
else
{
pvert->xyzw[3] = 1.0;
}
}
pvert++;
}
else if (buf[1] == 't')
{
/* Texture coords. */
if (sscanf (buf + 2, "%f %f %f", &puvw->uvw[0],
&puvw->uvw[1], &puvw->uvw[2]) != 3)
{
if (sscanf (buf + 2, "%f %f", &puvw->uvw[0],
&puvw->uvw[1]) != 2)
{
if (sscanf (buf + 2, "%f", &puvw->uvw[0]) != 1)
{
fprintf(stderr,"Error reading texture coordinates!\n");
return 0;
}
else
{
puvw->uvw[1] = 0.0;
puvw->uvw[2] = 0.0;
}
}
else
{
puvw->uvw[2] = 0.0;
}
}
puvw++;
}
else if (buf[1] == 'n')
{
/* Normal vector */
if (sscanf (buf + 2, "%f %f %f", &pnorm->ijk[0],
&pnorm->ijk[1], &pnorm->ijk[2]) != 3)
{
fprintf(stderr,"Error reading normal vectors!\n");
return 0;
}
pnorm++;
}
break;
}
case 'f':
{
pbuf = buf;
pface->num_elems = 0;
/* Count number of vertices for this face */
while (*pbuf)
{
if (*pbuf == ' ')
pface->num_elems++;
pbuf++;
}
/* Select primitive type */
if (pface->num_elems < 3)
{
fprintf(stderr,"Error: a face must have at least 3 vertices!\n");
return 0;
}
else if (pface->num_elems == 3)
{
pface->type = GL_TRIANGLES;
}
else if (pface->num_elems == 4)
{
pface->type = GL_QUADS;
}
else
{
pface->type = GL_POLYGON;
}
/* Memory allocation for vertices */
pface->vert_indices = (int *)malloc (sizeof (int) * pface->num_elems);
if (mdl->has_texCoords)
pface->uvw_indices = (int *)malloc (sizeof (int) * pface->num_elems);
if (mdl->has_normals)
pface->norm_indices = (int *)malloc (sizeof (int) * pface->num_elems);
/* Read face data */
pbuf = buf;
i = 0;
for (i = 0; i < pface->num_elems; ++i)
{
pbuf = strchr (pbuf, ' ');
pbuf++; /* Skip space */
/* Try reading vertices */
if (sscanf (pbuf, "%d/%d/%d",
&pface->vert_indices[i],
&pface->uvw_indices[i],
&pface->norm_indices[i]) != 3)
{
if (sscanf (pbuf, "%d//%d", &pface->vert_indices[i],
&pface->norm_indices[i]) != 2)
{
if (sscanf (pbuf, "%d/%d", &pface->vert_indices[i],
&pface->uvw_indices[i]) != 2)
{
sscanf (pbuf, "%d", &pface->vert_indices[i]);
}
}
}
/* Indices must start at 0 */
pface->vert_indices[i]--;
if (mdl->has_texCoords)
pface->uvw_indices[i]--;
if (mdl->has_normals)
pface->norm_indices[i]--;
}
pface++;
break;
}
}
}
printf ("second pass results: read\n");
printf (" * %li vertices\n", pvert - mdl->vertices);
printf (" * %li texture coords.\n", puvw - mdl->texCoords);
printf (" * %li normal vectors\n", pnorm - mdl->normals);
printf (" * %li faces\n", pface - mdl->faces);
return 1;
}
/**
* Load an OBJ model from file, in two passes.
*/
int
ReadOBJModel (const char *filename, struct obj_model_t *mdl)
{
FILE *fp;
fp = fopen (filename, "r");
if (!fp)
{
fprintf(stderr,"Error: couldn't open \"%s\"!\n", filename);
return 0;
}
/* reset model data */
memset (mdl, 0, sizeof (struct obj_model_t));
/* first pass: read model info */
if (!FirstPass (fp, mdl))
{
fclose (fp);
return 0;
}
rewind (fp);
/* memory allocation */
if (!MallocModel (mdl))
{
fclose (fp);
FreeModel (mdl);
return 0;
}
/* second pass: read model data */
if (!SecondPass (fp, mdl))
{
fclose (fp);
FreeModel (mdl);
return 0;
}
fclose (fp);
return 1;
}
/**
* Draw the OBJ model.
*/
void
RenderOBJModel (struct obj_model_t *mdl)
{
int i, j;
for (i = 0; i < mdl->num_faces; ++i)
{
glBegin (mdl->faces[i].type);
for (j = 0; j < mdl->faces[i].num_elems; ++j)
{
if (mdl->has_texCoords) {
GLfloat *v = mdl->texCoords[mdl->faces[i].uvw_indices[j]].uvw;
glTexCoord4f (v[0], v[1], v[2], 1);
}
if (mdl->has_normals)
glNormal3fv (mdl->normals[mdl->faces[i].norm_indices[j]].ijk);
GLfloat *v = mdl->vertices [mdl->faces[i].vert_indices[j]].xyzw;
glVertex4f (v[0], v[1], v[2], v[3]);
}
glEnd();
}
}
void
init (const char *filename)
{
GLfloat lightpos[] = { 5.0f, 10.0f, 0.0f, 1.0f };
/* Initialize OpenGL context */
glClearColor (0.5f, 0.5f, 0.5f, 1.0f);
glShadeModel (GL_SMOOTH);
glEnable (GL_DEPTH_TEST);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glLightfv (GL_LIGHT0, GL_POSITION, lightpos);
/* Load OBJ model file */
if (!ReadOBJModel (filename, &objfile))
exit (EXIT_FAILURE);
}
void
cleanup ()
{
FreeModel (&objfile);
}
void
reshape (int w, int h)
{
if (h == 0)
h = 1;
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (45.0, w/(GLdouble)h, 0.1, 1000.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
//glutPostRedisplay ();
}
void
showmodel_update (void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
glTranslatef (0.0f, 0.0f, -15.0f);
/* Draw the model */
RenderOBJModel (&objfile);
//glutSwapBuffers ();
}
void
showmodel_init (int w, int h, void *cbuf, char *filename)
{
frameBuffer = ZB_open(w, h, ZB_MODE_5R6G5B, 0, NULL, NULL, cbuf);
// initialize GL:
glInit(frameBuffer);
glClearColor(0.0, 0.0, 0.0, 0.0);
glViewport(0, 0, w, h);
init(filename);
}
This is also my first opengl attempt.
Looks like setting the camera is in gluPerspective (45.0, w/(GLdouble)h, 0.1, 1000.0). There is also a camera setting in the model file.
TinyGL is an opengl subset, so the latter documentation can be used.
https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml
Your post has: / Initialize OpenGL context / glClearColor (0.5f, 0.5f, 0.5f, 1.0f);
Tried myselft to get a grey background but this rgb at .5 turned out yellow. Something was not right. This is probably the color you are seeing.
I've found the root of the color issue. There was a bug in RGB_TO_PIXEL
macro (zbuffer.h). Here is the corrected version:
/* 16 bit mode */
#define RGB_TO_PIXEL(r,g,b) \
(((r) & 0xF800) | (((g >> 5)) & 0x07E0) | ((b) >> 11))
@embeddedt
That's great that you find this example! I couldn't figure out which version of OpenGL TinyGL is compatible with.
I've tried your code but it crashed for me. The problem is that it finds 7 normals, but still says "has normal: no" therefore the array of normals is not allocated and NULL
is referenced.
first pass results: found
* 17 vertices
* 3 texture coords.
* 7 normal vectors
* 12 faces
* has texture coords.: no
* has normals: no
I've created the lv_lib_tinygl repo for easier code sharing. @barbiani, I've granted write access to you. @embeddedt, could you upload your code there?
I've found the root of the color issue. There was a bug in 'RGB_TO_PIXEL' macro (zbuffer.h). Here is the corrected version:
I tried editing initScene() to make red, green and blue colors pure. The array format seems to be RGBA. Do that and you will see the color errors I was talking about.
void initScene() { static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; static GLfloat red[4] = { 1.0, 0.0, 0.0, 1.0 }; static GLfloat green[4] = { 0.0, 1.0, 0.0, 1.0 }; static GLfloat blue[4] = { 0.0, 0.0, 1.0, 1.0 }; ... }
Correct look:
I see the issue. However, if I set glClearColor(0.0, 0.0, 1.0, 1.0);
or glClearColor(0.0, 1.0, 0.0, 1.0);
in gear_init
I got the correct colors in the bacground. Probably It's an other bug in the renderer.
I'll take a look.
I've found it. It was really a bug deep in the renderer. Actually it was a critical thing: GLParam
is an union with many types. An op_list (an array of GLParam
) is built from it where opcodes and values are stored. However, at some point, the array was converted to float *
. I suppose not float
is the largest member of the union so indexing the array this way made the parameters corrupted. It was easy to fix, but I wonder how many of similar issues could be there.
Now it works for me with 16 bit color depth.
I uploaded my current version to lv_lib_tinygl
.
You are fast! I did not know it was a bug there because I managed to get the right gear colors, but not the grey background by changing the RGB_TO_PIXEL macro and the gear color definitions.
The original tinygl package has more files than I had in my project.
https://github.com/ska80/tinygl
One of them is LIMITATIONS:
` Here are listed the functions that TinyGL understands with the known limitations. The non mentionned functions are not implemented and must not be used.
**** glEnable / glDisable
GL_CULL_FACE, GL_LIGHTING, GL_COLOR_MATERIAL, GL_TEXTURE_2D, GL_NORMALIZE, GL_LIGHTx, GL_POLYGON_OFFSET_FILL, GL_POLYGON_OFFSET_POINT, GL_POLYGON_OFFSET_LINE
**** glShadeModel
OK.
**** glCullFace
OK.
**** glPolygonMode
OK.
**** glBegin
No tests are performed to prevent some functions of being executed between glBegin/glEnd.
**** glEnd
OK.
**** glVertex
Some prototypes are not implemented.
**** glColor
Some prototypes are not implemented.
**** glNormal
Some prototypes are not implemented.
**** glTexCoord
Some prototypes are not implemented.
The Matrix transformation is not applied yet.
**** glEdgeFlag
OK. The edge handling has to be tested, although it is not much useful in TinyGL.
**** glMatrixMode / glLoadMatrixf / glLoadIdentity / glMultMatrixf / glPushMatrix / glPopMatrix / glRotatef / glTranslatef / glScalef / glFrustum
**** glViewport
GlViewport calls a function pointers to tell glx (or another display system) to resize the Z buffer and the ximage. Made optional in version 0.2.
**** glGenLists / glIsList / glNewList / glEndList / glCallList
OK.
**** glClear / glClearColor / glClearDepth
The whole zbuffer and the colors are cleared in any case. The clear color can be redefined, by not the initial z value.
**** glRenderMode
Only the modes GL_RENDER and GL_SELECT are implemented.
**** glSelectBuffer / glInitNames / glPushName / glPopName / glLoadName
OK.
**** glGenTextures / glDeleteTextures / glBindTexture
OK. These functions should be used to get the maximum performance with TinyGL.
**** glTexImage2D
The function accepts only RGB UNSIGNED_BYTES bitmaps. They are internally resized to 256x256 so you'd better use that size. No mipmapping is implemented although it will come if asked. No borders are implemented.
**** glTexEnvi
The only supported mode is GL_DECAL, although others are planned if asked.
**** glTexParameteri
The other prototypes are not implemented. Only the follwing mode are implemented:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
**** glPixelStorei
The pixels are alware byte aligned.
**** glMaterialfv / glMaterialf / glColorMaterial
OK.
**** glLightfv / glLightf / glLightModeli / glLightModelfv
OK. The OpenGL lightening is implemented but not optimized.
**** glFlush
Ignored.
**** glHint
Ignored.
**** glGetIntegerv
**** glGetIntegerv
**** glPolygonOffset
**** glEnableClientState, glDisableClientState,
**** glVertexPointer, glNormalPointer, glColorPointer, glTexureCoordPointer
TinyGL GLX emulation:
**** glXQueryExtension
Returns always True
**** glXChooseVisual
Only 8 bit Pseudocolor or 16 bit Truecolor Visual are accepted. The attribute list is ignored.
**** glXCreateContext
The sharing is not implemented although the code could handle it.
**** glXDestroyContext
OK.
**** glXMakeCurrent
Not all the syntax is supported yet, in particular with the 'NULL' or 'None' parameters.
**** glXSwapBuffers
OK.
**** glXWaitGL / glXWaitX
Ignored.
See README.BEOS for BeOS limitations. `
For the 3d model rendering I believe that we should parse the obj file, removing comments, including the mtl and changing any texture bitmap to the supported format and writing to a const byte array.
Let's wait until @embeddedt will have time to upload his code to lv_lib_tinygl
.
Further research found this. Might give good results with lvgl.
https://gitlab.com/drummyfish/small3dlib
Discussion about it: https://forum.freegamedev.net/viewtopic.php?f=22&t=11747
Single header library. All it needs is a setpixel function.. compatible with the canvas object.
Looks nice! It definitely appears to have been optimized for memory-constrained environments.
We could probably even get it to render directly through LittlevGL's rendering system instead of needing a separate buffer+canvas.
Really an interesting option, although I'm concerned about the rendering quality if small3dlib due to integer arithmetics.
IMO if the user needs 3D he can afford the use of float for better quality. What do you think?
I played with small3dlib
a bit today and it would definitely be a good fit for someone trying to recreate a retro game on a microcontroller. I'm not sure how useful it would be for rendering "modern" 3D models, but for simple games it might suffice.
Performance may be an issue - I ran it rendering directly to the framebuffer (i.e. without LittlevGL) and my STM32F746 was only able to get 1-2 FPS at 480x272 resolution. I did not have the CPU cache on, however. That probably would have given much better results.
Going back to TinyGL, my code appears to be in objtest.c
. It does look like some modifications have been made to it though. In particular, ReadOBJModel
should not be commented out here.
If the user needs 3D he can afford the use of float for better quality. What do you think?
I agree. The author of small3dlib
actually writes here that calculations with HW floating-point operations would be faster than fixed-point integer operations in some cases.
I'm also wondering whether full-on 3D rendering capabilities are necessary. Consider the 3D transformation features available in CSS nowadays. If we had the ability to draw things on the canvas and rotate them in 3D space, the plane information interface linked above could be recreated without the need to render any 3D models.
Performance may be an issue - I ran it rendering directly to the framebuffer (i.e. without LittlevGL) and my STM32F746 was only able to get 1-2 FPS at 480x272 resolution. I did not have the CPU cache on, however. That probably would have given much better results.
Do I remember well that you have seen a good FPS with TinyGL?
Consider the 3D transformation features available in CSS nowadays.
I'm learning texture mapping and other basics of 3D rendering to see how to realize a "simple" perspective effect on a canvas. Something like rotate-y in CSS.
Instead of a 3D globe model, a series of 2D images could be used, or a flat 2D map could be used.
What about the plane itself? It also could be a 3D model which is rotated. I've seen car dashboards where the model of the car was rotated, moved, zoomed and the doors opened and closed.
Perhaps the compass underneath the plane could rotate instead of the plane itself. Then the plane could be a static 2D image.
With rotate and perspective effect it really could be a normal image.
I'll try the updated code again. I'm still busy with dev-7.0
and probably will have time for it only at the end of the week.
you have seen a good FPS with TinyGL?
Yes. It was much smoother.
Then it seems like a clear decision here. If TinyGL seems faster and has better quality then we should go with it.
@embeddedt I've added a lv_tinygl_test.c which uses the mentioned model but it still crashes for me due to the same inconsistency:
* 17 vertices
* 3 texture coords.
* 7 normal vectors
* 12 faces
* has texture coords.: no #How? There are 3 as stated above
* has normals: no #How? There are 7 as stated above
Could you take a look is it already worked for you? Only lv_tinygl_test()
needs to be called.
Maybe I missed it but where the MTL file is loaded?
Could you take a look is it already worked for you?
Sure; I'll take a look.
Maybe I missed it but where the MTL file is loaded?
It's referenced inside the OBJ file.
@kisvegabor I think I've fixed that issue now, but I am still unable to get anything to appear on the screen besides the gray background.
Thank you for the fix. It works better but I also see only the gray background. I've tried to understand what's going on inside TinyGL but find nothing so far. It's new territory for me so there are a lot of unclear parts.
This issue or pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I didn't have time to figure out why we can't see any output and now I'm working with full capacity on v7. :disappointed:
I still belive the 3D extension would be very useful, but I have no time deal with it now.
This issue or pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I close this issue in lack of activity :frowning_face: Feel free to comment here if you are interested in working on it.
I close this issue in lack of activity ☹️ Feel free to comment here if you are interested in working on it.
I lack the knowledge to push this forward. But there really should be 3D support in LVGL. It would be a great addition!
Is there any chance of 3D functions to the engine? Like lights, polygons, meshes, vertexes. (There are some repos on GitHub for MCU's that have some of these features)