View Full Version : M15 - reimplementation via GBuffers
Petr Schreiber
12-03-2016, 09:02
Hi guys,
I was thinking about the M15 from memory a lot last days, and I got a crazy idea (my default kind of ideas).
What about re-implementing the M15 as ThinBASIC TWF (TYPE with FUNCTIONs), using TBGL GBuffers as backend?
Advantage:
- much faster rendering than current M15 backend
- dynamic allocation, no longer needed to specify number of models and their dimensions ahead
- thinBasic code layer, adjustable by anyone
Where is the code?
https://github.com/petrSchreiber/m15Model
How can I use it?
Please note the current implementation is in pre-release phase, targetted at testing.
You can grab the files from releases page (https://github.com/petrSchreiber/m15Model/releases).
How difficult it is to use?
Not much :) After you download the includes, it can be as simple as:
#include "m15Model.tbasicu"
...
dim model as m15Model
model.FromFile("C:\myModel.m15")
' -- or
String memoryBuffer = file_load("C:\myModel.m15")
model.FromMemory(memoryBuffer)
...
model.render
Feedback welcome!
Looking forward to your feedback. And if it is the way to go for you, please attach your M15 models, so I can use them as test data!
Petr
Hi Petr
i suggest a model such as the obj model here https://github.com/vispy/demo-data/blob/master/orig/triceratops.obj.gz
i have converted it to triceratops.M15 its size 1.5MB so it is complex and big enough and can be viewed okay with thinedge
attached the triceratops.M15.rar
could be made into GitHub project
yes this is a good choice
can't comment on the technical sides.
this is a great detailed meshes with textures
http://graphics.williams.edu/data/meshes.xml
look at this HairBall created by NVIDIA Research 250 MB obj file, can't convert it to M15. i can't even load it in my 3d viewer to view it as obj file. it needs a powerful computer.
Cornil Box seems interesting with textures, but it is several files
Petr,
You have mention M15 in several posts lately. What is it, and where can it be downloaded?
Bill
Petr Schreiber
12-03-2016, 15:44
Hi Bilbo,
m15 is a 3D model format, which can be loaded and displayed in thinBASIC using TBGL module.
You can convert industry standard OBJ models to M15 using batch convertor (http://www.thinbasic.com/community/showthread.php?8585-TBGL-OBJ-to-M15-converter-UPDATED-to-v-1-5&highlight=obj2m15).
If interested, checkout examples in thinBasic\SampleScripts\TBGL\m15Models\
Petr
i have converted the sibenik cathedral model from http://graphics.williams.edu/data/meshes.xml to m15 model, i have used example TBGL_UserDataStorage.tbasic from the thinbasic examples, wait a few seconds and you will see what is like a space station with a ufo above. but i can't get it textured. here is what i see in my computer :
9585
i think it is suitable for Petr to test since it a heavy model with textures.
change the load models code in the example TBGL_UserDataStorage.tbasic like this
' -- Load models
tbgl_m15InitModelBuffers 1, 2500
tbgl_m15LoadModel APP_SOURCEPATH+"Models\alien1.m15", "Textures\", 1, 1, %TBGL_NORMAL_SMOOTH
tbgl_m15ClearModel 1
TBGL_m15LoadModel APP_SourcePath+"Models\sibenik.M15", "Textures\", 1, 2, %TBGL_NORMAL_SMOOTH
tbgl_m15ClearModel 1
tbgl_m15LoadModel APP_SOURCEPATH+"Models\alien3.m15", "Textures\", 1, 3, %TBGL_NORMAL_SMOOTH
here is the model with textures save it to C:\thinBasic\SampleScripts\TBGL\EntityBased\Models
http://wikisend.com/download/968692/sibenik.M15.rar
Petr Schreiber
12-03-2016, 16:39
Thank you Primo,
this will help me to see what is the performance about :)
Textures did not load, because PNG is not supported (now, I have it on list).
Petr
Michael Hartlef
16-03-2016, 14:46
That sounds actually like a very good idea!
Petr Schreiber
20-03-2016, 13:08
Thanks Mike!
Moving from paper stage to implementation. You can track the progress here:
https://github.com/petrSchreiber/m15Model
I started with auxiliary routines (logger, validator).
Petr
Hi Petr, i have found that there is too much interests with Quad meshes, i was not aware before. many graphics engines does not support quad mesh and they convert it first to triangles mostly erroneously. but most new versions of the modelers have a tris to quad tool or (quadify mesh) like in the Blender in the mesh sub menu. it is good your graphics engine support the quad mesh. i have tested it with an obj file made from quads and converted successfully by the obj2m15 tool to m15 file
i have found several quad meshes (quad_meshes.zip) in the site : http://vcg.isti.cnr.it/quadSemplif/ you may be interested in checking the quad mesh aware feature of your engine . the site have also a video demo.
attached a deforming of the head made from quads mostly: (needs "womanhead.m15" file attached below)
9593
'
' TBGL Waves
'
Uses "TBGL","math"
Dim hWnd As DWord
Global tot, num, flag, indx, wireframe As Long
num = 1
Global v, ro, y2, x2, z2, part As Single
part = 0.99
hWnd = TBGL_CreateWindowEx("press 'W' for wire/solid Frame .... press ESC to quit", 640, 600, 32, 0)
TBGL_ShowWindow
TBGL_m15InitModelBuffers 1, 2000
'TBGL_PolygonLook %GL_LINE
TBGL_m15LoadModel "womanhead.m15", "", 1, 0, %TBGL_NORMAL_SMOOTH
TBGL_GetAsyncKeyState(-1) ' Resets status of all keys
Dim gFrameTime As Long
TBGL_UseLighting 1
TBGL_UseLightSource %GL_LIGHT0, 1
'tot = TBGL_m15GetModelVertexcount(1)
'MsgBox 0, tot
gFrameTime = GetTickCount
While TBGL_IsWindow(hWnd)
If TBGL_GetWindowKeyOnce( hWnd, %VK_W) Then
If wireframe = 0 Then
TBGL_PolygonLook %GL_LINE
wireframe = 1
Else
TBGL_PolygonLook %GL_FILL
wireframe = 0
End If
End If
gFrameTime = GetTickCount
TBGL_ClearFrame
TBGL_Camera 0,7,16,0,2,0
waves()
If tot = 0 Then
num = 1
part = 0.99
ElseIf tot =100 Then
num = -1
part = 1.01
End If
tot = tot + num
TBGL_m15RecalcNormals 1, %TBGL_NORMAL_SMOOTH
ro+1
TBGL_Rotate ro-90 , 0, 1, 0
TBGL_m15DrawModel 1
TBGL_DrawFrame
If TBGL_GetWindowKeyState( hWnd, %VK_ESCAPE) Then Exit While
Wend
TBGL_DestroyWindow
Sub waves()
Long i, vertex
Local x,y,z, YY, XX, ZZ As Single
vertex = TBGL_m15GetModelVertexcount(1)
YY = y
For i = 1 To vertex
TBGL_m15GetVertexXYZ(1, i, x, y, z)
XX = x*part
ZZ = z*part
YY = y*part
If yy < 2 Then
yy = y
ElseIf yy > 6 Then
yy = y
End If
TBGL_m15SetVertexXYZ(1, i, XX,YY,Z)
TBGL_m15SetVertexRGB( 1, i, 100,160,100)
Next
End Sub
Petr Schreiber
20-03-2016, 16:00
You are very kind,
I was just looking for some material to test my parser on. Perfect! :)
Petr
Petr Schreiber
22-03-2016, 20:28
I need some help from Eros, but my early tests show good parsing performance of the early implementation - triceratops is already dancing on my screen, woman head will be more complex, as it combines triangles and quads :)
Petr
Petr Schreiber
25-03-2016, 23:35
I updated the code with gBufferBuilder, which allows to define iteratively a gBuffer. By using this type it is already possible to produce some visible geometry.
Next step is to analyse m15 buffer in order to resolve all submeshes which would be automatically converted to gBuffers of correct type (triangles/quads/polygons).
Petr
Petr Schreiber
27-03-2016, 09:52
With a bit of work, the current version at GitHub allows to render geometry - from memory or from file.
The performance of meshes with uniform type (just triangles/quads) matches the m15DrawModel, but in case of mixed types, it is still slower.
The reason is in the way the gBuffer groups are created - every time a texture or type of polygon changes.
This way it can happen that model such as woman head in this thread ends up having 500+ gBuffers, on which I need to iterate.
So next step will be smarter polygon batching to gBuffers.
If you are interested in first version for testing, please read the first post (http://www.thinbasic.com/community/showthread.php?12666-M15-reimplementation-via-GBuffers) to learn about the use and where to get the code.
Petr
Hi Petr
i have downloaded your m15 package. and have saved the following m15 viewer code in the folder m15Model which have 9 files. but there is an error msg : Dim type not defined , Dim model As m15Model http://s9.postimg.org/id378qp0f/msg.png
how to edit this viewer code so to work with your new package.
thanks
'#INCLUDE "m15Model.tbasicu"
Uses "TBGL","math"
Dim hWnd As DWord
Global tot, num, flag, indx, wireframe As Long
num = 1
Global v, ro, y2, x2, z2, part As Single
part = 0.99
hWnd = TBGL_CreateWindowEx("press 'W' for wire/solid Frame .... press ESC to quit", 640, 600, 32, 0)
TBGL_ShowWindow
'Dim model As m15Model
TBGL_m15InitModelBuffers 1, 2000
'TBGL_PolygonLook %GL_LINE
TBGL_m15LoadModel "womanhead.m15", "", 1, 0, %TBGL_NORMAL_SMOOTH
TBGL_GetAsyncKeyState(-1) ' Resets status of all keys
Dim gFrameTime As Long
TBGL_UseLighting 1
TBGL_UseLightSource %GL_LIGHT0, 1
gFrameTime = GetTickCount
While TBGL_IsWindow(hWnd)
If TBGL_GetWindowKeyOnce( hWnd, %VK_W) Then
If wireframe = 0 Then
TBGL_PolygonLook %GL_LINE
wireframe = 1
Else
TBGL_PolygonLook %GL_FILL
wireframe = 0
End If
End If
gFrameTime = GetTickCount
TBGL_ClearFrame
TBGL_Camera 0,7,16,0,2,0
'waves()
TBGL_m15RecalcNormals 1, %TBGL_NORMAL_SMOOTH
ro+1
TBGL_Rotate ro-90 , 0, 1, 0
TBGL_m15DrawModel 1
'model.render 1
TBGL_DrawFrame
If TBGL_GetWindowKeyState( hWnd, %VK_ESCAPE) Then Exit While
Wend
TBGL_DestroyWindow
Petr Schreiber
27-03-2016, 19:33
Hi Primo,
good catch! The problem was that GitHub automatically converted the line endings to Unix.
I fixed this issue, and made a new release. Grab it here:
https://github.com/petrSchreiber/m15Model/releases/tag/v0.1.1
Here is code which works fine with it:
Uses "tbgl", "math"
#INCLUDE "m15Model/m15Model.tbasicu" ' -- can be just m15Model.tbasicu, depends where your code is :]
Long tot, flag, indx, wireframe
Long num = 1
Single v, ro, y2, x2, z2
Single part = 0.99
DWord hWnd = TBGL_CreateWindowEx("press 'W' for wire/solid Frame .... press ESC to quit", 640, 600, 32, 0)
TBGL_ShowWindow
Dim model As m15Model
model.fromFile(APP_SourcePath + "womanhead.m15")
TBGL_ResetKeyState
Long gFrameTime
TBGL_UseLighting TRUE
TBGL_UseLightSource %GL_LIGHT0, 1
gFrameTime = GetTickCount
While TBGL_IsWindow(hWnd)
If TBGL_GetWindowKeyOnce( hWnd, %VK_W) Then
wireframe = Not wireframe
TBGL_PolygonLook IIf(wireframe, %GL_LINE, %GL_FILL)
End If
gFrameTime = GetTickCount
TBGL_ClearFrame
TBGL_Camera 0, 7, 16, 0, 2, 0
ro+1
TBGL_Rotate ro-90 , 0, 1, 0
model.render
TBGL_DrawFrame
If TBGL_GetWindowKeyState( hWnd, %VK_ESCAPE) Then Exit While
Wend
TBGL_DestroyWindow
Petr
Thank you Petr, yes it works now with v0.1.1 and also it works with
String memoryBuffer = FILE_Load(APP_SourcePath + "womanhead.m15")
model.FromMemory(memoryBuffer)
even with a slightly more time in the later
also the triceratops.M15 loaded okay
there is an error msg when we load some m15 files such as the Cubes.m15 and aliens(1 to 3).m15 inside the thinbasic folder
"fatal error has occurred program will be aborted
the content is not valid m15 v1.0.0.7"
Petr Schreiber
27-03-2016, 21:48
Hi Primo,
thanks for testing. This message is correct at the time - I am currently supporting just 1.0.0.7, because it has normals present.
I will eventually add support for 1.0.0.6, once I invent some fast way to calculate normals from tB. Probably using Oxygen, will see :)
Petr
Petr Schreiber
23-04-2016, 08:50
I am reaching the state when I can code again, so I optimized the m15Model geometry implementation.
v0.1.1 provided performance approximately 5.5x worse than native tbgl_m15DrawModel
v0.1.2 now provides performance which is on par with native m15 implementation, usually giving a few frames extra of performance
* measurements performed with WomanHead.m15
Previously, womanhead was done in 450+ draw calls, now it is done in single.
How this is achieved? By normalizing the mesh to triangles.
Grab the latest pre-release here:
https://github.com/petrSchreiber/m15Model/releases
Petr
Hi all
Is there a possibility that M15 format can manage animations like .x or .b3d ?
It would be great
Petr Schreiber
26-08-2016, 00:01
Hi,
thank you for your interest! I don't see this happening in near time frame, but what do you think about MD2 format? (quake 2)
I did a module for thinBasic to load these and animate.
Petr
Michael Hartlef
26-08-2016, 08:38
There are X to md2 converter out there.
loading M15 models from memory is a fun thing, here is loading a textured box using :
Dim model(2) As m15Model
String memoryBuffer = FILE_Load(APP_SourcePath + "box.M15")
For i=1 To 2
model(i).FromMemory(memoryBuffer)
Next
still i don't know how to access one vertex and change its positions, colors, normals and UV values at run time
while the usual M15 have many functions such as TBGL_m15SetVertexXYZ and so on.
Uses "tbgl"
#INCLUDE "m15Model/m15Model.tbasicu" ' -- can be just m15Model.tbasicu, depends where your code is :]
Long i, wireframe
Single y, x, z
DWord hWnd = TBGL_CreateWindowEx("press 'W' for wire/solid Frame .... press ESC to quit", 800, 600, 32, 0)
TBGL_ShowWindow
Dim model(2) As m15Model
String memoryBuffer = FILE_Load(APP_SourcePath + "box.M15")
For i=1 To 2
model(i).FromMemory(memoryBuffer)
Next
TBGL_LoadTexture APP_SourcePath+"color.bmp", 1, %TBGL_TEX_MIPMAP ' Loads texture as #1, with high quality
TBGL_UseTexturing %TRUE ' I want to use textures
TBGL_BindTexture 1
TBGL_ResetKeyState
TBGL_UseLighting TRUE
TBGL_UseLightSource %GL_LIGHT0, 1
While TBGL_IsWindow(hWnd)
If TBGL_GetWindowKeyOnce( hWnd, %VK_W) Then
wireframe = Not wireframe
TBGL_PolygonLook IIf(wireframe, %GL_LINE, %GL_FILL)
End If
TBGL_ClearFrame
TBGL_Camera 0, 40, 60, 0, 0, 0
TBGL_Rotate GetTickCount/40 , 0, 1, 0
TBGL_Translate -10, 0, 0.7
model(1).render
TBGL_Translate 20, 0, 0.7
model(2).render
TBGL_DrawFrame
If TBGL_GetWindowKeyState( hWnd, %VK_ESCAPE) Then Exit While
Wend
TBGL_DestroyWindow
download : code+box model+texture+m15 units
Petr Schreiber
07-03-2017, 19:04
Hi Primo,
what a joy to see you using the header :) I will think about how I can add this direct manipulation to the unit, stay tuned!
Petr
Petr Schreiber
12-03-2017, 11:30
Primo,
I was thinking how to improve current approach, how to do batched changes more efficientely.
This is what I came up with, not yet implemented:
dim vertices as m15VertexEnumerator(model)
model.BeginWrite()
model.SetVertexPos(vertices.first, 1, 2, 3) ' -- Sets coordinates of 1, 2, 3 to the first vertex
model.SetVertexColor(vertices.first, 255, 255, 255) ' -- Sets white color to the first vertex
model.SetVertexColor(vertices.firstPolygon, 255, 255, 255) ' -- Sets white color to vertices of the first polygon
model.SetVertexColor(vertices.nthPolygon(2), 255, 255, 255) ' -- Sets white color to vertices of the second polygon
model.SetVertexColor(vertices.all, 255, 255, 255) ' -- Sets white color to all vertices
model.EndWrite()
I think it could result in more readable code, with less FOR/NEXTing.
Petr
Hi Petr
seems goods choices, i suggest also something like this:
model.SetVertexPos(vertices.nthVertex(37), 20, 50, -10)
will change the vertex number 37 coordinates to 20, 50, -10
if everything is okay, then i think adding it to the official thinbasic distribution will be great. like adding before the StringBuilder .
regards
edit: model.SetVertexPos(vertices.nthPolygon(6), 10,30, 10)
could it be possible !! in which the polygon coordinates is the coord of its center.
it is like : model.SetVertexColor(vertices.nthPolygon(2), 255, 255, 255)
edit2: i think model.SetVertexPos(vertices.nthPolygon(6), 10,30, 10) is not necessary, since it is a programmer task to get every polygon vertices and do what he wants.
Petr Schreiber
19-03-2017, 09:57
Thank you Primo,
I will have a look at it :)
Petr