GLXtractor is a GUI tool which can be used to capture the Geometry from PureBasic Ogre 3D running programs and rendered with opengl subsystem . it captured the vertex positions, faces, normals, UV and direct these data to wavefront OBJ file , it captures also the texture used whether it is standalone image file or generated from code.
it can also capture geometry from PB opengl programs
download it from
https://web.archive.org/web/20151126041 ... t/~alexan/
or
http://glxtractor.software.informer.com/
its latest version is
0.9.9.1 , in the second link they say "Version 1.0 is not available yet"
How to use:
1- compile the following code (
with opengl subsystem) to sphere.exe and save it to purebasic\compilers
2- run the GLXtractor program and accept the defaults. click on "Choose App" and choose the sphere.exe you have saved before.
3- click on
Ogle Plugin Tab and choose capture texture ... capture. this is to capture the UV and normals data
4- click Start Application
5- when the purebasic program launched use either the mouse or ALT-TAB to focus on the GLXtractor window , and press
ctrl-shift-f . you will notice the rendering stop for a second or more (may be 10 seconds for very big meshes.)
6- exit the purebasic program
7- look at
My Documents - Xtracted folder (or whatever you choose before running PB example exe)
you will find sphere.obj and a texture . note it will work for meshes have submeshes such as "AKM.mesh" in the folder Models inside purebasic example data. but will not work with animated meshes such as robot.mesh ...
Code: Select all
InitEngine3D()
InitSprite()
InitKeyboard()
Global CameraSpeed.f = 0.07
Define.f KeyX, KeyY
Quit.b = #False
OpenWindow(0, 0, 0, 800, 600, "simple scene ... , move the camera with arrow keys ... , Space: stop/start rotation ... W: wire/solid", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 800, 600)
Add3DArchive(".", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Models", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Scripts",#PB_3DArchive_FileSystem)
Parse3DScripts()
CreateMaterial(0, LoadTexture(0, "MRAMOR6X6.jpg"))
MaterialCullingMode(0, #PB_Material_NoCulling)
CreateSphere(0, 1, 32,32)
;LoadMesh(0, "AKM.mesh")
;LoadMesh(0,"tudorhouse.mesh")
SetMeshMaterial(0, MaterialID(0))
CreateEntity(0, MeshID(0), #PB_Material_None, 0, 0, 0)
MeshRad.f = MeshRadius(0)
ScaleEntity(0, 1.244/MeshRad, 1.24/MeshRad, 1.24/MeshRad)
CreateCamera(0, 0, 0, 100, 100)
MoveCamera(0, 0, 2, 5, #PB_Absolute)
CameraLookAt(0, 0,0,0)
CreateLight(0, RGB(200,150,100), 10, 2000, 300)
AmbientColor(RGB(90, 90, 60))
rot = 1
Repeat
Repeat
Select WindowEvent()
Case #PB_Event_None
Break
Case #PB_Event_CloseWindow
Break 2
EndSelect
ForEver
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_Left)
KeyX = -CameraSpeed
ElseIf KeyboardPushed(#PB_Key_Right)
KeyX = CameraSpeed
Else
KeyX = 0
EndIf
If KeyboardPushed(#PB_Key_Up)
KeyY = -CameraSpeed
ElseIf KeyboardPushed(#PB_Key_Down)
KeyY = CameraSpeed
Else
KeyY = 0
EndIf
If KeyboardReleased(#PB_Key_W)
wire ! 1
If wire
MaterialShadingMode(0, #PB_Material_Wireframe)
Else
MaterialShadingMode(0, #PB_Material_Solid)
EndIf
EndIf
If KeyboardReleased(#PB_Key_Space)
rot ! 1
EndIf
EndIf
MoveCamera (0, KeyX, 0, KeyY)
RotateEntity(0, 0,rot/2,0, #PB_Relative)
RenderWorld()
FlipBuffers()
ExamineKeyboard()
Until KeyboardPushed(#PB_Key_Escape)
try GLXtractor with the following PB opengl code, try to capture its graphics
Code: Select all
Structure Point3D
x.f
y.f
z.f
tu.f
tv.f
r.f
g.f
b.f
EndStructure
UseJPEGImageDecoder()
UseJPEGImageEncoder()
UsePNGImageDecoder()
Declare FillArray()
Global.f txu, txv
Define event, quit
#ImagePath = #PB_Compiler_Home + "examples/3d/Data/Textures/"
LoadImage(1, #ImagePath+"axes.png")
*Buffer = EncodeImage(1) ; default is: #PB_ImagePlugin_BMP : encode the image in BMP
Define TexID
ExamineDesktops()
OpenWindow(0, 0, 0, DesktopWidth(0), DesktopHeight(0), "... Up/Down: zoom in/out... 'W': wire frame... 'A'/'Z': change Camera view")
SetWindowColor(0, RGB(200,220,200))
OpenGLGadget(0, 10, 10, WindowWidth(0) , WindowHeight(0) , #PB_OpenGL_Keyboard)
;- Generate texture
glGenTextures_(1, @TexID)
glBindTexture_(#GL_TEXTURE_2D, TexID)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_LINEAR)
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MAG_FILTER, #GL_LINEAR)
glTexImage2D_(#GL_TEXTURE_2D, 0, 3, ImageWidth(1), ImageHeight(1), 0, #GL_BGR_EXT, #GL_UNSIGNED_BYTE, *Buffer+57)
FreeMemory(*Buffer)
glEnable_(#GL_TEXTURE_2D) ; Enable texture mapping
glBindTexture_(#GL_TEXTURE_2D, TexID)
glLoadIdentity_();
gluPerspective_(45.0, DesktopWidth(0)/DesktopHeight(0), 1.0, 60.0)
glTranslatef_(0, 0, -5)
glEnable_(#GL_DEPTH_TEST)
Global NbX = 100
Global NbZ = 100
Global Dim Point3D.Point3D(0)
Global Dim MeshDataInd.PB_MeshFace(0)
Global indexsize ;= ArraySize(MeshDataInd()) + 1
;Debug indexsize
FillArray()
;Debug VertexIndex
;=================================================================================
rot.f = 1
;glPointSize_( 3 )
;glTranslatef_(0.0, 0.0, -30)
SetActiveGadget(0) ; make the openGLgadget active
glPushMatrix_(); to store the current state
glMatrixMode_(#GL_PROJECTION)
glLoadIdentity_();
gluPerspective_(45.0, WindowWidth(0)/WindowHeight(0), 1.0, 800.0)
glMatrixMode_(#GL_MODELVIEW)
glTranslatef_(0, 0, -1)
glShadeModel_(#GL_SMOOTH)
glEnable_(#GL_DEPTH_TEST)
glViewport_(0, 0, WindowWidth(0), WindowHeight(0))
gluLookAt_( 0, 1, 1, ; the camera looking from position 0,0.3,0.5 to 0,0,0 from above
0, 0, 0,
0, 1, 0 )
glPolygonMode_(#GL_FRONT_AND_BACK, #GL_LINE )
glPopMatrix_()
glPushMatrix_()
t=1: zz=30
;Debug indexsize
Repeat
Event = WindowEvent()
glViewport_(0, 0, WindowWidth(0), WindowHeight(0))
glClearColor_(0.9, 0.9, 0.9, 1)
;glClearColor_(0.3, 0.3, 0.3, 1)
glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
glEnableClientState_(#GL_VERTEX_ARRAY )
glEnableClientState_(#GL_COLOR_ARRAY)
glEnableClientState_(#GL_TEXTURE_COORD_ARRAY)
glRotatef_(rot/5, 0, 1, 0);
glVertexPointer_(3, #GL_FLOAT,SizeOf(Point3D),@Point3D(0)\x)
glColorPointer_(3, #GL_FLOAT, SizeOf(Point3D), @Point3D(0)\r)
glTexCoordPointer_(2, #GL_FLOAT, SizeOf(Point3D), @Point3D(0)\tu)
;glDrawElements_(#GL_LINES,indexsize,#GL_UNSIGNED_INT, @MeshDataInd(0)\Index)
;glDrawElements_(#GL_POINTS,indexsize,#GL_UNSIGNED_INT, @MeshDataInd(0)\Index)
;glDrawElements_(#GL_TRIANGLES,indexsize,#GL_UNSIGNED_INT, @MeshDataInd(0)\Index)
glDrawElements_(#GL_QUADS,indexsize,#GL_UNSIGNED_INT, @MeshDataInd(0)\Index)
glDisableClientState_(#GL_TEXTURE_COORD_ARRAY)
glDisableClientState_(#GL_COLOR_ARRAY)
glDisableClientState_(#GL_VERTEX_ARRAY);
If Event = #PB_Event_Gadget And EventGadget() = 0
If EventType() = #PB_EventType_KeyDown ; like KeyboardReleased
key = GetGadgetAttribute(0,#PB_OpenGL_Key )
If key = #PB_Shortcut_Escape ; Esc key to exit
quit = 1
ElseIf Key = #PB_Shortcut_W; display wire Frame or solid frame
If fill
glPolygonMode_(#GL_FRONT_AND_BACK, #GL_LINE)
fill ! 1
Else
glPolygonMode_(#GL_FRONT_AND_BACK, #GL_FILL )
fill ! 1
EndIf
ElseIf Key = #PB_Shortcut_Up
glScalef_(1.05,1.05,1.05)
ElseIf Key = #PB_Shortcut_Down
glScalef_(0.95,0.95,0.95)
ElseIf Key = #PB_Shortcut_A
glMatrixMode_(#GL_MODELVIEW);
glLoadIdentity_() ;
gluLookAt_(0, 3, 1, 0,0,0, 0,1,0 )
ElseIf Key = #PB_Shortcut_Z
glMatrixMode_(#GL_MODELVIEW);
glLoadIdentity_();
gluLookAt_(0, 1, 2, 0,0,0, 0,1,0 )
EndIf
EndIf
EndIf
SetGadgetAttribute(0, #PB_OpenGL_FlipBuffers, #True)
Delay(5)
Until Event = #PB_Event_CloseWindow Or quit = 1
glDeleteTextures_(1, @TexID)
Macro Vertex(u, v, txu, txv)
;this produce very beautiful shape
x.f = 0.5 * (1 - Cos(u)) * Sin(u) * Cos(v)
y.f = 0.5 * (1 - Cos(u)) * Sin(u) * Sin(v)
z.f = Cos(u)
;this produce a sphere shape
;x.f = 0.5 * Cos(u)* Sin(v)
;y.f = 0.5 * Sin(u)* Sin(v)
;z.f = 0.5 * Cos(v)
ReDim Point3D.Point3D(a)
Point3D(a)\x = x*1
Point3D(a)\y = y*1
Point3D(a)\z = z*1
Point3D(a)\tu = txu
Point3D(a)\tv = txv
Point3D(a)\r = 1.0 :Point3D(a)\g = 1.0 :Point3D(a)\b = 1
a+1
EndMacro
Procedure FillArray()
Protected.f u, v, Delta = 4*#PI/NbX ; change 4 to 2 to get more quads
Protected.f x, y, z
txu.f : txv.f
;Debug delta
u = 0
v = 0
While v <= 2 * #PI
While u <= 1 * #PI ; change 2 to 1 and will get half of the object
Vertex(u, v, txu, txv)
Vertex(u + Delta, v, txu+u/NbX*#PI, txv)
Vertex(u + Delta, v + Delta, txu+u/NbX*#PI, txv+v/NbX*#PI)
Vertex(u, v + Delta, txu, txv+v/NbX*#PI)
txu = txu + u/NbX*#PI ; for texturing
ReDim MeshDataInd.PB_MeshFace(VertexIndex+4)
MeshDataInd(VertexIndex)\Index = VertexIndex + 0
MeshDataInd(VertexIndex+1)\Index = VertexIndex + 1
MeshDataInd(VertexIndex+2)\Index = VertexIndex + 2
MeshDataInd(VertexIndex+3)\Index = VertexIndex + 3
VertexIndex + 4
u + Delta
Wend
txu = 0
txv = txv + v/NbX*1*#PI ; for texturing
u = 0
v + Delta
Wend
indexsize = ArraySize(MeshDataInd())
;Debug indexsize
;Debug VertexIndex
EndProcedure
Notes:
if our approach in constructing a manual mesh is like this:
CreateMesh(0, #PB_Mesh_TriangleList, #PB_Mesh_Static)
MeshVertexPosition(-1, 0, -1) ; vertex number 0
MeshVertexPosition(-1, 0, 1) ; vertex number 1
MeshVertexPosition( 1, 0, 1) ; vertex number 2
MeshVertexPosition( 1, 0, -1) ; vertex number 3
MeshFace(0,1,2)
MeshFace(2,3,0)
FinishMesh(#True)
note here in MeshFace(2,3,0) we have referred to vertex 2 and vertex 0 which are used before
but in GLXtractor capturing it is considered as a new points, and inside OBJ file we see:
#TRIANGLES
g 1
v -1.000000 0.000000 -1.000000
v -1.000000 0.000000 1.000000
v 1.000000 0.000000 1.000000
f 1 2 3
v 1.000000 0.000000 1.000000
v 1.000000 0.000000 -1.000000
v -1.000000 0.000000 -1.000000
f 4 5 6
these data if the camera in 0,0,0 and the entity in 0,0,0. the rendered data is different for other camera or entity positions or if the entity is rotated the data will be different but the shape stay as the original one.
so there are more vertices using the GLXtractor, and if we add the normals and the UV the OBJ will grow to gigantic sizes for big meshes. your only choice is to use the great
MeshLab tool to reduce the number of vertices again, in the above OBJ file the vertices will be again 4. using the
MeshLab Filters -> Cleaning and Repairing -> Merge Close Vertices
GLXtractor is a GUI for the OGLE the OpenGLExtractor tool, download Ogle bin and src from the Links provided here:
https://vrwiki.wikispaces.com/OGLE
Ogle is using glintercept tool: GLIntercept is a OpenGL function call interceptor for Windows that will intercept and log all OpenGL calls:
https://github.com/dtrebilco/glintercept
===========================================================
How to capture DX
3D Ripper 0.1 beta :
http://denull.ucoz.ru/load/1-1-0-40
i have tested it and it works, with PB Ogre 3D compiled as DirectX 9 subsytem (the default)
http://www.deep-shadows.com/hax/3DRipperDX.htm
i was not able to save as OBJ, but at least it produce a material file *.mtl which the other tools does not provide
your notes and experience is very welcome