SyntaxBomb - Indie Coders

Languages & Coding => BlitzMax / BlitzMax NG => MiniB3D => Topic started by: Krischan on January 04, 2019, 11:33:07 PM

Title: OpenB3D Questions
Post by: Krischan on January 04, 2019, 11:33:07 PM
Hi there. I've stopped working with Blitzmax and OpenB3D a few months ago due to a great showstopper problem with OpenB3D. Now I started to work on it again and came across new topics. I modified one of my techdemos so that you can play around with it. Maybe Mark or someone else can help here.

Background: OpenB3D should be mostly syntax compatible to MiniB3D. So I wrote the same demo once in the latest MiniB3D version and once parallel in the newest OpenB3D release from Github. Actually these source codes should be almost the same in syntax, but I noticed different results in some parts in OpenB3D and had to code some workarounds. I'm still using BlitzmaxOS, BLIDE and a BMK.exe from October 2017 (because of BLIDE). MinGW is gcc.exe (tdm64-1) 5.1.0 here.

The demo is visually quite simple, but has - as always - a complex sourcecode. I tried to stay below 1000 lines - I've attached both sources and the compiled executables here to this post. The demo shows an endless star field, which consists of 6.250.000 single stars (yes, correctly read). The star texture is generated procedurally by the code so no external media is needed. You can move around with WASD, QE and RF - hold TAB for Turbo. I've added three Debug stages which you can enable by changing the DEBUGLEVEL variable at the top of the source, together with other variables there. Level 1 disables Instancing and calculates a limited starfield using the TQuad rotations only for ALL stars, which is very slow. Level 2 disables textures and shows the 125 clusters colored, visualizing the teleport effect. And Level 3 makes it possible to leave the Cube to see the whole structure.

To make the demo still run with 60FPS I use Instancing with CopyEntity. First, a single star cluster with 50,000 stars is calculated, which is then duplicated in a 5x5x5 matrix in a cube. The camera only moves around in the innermost cube and is teleported to the opposite side of the inner cluster when reaching the edge. Since all clusters are visually identical, this teleporting is nearly not noticeable and the impression of an infinite star field is created.

Now to the problems / questions regarding OpenB3D: ???

1) Line 99: I must add "SetBlend ALPHABLEND" here or the initialization in OpenB3D looks very strange - MiniB3D doesn't have this problem. Generally the blending seems to work differently than in MiniB3D. Comment this line and see yourself :-)

2) Line 111 / 257 / TQuad Type: why are the vertex coordinate changes in CopyEntity not copied to all children meshes live like in MiniB3D? I manipulate the quads only in the source mesh, but the copies are ignored? Is it a bug? Or still not implemented? This is IMHO a very important feature of 3D graphics.

3) Line 102-185: why does the initialization take much longer with OpenB3D than with MiniB3D? MiniB3D: 1250ms vs. OpenB3D: 3000ms

4) Line 739: why do I must calculate the Cameraviewport Y value from the bottom left? In MiniB3D I use "CameraViewport tempcam, 0, 0, size, size" (top left) and in OpenB3D I must use "GraphicsHeight() - size" for the Y-coordinate to get the same result. I know that OpenGL calculates this way, but it is confusing compared to Blitz3D/MiniB3D

5) Line 205-206: in OpenB3D the mouse pointer moves slightly after initialization, this can only be fixed by NOT subtracting -1 in GraphicsHeight() - in MiniB3D it works (and would also be mathematically correct) - is it a rounding bug?

6) Line 279-285: I must use my own Begin2D/End2D functions here instead of the BeginMax2D/EndMax2D, or all vertex colors vanish and the universe is grey (replace my Commands with the default ones and see yourself). But why is this? It could be connected to the first problem noticed here.

7) Line 846: in MiniB3D I could access a Texture's pixmap directly by using the "glBindTexture (GL_TEXTURE_2D, tex.gltex[0])" command. How do I access the Pixmap of a Texture in OpenB3D? Is it only possible with the "BufferToTex tex, PixmapPixelPtr(pixmap, 0, 0)" command I've used instead?

8. @Mark: has OpenB3D development stopped four months ago or did you just not have time for it anymore? Am I the only one still using it? :o

Oh, and even if you can't help - have fun with the demo ;D It was a hard piece of work to get BOTH versions running.

MiniB3D Version:
Code: BlitzMax
  1. SuperStrict
  2.  
  3. Import sidesign.minib3d
  4.  
  5. Graphics3D DesktopWidth() / 1.5, DesktopHeight() / 1.5, 32, 2
  6.  
  7. ClearTextureFilters()
  8.  
  9. Global STARS:Int = 50000        ' number of stars per cluster part
  10. Global DIMENSION:Int = 2000     ' cluster dimension
  11. Global DISTRIBUTION:Float = 0.99' star distribution (0...1 = random...clustered)
  12. Global SPEED:Float = 1.0        ' overall move speed multiplicator
  13. Global BRAKE:Float = 0.95       ' brake multiplicator
  14. Global VSYNC:Int = False        ' Vertical Sync
  15. Global HOMING:Int = True        ' turn homing on/off
  16. Global COLORED:Int = False      ' colorize clusters
  17. Global TEXTURED:Int = True      ' use star texture
  18. Global Scale:Float = 0.5        ' star scale factor
  19. Global FADE:Int = True          ' fade distant clusters
  20. Global INSTANCING:Int = True    ' duplicate source mesh
  21.  
  22. Global DEBUGLEVEL:Int = 0       ' 0=off, 1=no instancing, 2=colored, 3=scene
  23.  
  24. If DEBUGLEVEL > 0 Then
  25.  
  26.         STARS = 1000
  27.         Scale = 1.6
  28.         DISTRIBUTION = 0.5
  29.         INSTANCING = False
  30.  
  31.         If DEBUGLEVEL > 1 Then
  32.  
  33.                 COLORED = True
  34.                 TEXTURED = False
  35.  
  36.                 If DEBUGLEVEL > 2 Then
  37.  
  38.                         HOMING = False
  39.                         FADE = False
  40.  
  41.                 EndIf
  42.  
  43.         EndIf
  44.  
  45. EndIf
  46.  
  47. ' ----------------------------------------------------------------------------
  48. ' Global variables
  49. ' ----------------------------------------------------------------------------
  50. Global localx:Float, localy:Float, localz:Float
  51. Global globalx:Float, globaly:Float, globalz:Float
  52. Global simx:Float, simy:Float, simz:Float
  53. Global xspeed:Float, yspeed:Float, zspeed:Float, rspeed:Float
  54. Global xadd:Float, yadd:Float, zadd:Float, radd:Float, tadd:Float
  55.  
  56. Global FPS:TFPS = New TFPS
  57. Global MS:Int = MilliSecs()
  58.  
  59. ' ----------------------------------------------------------------------------
  60. ' Init scene
  61. ' ----------------------------------------------------------------------------
  62. Global masterpivot:TPivot = CreatePivot()
  63.  
  64. Global cam:TCamera = CreateCamera()
  65. CameraRange cam, 1, DIMENSION * 8
  66. PositionEntity cam, 0, 0, 0
  67.  
  68. Local tex:TTexture = CreateSunTexture(512, 128, 128, 128)
  69. TextureBlend tex, 3
  70.  
  71. ' ----------------------------------------------------------------------------
  72. ' Duplicate Quad mesh in a 9x9x9 matrix
  73. ' ----------------------------------------------------------------------------
  74. Global meshlist:TList = CreateList()
  75. Global quadlist:TList = CreateList()
  76. Global quadsourcelist:TList = CreateList()
  77. Global lx:Float, ly:Float, lz:Float
  78.  
  79. Local entities:TEntity[9, 9, 9]
  80. Local meshes:TMesh[9, 9, 9]
  81.  
  82. Local mesh:TMesh
  83.  
  84. ' star cluster properties
  85. mesh = CreateMesh()
  86. EntityFX mesh, 1 + 2
  87. EntityBlend mesh, 3
  88. If TEXTURED Then EntityTexture mesh, tex
  89. HideEntity mesh
  90.  
  91. ' create blueprint star cluster
  92. For Local i:Int = 1 To STARS
  93.        
  94.         CreateStar(mesh)
  95.        
  96. Next
  97.  
  98. ' fix for OpenB3D to enable Texture Blending and Alpha?
  99. SetBlend ALPHABLEND
  100.  
  101. ' create 5x5x5 = 125 cluster
  102. For Local x:Int = 0 To 4 Step 1
  103.        
  104.         For Local y:Int = 0 To 4 Step 1
  105.  
  106.                 For Local z:Int = 0 To 4 Step 1
  107.  
  108.                         ' create a mesh and duplicate its properties = FAST
  109.                         If INSTANCING Then
  110.  
  111.                                 entities[x, y, z] = CopyEntity(mesh)
  112.  
  113.                                 PositionEntity entities[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION
  114.  
  115.                                 If COLORED Then
  116.  
  117.                                         EntityColor entities[x, y, z], Rand(64, 255), Rand(64, 255), Rand(64, 255)
  118.  
  119.                                 Else
  120.  
  121.                                         EntityColor entities[x, y, z], 255, 255, 255
  122.  
  123.                                 EndIf
  124.  
  125.                                 ListAddLast(meshlist, entities[x, y, z])
  126.  
  127.                         ' create many unique meshes without instancing = SLOW
  128.                         Else
  129.  
  130.                                 ' new mesh
  131.                                 meshes[x, y, z] = CreateMesh()
  132.                                 EntityFX meshes[x, y, z], 1
  133.                                 EntityBlend meshes[x, y, z], 3
  134.                                 If TEXTURED Then
  135.                                
  136.                                         EntityTexture meshes[x, y, z], tex
  137.                                         EntityFX meshes[x, y, z], 1 + 2
  138.                                        
  139.                                 EndIf
  140.        
  141.                                 ' duplicate blueprint cluster
  142.                                 For Local s:TQuad = EachIn quadsourcelist
  143.  
  144.                                         Local q:TQuad = New TQuad
  145.  
  146.                                         q.mesh = meshes[x, y, z]
  147.                                         q.x = s.x
  148.                                         q.y = s.y
  149.                                         q.z = s.z
  150.                                         q.scalex = s.scalex
  151.                                         q.scaley = s.scaley
  152.                                         q.RGB = s.RGB
  153.                                        
  154.                                         q.Add()
  155.                                         q.Update(cam)
  156.  
  157.                                         ListAddLast(quadlist, q)
  158.                                        
  159.                                 Next
  160.                                
  161.                                 PositionEntity meshes[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION
  162.  
  163.                                 If COLORED Then
  164.  
  165.                                         EntityColor meshes[x, y, z], Rand(128, 255), Rand(128, 255), Rand(128, 255)
  166.  
  167.                                 Else
  168.  
  169.                                         EntityColor meshes[x, y, z], 255, 255, 255
  170.  
  171.                                 EndIf
  172.  
  173.                                 ListAddLast(meshlist, meshes[x, y, z])
  174.  
  175.                         EndIf
  176.  
  177.                         RenderWorld
  178.                        
  179.                         Flip False
  180.  
  181.                 Next
  182.  
  183.         Next
  184.  
  185. Next
  186.  
  187. ' Fix to really center the mouse (otherwise it "jumps" a little bit initially)
  188. MoveMouse(GraphicsWidth() / 2, GraphicsHeight() / 2) ; Flip
  189. MouseX()
  190. MouseY()
  191. MouseXSpeed()
  192. MouseYSpeed()
  193. Flip
  194.  
  195. MS = MilliSecs() - MS
  196.  
  197. ' ----------------------------------------------------------------------------
  198. ' Main Loop
  199. ' ----------------------------------------------------------------------------
  200. While Not AppTerminate()
  201.  
  202.         If KeyHit(KEY_ESCAPE) Then End
  203.  
  204.         ' axis rotation
  205.         Local pitch:Float = Normalize(MouseY(), 0, GraphicsHeight() - 1, -2, 2)
  206.         Local yaw:Float = Normalize(MouseX(), 0, GraphicsWidth() - 1, 2, -2)
  207.         Local roll:Int = KeyDown(KEY_Q) - KeyDown(KEY_E)
  208.  
  209.         ' XYZ movement
  210.         Local xmove:Int = KeyDown(KEY_D) - KeyDown(KEY_A)
  211.         Local ymove:Int = KeyDown(KEY_R) - KeyDown(KEY_F)
  212.         Local zmove:Int = KeyDown(KEY_W) - KeyDown(KEY_S)
  213.         Local turbo:Int = KeyDown(KEY_TAB)
  214.  
  215.         If xmove = 0 And xadd <> 0 Then xadd = 0 Else If xmove And xadd = 0 Then xadd = 0.001
  216.         If ymove = 0 And yadd <> 0 Then yadd = 0 Else If ymove And yadd = 0 Then yadd = 0.001
  217.         If zmove = 0 And zadd <> 0 Then zadd = 0 Else If zmove And zadd = 0 Then zadd = 0.001
  218.         If roll = 0 And radd <> 0 Then radd = 0 Else If roll And radd = 0 Then radd = 0.01
  219.         If turbo = 0 And tadd <> 0 Then tadd:*0.9 Else If turbo And tadd = 0 Then tadd = 0.1
  220.  
  221.         If tadd < 0.01 Then tadd = 0.0
  222.  
  223.         If Abs(xmove) Then xadd:+0.01
  224.         If Abs(ymove) Then yadd:+0.01
  225.         If Abs(zmove) Then zadd:+0.01
  226.         If Abs(roll) Then radd:+0.025
  227.         If Abs(turbo) Then tadd:+0.05
  228.  
  229.         xadd:*1.025
  230.         yadd:*1.025
  231.         zadd:*1.025
  232.         radd:*1.025
  233.         tadd:*1.025
  234.  
  235.         If xadd > 2.0 Then xadd = 2.0
  236.         If yadd > 2.0 Then yadd = 2.0
  237.         If zadd > 2.0 Then zadd = 2.0
  238.         If radd > 1.5 Then radd = 1.5
  239.         If tadd > 25.0 Then tadd = 25.0
  240.  
  241.         ' calculate movespeed/rollspeed
  242.         If Abs(xmove) Then xspeed = xadd * SPEED * Sgn(xmove) * (1.0 + tadd)
  243.         If Abs(ymove) Then yspeed = yadd * SPEED * Sgn(ymove) * (1.0 + tadd)
  244.         If Abs(zmove) Then zspeed = zadd * SPEED * Sgn(zmove) * (1.0 + tadd)
  245.         If Abs(roll) Then rspeed = radd * Sgn(roll)
  246.        
  247.         ' perform rotation and motion
  248.         Turn(cam, pitch, yaw, rspeed)
  249.         MoveEntity cam, xspeed, yspeed, zspeed
  250.  
  251.         ' keep camera at home
  252.         If HOMING Then Home(cam, masterpivot, DIMENSION)
  253.  
  254.         ' only the master instance quads are facing to the camera
  255.         For Local q:TQuad = EachIn quadlist
  256.  
  257.                 q.Update(cam)
  258.  
  259.         Next
  260.  
  261.         ' fade mesh according to its distance
  262.         If FADE Then
  263.  
  264.                 For Local e:TEntity = EachIn meshlist
  265.  
  266.                         Local d:Float = EntityDistance(cam, e)
  267.                         Local a:Float = Normalize(d, DIMENSION * 1.0, DIMENSION * 2.0, 1.0, 0.0)
  268.                         EntityAlpha e, a
  269.  
  270.                 Next
  271.  
  272.         EndIf
  273.  
  274.         RenderWorld
  275.  
  276.         FPS.Update()
  277.  
  278.         ' fix for OpenB3D to have vertex colors enabled (otherwise its greyscale)
  279.         Begin2D()
  280.  
  281.                 DrawText("FPS [Init]..: " + FPS.FPS + " [" + MS + "ms]", 0, 0)
  282.                 DrawText("Star Cluster: " + STARS, 0, 15)
  283.                 DrawText("Stars Total.: " + (STARS * 5 * 5 * 5), 0, 30)
  284.  
  285.         End2D()
  286.  
  287.         Flip VSYNC
  288.  
  289.         ' decrease speed
  290.         xspeed:*BRAKE
  291.         yspeed:*BRAKE
  292.         zspeed:*BRAKE
  293.         rspeed:*BRAKE
  294.  
  295. Wend
  296.  
  297. End
  298.  
  299. ' creates a single star quad
  300. Function CreateStar(mesh:TMesh, surf:TSurface = Null, xoff:Float = 0.0:Float, yoff:Float = 0.0, zoff:Float = 0.0)
  301.  
  302.         Local q:TQuad = New TQuad
  303.  
  304.         q.mesh = mesh
  305.         q.surf = surf
  306.  
  307.         q.x = Rnd(-DIMENSION / 2, DIMENSION / 2) + xoff
  308.         q.y = Rnd(-DIMENSION / 2, DIMENSION / 2) + yoff
  309.         q.z = Rnd(-DIMENSION / 2, DIMENSION / 2) + zoff
  310.        
  311.         ' randomized clustering
  312.         If Rnd(1) > 1 - DISTRIBUTION Then
  313.  
  314.                 Local d:Float = Rnd(0.0001, 0.05)
  315.  
  316.                 q.x = lx + Rnd(-DIMENSION * d, DIMENSION * d) + xoff
  317.                 q.y = ly + Rnd(-DIMENSION * d, DIMENSION * d) + yoff
  318.                 q.z = lz + Rnd(-DIMENSION * d, DIMENSION * d) + zoff
  319.  
  320.         EndIf
  321.  
  322.         q.scalex = Rnd(1, Rnd(2, Rnd(4, Rnd(8, Rnd(16, 32))))) * Scale
  323.         q.scaley = q.scalex
  324.  
  325.         Local c:Float = (1.0 / q.scalex)
  326.         If Rnd(1) > 0.9 And c < 0.70 Then c = 1 - c             ' 10% Giants
  327.         If c >= 0.0 And c < 0.35 Then q.RGB = [255, 64, 0]      ' 35% Class M
  328.         If c >= 0.35 And c < 0.50 Then q.RGB = [255, 128, 32]   ' 15% Class K
  329.         If c >= 0.50 And c < 0.60 Then q.RGB = [255, 255, 64]   ' 10% Class G
  330.         If c >= 0.60 And c < 0.70 Then q.RGB = [255, 255, 128]  ' 10% Class F
  331.         If c >= 0.70 And c < 0.80 Then q.RGB = [255, 255, 255]  ' 10% Class A
  332.         If c >= 0.80 And c < 0.90 Then q.RGB = [0, 64, 255]     ' 10% Class B
  333.         If c >= 0.90 And c <= 1.00 Then q.RGB = [0, 0, 255]     ' 10% Class O
  334.  
  335.         q.Add()
  336.         q.Update(cam)
  337.  
  338.         ListAddLast(quadlist, q)
  339.         ListAddLast(quadsourcelist, q)
  340.        
  341.         lx = q.x
  342.         ly = q.y
  343.         lz = q.z
  344.  
  345. End Function
  346.  
  347. ' keeps the player in a predefined cubic area
  348. Function Home(target:TEntity, world:TEntity, homesize:Int = 100)
  349.  
  350.         ' store Local player Position
  351.         Local localx:Double = EntityX(target)
  352.         Local localy:Double = EntityY(target)
  353.         Local localz:Double = EntityZ(target)
  354.  
  355.         ' Check X axis
  356.         While localx > homesize
  357.  
  358.                 globalx:+homesize
  359.                 localx:-homesize
  360.                 PositionEntity target, localx, localy, localz
  361.                 MoveEntity world, -homesize, 0, 0
  362.                
  363.         Wend
  364.  
  365.         While localx < - homesize
  366.  
  367.                 globalx:-homesize
  368.                 localx:+homesize
  369.                 PositionEntity target, localx, localy, localz
  370.                 MoveEntity world, homesize, 0, 0
  371.  
  372.         Wend
  373.  
  374.         ' Check Y axis
  375.         While localy > homesize
  376.  
  377.                 globaly:+homesize
  378.                 localy:-homesize
  379.                 PositionEntity target, localx, localy, localz
  380.                 MoveEntity world, 0, -homesize, 0
  381.  
  382.         Wend
  383.  
  384.         While localy < - homesize
  385.  
  386.                 globaly:-homesize
  387.                 localy:+homesize
  388.                 PositionEntity target, localx, localy, localz
  389.                 MoveEntity world, 0, homesize, 0
  390.  
  391.         Wend
  392.  
  393.         ' Check Z axis
  394.         While localz > homesize
  395.  
  396.                 globalz:+homesize
  397.                 localz:-homesize
  398.                 PositionEntity target, localx, localy, localz
  399.                 MoveEntity world, 0, 0, -homesize
  400.  
  401.         Wend
  402.  
  403.         While localz < - homesize
  404.  
  405.                 globalz:-homesize
  406.                 localz:+homesize
  407.                 PositionEntity target, localx, localy, localz
  408.                 MoveEntity world, 0, 0, homesize
  409.  
  410.         Wend
  411.  
  412.         ' store simulated player Position
  413.         simx = localx + globalx
  414.         simy = localy + globaly
  415.         simz = localz + globalz
  416.  
  417. End Function
  418.  
  419. ' ----------------------------------------------------------------------------
  420. ' Normalizes a value to given range
  421. ' ----------------------------------------------------------------------------
  422. Function Normalize:Float(value:Float, vmin:Float, vmax:Float, nmin:Float, nmax:Float)
  423.  
  424.         Return((value - vmin) / (vmax - vmin)) * (nmax - nmin) + nmin
  425.  
  426. End Function
  427.  
  428. ' ----------------------------------------------------------------------------
  429. ' Turn Entity using Quaternions
  430. ' ----------------------------------------------------------------------------
  431. Function Turn(Ent:TEntity, X:Float = 0.0, Y:Float = 0.0, Z:Float = 0.0, Glob:Int = False)
  432.  
  433.         Local Pitch:Float = 0.0
  434.         Local Yaw:Float = 0.0
  435.         Local Roll:Float = 0.0
  436.  
  437.         Local Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)
  438.         Local Turn_Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)
  439.  
  440.         If Glob = False
  441.  
  442.                 Quat = EulerToQuat(EntityPitch(ent, True), EntityYaw(ent, True), EntityRoll(ent, True))
  443.                 Turn_Quat = EulerToQuat(X, Y, Z)
  444.                 Quat = MultiplyQuats(Quat, Turn_Quat)
  445.                 Quat = NormalizeQuat(Quat)
  446.                 QuatToEuler2(Quat.X, Quat.Y, Quat.Z, Quat.w, Pitch, Yaw, Roll)
  447.                 RotateEntity Ent, Pitch, Yaw, Roll
  448.  
  449.         Else
  450.  
  451.                 RotateEntity Ent, EntityPitch(Ent) + X, EntityYaw(Ent) + Y, EntityRoll(Ent) + Z
  452.  
  453.         EndIf
  454.  
  455. End Function
  456.  
  457. ' ----------------------------------------------------------------------------
  458. ' Euler to Quaternion
  459. ' ----------------------------------------------------------------------------
  460. Function EulerToQuat:TQuaternion(pitch:Float, yaw:Float, roll:Float)
  461.  
  462.         Local cr:Float = Cos(-roll / 2.0)
  463.         Local cp:Float = Cos(pitch / 2.0)
  464.         Local cy:Float = Cos(yaw / 2.0)
  465.         Local sr:Float = Sin(-roll / 2.0)
  466.         Local sp:Float = Sin(pitch / 2.0)
  467.         Local sy:Float = Sin(yaw / 2.0)
  468.         Local cpcy:Float = cp * cy
  469.         Local spsy:Float = sp * sy
  470.         Local spcy:Float = sp * cy
  471.         Local cpsy:Float = cp * sy
  472.  
  473.         Local q:TQuaternion = New TQuaternion
  474.  
  475.         q.w = cr * cpcy + sr * spsy
  476.         q.x = sr * cpcy - cr * spsy
  477.         q.y = cr * spcy + sr * cpsy
  478.         q.z = cr * cpsy - sr * spcy
  479.  
  480.         Return q
  481.  
  482. End Function
  483.  
  484. ' ----------------------------------------------------------------------------
  485. ' Quaternion to Euler
  486. ' ----------------------------------------------------------------------------
  487. Function QuatToEuler2(x:Float, y:Float, z:Float, w:Float, pitch:Float Var, yaw:Float Var, roll:Float Var)
  488.  
  489.         Local QuatToEulerAccuracy:Double = 1.0 / 2 ^ 31
  490.  
  491.         Local sint:Float = (2.0 * w * y) - (2.0 * x * z)
  492.         Local cost_temp:Float = 1.0 - (sint * sint)
  493.         Local cost:Float
  494.  
  495.         If Abs(cost_temp) > QuatToEulerAccuracy
  496.  
  497.                 cost = Sqr(cost_temp)
  498.  
  499.         Else
  500.  
  501.                 cost = 0.0
  502.  
  503.         EndIf
  504.  
  505.         Local sinv:Float, cosv:Float, sinf:Float, cosf:Float
  506.  
  507.         If Abs(cost) > QuatToEulerAccuracy
  508.  
  509.                 sinv = ((2.0 * y * z) + (2.0 * w * x)) / cost
  510.                 cosv = (1.0 - (2.0 * x * x) - (2.0 * y * y)) / cost
  511.                 sinf = ((2.0 * x * y) + (2.0 * w * z)) / cost
  512.                 cosf = (1.0 - (2.0 * y * y) - (2.0 * z * z)) / cost
  513.  
  514.         Else
  515.  
  516.                 sinv = (2.0 * w * x) - (2.0 * y * z)
  517.                 cosv = 1.0 - (2.0 * x * x) - (2.0 * z * z)
  518.                 sinf = 0.0
  519.                 cosf = 1.0
  520.  
  521.         EndIf
  522.  
  523.         pitch = ATan2(sint, cost)
  524.         yaw = ATan2(sinf, cosf)
  525.         roll = -ATan2(sinv, cosv)
  526.  
  527. End Function
  528.  
  529. ' ----------------------------------------------------------------------------
  530. ' Multiply Quaternion
  531. ' ----------------------------------------------------------------------------
  532. Function MultiplyQuats:TQuaternion(q1:TQuaternion, q2:TQuaternion)
  533.  
  534.         Local q:TQuaternion = New TQuaternion
  535.        
  536.         q.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z
  537.         q.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y
  538.         q.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z
  539.         q.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x
  540.  
  541.         Return q
  542.  
  543. End Function
  544.  
  545. ' ----------------------------------------------------------------------------
  546. ' Normalize Quaternion
  547. ' ----------------------------------------------------------------------------
  548. Function NormalizeQuat:TQuaternion(q:TQuaternion)
  549.  
  550.         Local uv:Float = Sqr(q.w * q.w + q.x * q.x + q.y * q.y + q.z * q.z)
  551.  
  552.         q.w = q.w / uv
  553.         q.x = q.x / uv
  554.         q.y = q.y / uv
  555.         q.z = q.z / uv
  556.  
  557.         Return q
  558.  
  559. End Function
  560.  
  561. ' ------------------------------------------------------------------------------------------------
  562. ' Quad Type
  563. ' ------------------------------------------------------------------------------------------------
  564. Type TQuad
  565.  
  566.         Field x:Float = 0.0                                                                             ' position x
  567.         Field y:Float = 0.0                                                                             ' position y
  568.         Field z:Float = 0.0                                                                             ' position z
  569.  
  570.         Field row:Int = 0                                                                               ' texture row
  571.         Field col:Int = 0                                                                               ' texture column
  572.  
  573.         Field scalex:Float = 1.0                                                                ' current size X
  574.         Field scaley:Float = 1.0                                                                ' current size Y
  575.  
  576.         Field RGB:Int[] = [255, 255, 255]                                               ' Vertex Color
  577.         Field Alpha:Float = 1.0                                                                 ' Vertex Alpha
  578.  
  579.         Field v:Int = 0                                                                                 ' vertex counter
  580.         Field mesh:TMesh = Null                                                                 ' mesh pointer
  581.         Field surf:TSurface = Null                                                              ' surface pointer
  582.  
  583.         ' --------------------------------------------------------------------------------------------
  584.         ' METHOD: Add new Quad
  585.         ' --------------------------------------------------------------------------------------------
  586.         Method Add(col:Int = 0, row:Int = 0)
  587.  
  588.                 Local s:Int = CountSurfaces(mesh)
  589.                 If s = 0 Then
  590.                
  591.                         surf = CreateSurface(mesh)
  592.                        
  593.                 Else
  594.                
  595.                         surf = GetSurface(mesh, s)
  596.                        
  597.                 EndIf
  598.                
  599.                 Local i:Int = CountVertices(surf)
  600.                 If i + 4 > 32768 Then
  601.  
  602.                         surf = CreateSurface(mesh)
  603.                         v = 0
  604.  
  605.                 EndIf
  606.  
  607.                 ' add Vertices
  608.                 Local V0:Int = AddVertex(surf, 0, 0, 0, 1, 0)
  609.                 Local V1:Int = AddVertex(surf, 0, 0, 0, 1, 1)
  610.                 Local V2:Int = AddVertex(surf, 0, 0, 0, 0, 1)
  611.                 Local V3:Int = AddVertex(surf, 0, 0, 0, 0, 0)
  612.  
  613.                 ' color vertices
  614.                 VertexColor surf, V0, RGB[0], RGB[1], RGB[2], Alpha
  615.                 VertexColor surf, V1, RGB[0], RGB[1], RGB[2], Alpha
  616.                 VertexColor surf, V2, RGB[0], RGB[1], RGB[2], Alpha
  617.                 VertexColor surf, V3, RGB[0], RGB[1], RGB[2], Alpha
  618.  
  619.                 ' connect triangles
  620.                 AddTriangle surf, V0, V1, V2
  621.                 AddTriangle surf, V0, V2, V3
  622.  
  623.                 VertexTexCoords surf, V0, col + 1, row
  624.                 VertexTexCoords surf, V1, col + 1, row + 1
  625.                 VertexTexCoords surf, V2, col, row + 1
  626.                 VertexTexCoords surf, V3, col, row
  627.  
  628.                 ' increase vertex counter
  629.                 If v >= 4 Then v = V0 + 4 Else v = V0
  630.  
  631.         End Method
  632.  
  633.         ' --------------------------------------------------------------------------------------------
  634.         ' METHOD: Update a Quad
  635.         ' --------------------------------------------------------------------------------------------
  636.         Method Update(target:TEntity)
  637.  
  638.                 TFormVector scalex, 0, 0, target, Null
  639.                 Local X1:Float = TFormedX()
  640.                 Local Y1:Float = TFormedY()
  641.                 Local Z1:Float = TFormedZ()
  642.  
  643.                 TFormVector 0, scaley, 0, target, Null
  644.                 Local X2:Float = TFormedX()
  645.                 Local Y2:Float = TFormedY()
  646.                 Local Z2:Float = TFormedZ()
  647.                
  648.                 ' set vertices
  649.                 VertexCoords surf, v + 0, x - x1 - x2, y - y1 - y2, z - z1 - z2
  650.                 VertexCoords surf, v + 1, x - x1 + x2, y - y1 + y2, z - z1 + z2
  651.                 VertexCoords surf, v + 2, x + x1 + x2, y + y1 + y2, z + z1 + z2
  652.                 VertexCoords surf, v + 3, x + x1 - x2, y + y1 - y2, z + z1 - z2
  653.  
  654.         End Method
  655.  
  656. End Type
  657.  
  658. ' ------------------------------------------------------------------------------------------------
  659. ' Exact FPS counter
  660. ' ------------------------------------------------------------------------------------------------
  661.  
  662. Type TFPS
  663.  
  664.         Global renders:Int = 0
  665.  
  666.         Field FPS:Int = 60                                                                              ' current FPS value
  667.         Field interval:Int = 999
  668.         Field averagefps:Int = 60                                                               ' average FPS value
  669.         Field framedrops:Int = 0                                                                ' dropped frames
  670.         Field oldlooptime:Int = 0
  671.         Field looptime:Int = 0
  672.         Field multi:Float                                                                               ' main loop multiplicator
  673.  
  674.         Field old:Int = MilliSecs()
  675.         Field totalfps:Int = 30
  676.         Field Ticks:Int
  677.  
  678.         ' --------------------------------------------------------------------------------------------
  679.         ' METHOD: Update FPS counter
  680.         ' --------------------------------------------------------------------------------------------
  681.         Method Update()
  682.  
  683.                 renders:+1
  684.  
  685.                 looptime = MilliSecs() - oldlooptime
  686.                 oldlooptime = MilliSecs()
  687.  
  688.                 If MilliSecs() - old >= interval Then
  689.  
  690.                         old = MilliSecs()
  691.  
  692.                         FPS = renders * (1000 / interval)
  693.                         renders = 0
  694.                         totalfps:+FPS
  695.                         Ticks:+1
  696.                        
  697.                         averagefps = totalfps / Ticks
  698.  
  699.                 EndIf
  700.  
  701.         End Method
  702.  
  703. End Type
  704.  
  705. ' Create a stunning star texture
  706. Function CreateSunTexture:TTexture(size:Int = 512, r:Int = 255, g:Int = 255, b:Int = 255)
  707.  
  708.         Local i:Float, j:Int, col:Int, rgb:Int
  709.         Local x:Int, y:Int
  710.        
  711.         Local w:Int = GraphicsWidth()
  712.  
  713.         Local tempcam:TCamera, tempsun:TPivot
  714.         Local pixmap:TPixmap = CreatePixmap(size, size, PF_RGBA8888)
  715.         Local tex:TTexture = CreateTexture(size, size, 1 + 8)
  716.  
  717.         For j = 0 To (size / 2) - 1
  718.  
  719.                 col = 255 - Normalize(j, 0, (size / 2.0) - 1, 0, 255)
  720.                 If col > 255 Then col = 255
  721.                 rgb = col * $1000000 + col * $10000 + col * $100 + col
  722.  
  723.                 For i = 0 To 360 Step 0.1
  724.  
  725.                         WritePixel(pixmap, (size / 2) + (Sin(i) * j), (size / 2) + (Cos(i) * j), rgb)
  726.  
  727.                 Next
  728.  
  729.         Next
  730.        
  731.         PixmapToTexture(pixmap, tex)
  732.         'SavePixmapPNG(pixmap, "proceduralstar1.png", 0)
  733.  
  734.         ' temp camera
  735.         tempcam = CreateCamera()
  736.         CameraRange tempcam, 1, w * 2
  737.  
  738.         ' no fix needed compared to OpenB3D
  739.         CameraViewport tempcam, 0, 0, size, size
  740.  
  741.         ' temp pivot
  742.         tempsun = CreatePivot()
  743.  
  744.         ' Create 4 body quads
  745.         CreateQuad(tempsun, size * 1.0, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
  746.         CreateQuad(tempsun, size * 1.5, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
  747.         CreateQuad(tempsun, size * 2.0, tex, 3, 1 + 8 + 16, r * 0.75, g * 0.75, b * 0.50, 0.75)
  748.         CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, r * 0.50, g * 0.50, b * 0.50, 0.50)
  749.  
  750.         ' create 4 ray quads
  751.         Local ray1:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
  752.         Local ray2:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
  753.         Local ray3:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)
  754.         Local ray4:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)
  755.  
  756.         ' rescale and rotate rays
  757.         ScaleEntity ray1, size * 2, size / 32, size
  758.         ScaleEntity ray2, size / 32, size * 2, size
  759.         ScaleEntity ray3, size, size / 32, size
  760.         ScaleEntity ray4, size, size / 32, size
  761.         RotateEntity ray3, 0, 0, 45
  762.         RotateEntity ray4, 0, 0, 135
  763.        
  764.         PositionEntity tempsun, 0, 0, w
  765.  
  766.         ' render star
  767.         RenderWorld
  768.         RenderWorld
  769.  
  770.         ' grab image
  771.         pixmap = GrabPixmap(0, 0, size, size)
  772.         For x = 0 To size - 1
  773.  
  774.                 For y = 0 To size - 1
  775.  
  776.                         rgb = ReadPixel(pixmap, x, y)
  777.  
  778.                         r = (rgb & $ff0000) / $10000
  779.                         g = (rgb & $ff00) / $100
  780.                         b = (rgb & $ff)
  781.  
  782.                         ' rgb
  783.                         rgb = (r + g + b) / 3 * $1000000 + r * $10000 + g * $100 + b
  784.  
  785.                         WritePixel(pixmap, x, y, rgb)
  786.  
  787.                 Next
  788.  
  789.         Next
  790.        
  791.         PixmapToTexture(pixmap, tex)
  792.         'SavePixmapPNG(pixmap, "proceduralstar2.png", 0)
  793.  
  794.         ' Delete pixmap, pivot and temp cam
  795.         pixmap = Null
  796.         FreeEntity tempsun
  797.         FreeEntity tempcam
  798.  
  799.         Return tex
  800.  
  801. End Function
  802.  
  803. ' custom quad creation
  804. Function CreateQuad:Tmesh(parent:TEntity, scale:Float = 1.0, tex:TTexture = Null, blend:Int = False, fx:Int = False, r:Int = 255, g:Int = 255, b:Int = 255, a:Float = 1.0)
  805.  
  806.         Local mesh:TMesh = CreateMesh()
  807.         Local surf:TSurface = CreateSurface(mesh)
  808.         Local v0:Int, v1:Int, v2:Int, v3:Int
  809.  
  810.         v0 = AddVertex(surf, 1, 1, 0, 0, 0)
  811.         v1 = AddVertex(surf, -1, 1, 0, 1, 0)
  812.         v2 = AddVertex(surf, -1, -1, 0, 1, 1)
  813.         v3 = AddVertex(surf, 1, -1, 0, 0, 1)
  814.  
  815.         AddTriangle surf, v0, v1, v2
  816.         AddTriangle surf, v0, v2, v3
  817.  
  818.         If parent Then EntityParent Mesh, parent
  819.         If fx Then EntityFX Mesh, fx
  820.         If tex Then EntityTexture Mesh, tex
  821.         If blend Then EntityBlend Mesh, blend
  822.  
  823.         EntityColor Mesh, r, g, b
  824.         EntityAlpha Mesh, a
  825.  
  826.         VertexColor surf, v0, r, g, b, a
  827.         VertexColor surf, v1, r, g, b, a
  828.         VertexColor surf, v2, r, g, b, a
  829.         VertexColor surf, v3, r, g, b, a
  830.  
  831.         ScaleEntity Mesh, Scale, Scale, Scale
  832.  
  833.         Return Mesh
  834.  
  835. End Function
  836.  
  837. ' creates a texture from a pixmap
  838. Function PixmapToTexture(pixmap:TPixmap, tex:TTexture)
  839.  
  840.         If PixmapFormat(pixmap) <> PF_RGBA8888 Then pixmap = ConvertPixmap(pixmap, PF_RGBA8888)
  841.  
  842.         ' OpenB3D only function to copy pixmap to texture
  843.         'BufferToTex tex, PixmapPixelPtr(pixmap, 0, 0)
  844.  
  845.         ' MiniB3D workaround to copy pixmap to texture
  846.         glBindTexture (GL_TEXTURE_2D, tex.gltex[0])
  847.         gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, pixmap.width, pixmap.Height, GL_RGBA, GL_UNSIGNED_BYTE, PixmapPixelPtr(pixmap, 0, 0))
  848.  
  849. End Function
  850.  
  851. ' --------------------------------------------------------------------------------
  852. ' Fixed BeginMax2D()
  853. ' --------------------------------------------------------------------------------
  854. Function Begin2D()
  855.  
  856.         Local x:Int, y:Int, w:Int, h:Int
  857.         GetViewport(x, y, w, h)
  858.  
  859.         'glPopClientAttrib()
  860.         'glPopAttrib()
  861.         glMatrixMode(GL_MODELVIEW)
  862.         glPopMatrix()
  863.         glMatrixMode(GL_PROJECTION)
  864.         glPopMatrix()
  865.         glMatrixMode(GL_TEXTURE)
  866.         glPopMatrix()
  867.         glMatrixMode(GL_COLOR)
  868.         glPopMatrix()
  869.        
  870.         glDisable(GL_LIGHTING)
  871.         glDisable(GL_DEPTH_TEST)
  872.         glDisable(GL_SCISSOR_TEST)
  873.         glDisable(GL_FOG)
  874.         glDisable(GL_CULL_FACE)
  875.  
  876.         glMatrixMode GL_TEXTURE
  877.         glLoadIdentity
  878.  
  879.         glMatrixMode GL_PROJECTION
  880.         glLoadIdentity
  881.         glOrtho 0, GraphicsWidth(), GraphicsHeight(), 0, -1, 1
  882.  
  883.         glMatrixMode GL_MODELVIEW
  884.         glLoadIdentity
  885.  
  886.         SetViewport x, y, w, h
  887.  
  888.         Local MaxTex:Int
  889.         glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(MaxTex))
  890.  
  891.         For Local Layer:Int = 0 Until MaxTex
  892.  
  893.                 glActiveTexture(GL_TEXTURE0+Layer)
  894.  
  895.                 glDisable(GL_TEXTURE_CUBE_MAP)
  896.                 glDisable(GL_TEXTURE_GEN_S)
  897.                 glDisable(GL_TEXTURE_GEN_T)
  898.                 glDisable(GL_TEXTURE_GEN_R)
  899.  
  900.                 glDisable(GL_TEXTURE_2D)
  901.  
  902.         Next
  903.  
  904.         glActiveTexture(GL_TEXTURE0)
  905.  
  906.         glViewport(0, 0, GraphicsWidth(), GraphicsHeight())
  907.         glScissor(0, 0, GraphicsWidth(), GraphicsHeight())
  908.  
  909.         glEnable GL_BLEND
  910.         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
  911.         glEnable(GL_TEXTURE_2D)
  912.  
  913. End Function
  914.  
  915. ' --------------------------------------------------------------------------------
  916. ' Fixed EndMax2D()
  917. ' --------------------------------------------------------------------------------
  918. Function End2D()
  919.  
  920.         ' save the Max2D settings for later
  921.         'glPushAttrib(GL_ALL_ATTRIB_BITS)
  922.         'glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
  923.         glMatrixMode(GL_MODELVIEW)
  924.         glPushMatrix()
  925.         glMatrixMode(GL_PROJECTION)
  926.         glPushMatrix()
  927.         glMatrixMode(GL_TEXTURE)
  928.         glPushMatrix()
  929.         glMatrixMode(GL_COLOR)
  930.         glPushMatrix()
  931.                
  932.         glDisable(GL_TEXTURE_CUBE_MAP)
  933.         glDisable(GL_TEXTURE_GEN_S)
  934.         glDisable(GL_TEXTURE_GEN_T)
  935.         glDisable(GL_TEXTURE_GEN_R)
  936.  
  937.         glDisable(GL_TEXTURE_2D)
  938.         glDisable(GL_BLEND)
  939.  
  940.         TGlobal.EnableStates()
  941.         'glDisable(GL_TEXTURE_2D)
  942.  
  943.         ' ' only needed for OpenB3D
  944.         'TGlobal.alpha_enable[0] = 0    ' alpha blending was disabled by Max2d (GL_BLEND)
  945.         'TGlobal.blend_mode[0] = 1      ' force alpha blending
  946.         'TGlobal.fx1[0] = 0                     ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
  947.         'TGlobal.fx2[0] = 1                     ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)
  948.  
  949.         glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)
  950.         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)
  951.  
  952.         glClearDepth(1.0)
  953.         glDepthFunc(GL_LEQUAL)
  954.         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
  955.  
  956.         glAlphaFunc(GL_GEQUAL, 0.5)
  957.  
  958.         ' ' only needed for OpenB3D
  959.         'For Local cam:TCamera=EachIn TCamera.cam_list
  960.                
  961.                  ' active camera - was if cam.hide[0]=0
  962.                  'If cam = TGlobal.camera_in_use
  963.                
  964.                         ' fog with Max2d fix
  965.                 '       cam.UpdateFog()
  966.                 '       Exit
  967.                        
  968.                 'EndIf
  969.                
  970.         'Next
  971.  
  972. End Function

OpenB3D Version:
Code: BlitzMax
  1. SuperStrict
  2.  
  3. Import openb3dmax.B3dglgraphics
  4.  
  5. Graphics3D DesktopWidth() / 1.5, DesktopHeight() / 1.5, 32, 2
  6.  
  7. ClearTextureFilters()
  8.  
  9. Global STARS:Int = 50000        ' number of stars per cluster part
  10. Global DIMENSION:Int = 2000     ' cluster dimension
  11. Global DISTRIBUTION:Float = 0.99' star distribution (0...1 = random...clustered)
  12. Global SPEED:Float = 1.0        ' overall move speed multiplicator
  13. Global BRAKE:Float = 0.95       ' brake multiplicator
  14. Global VSYNC:Int = False        ' Vertical Sync
  15. Global HOMING:Int = True        ' turn homing on/off
  16. Global COLORED:Int = False      ' colorize clusters
  17. Global TEXTURED:Int = True      ' use star texture
  18. Global Scale:Float = 0.5        ' star scale factor
  19. Global FADE:Int = True          ' fade distant clusters
  20. Global INSTANCING:Int = True    ' duplicate source mesh
  21.  
  22. Global DEBUGLEVEL:Int = 0       ' 0=off, 1=no instancing, 2=colored, 3=scene
  23.  
  24. If DEBUGLEVEL > 0 Then
  25.  
  26.         STARS = 1000
  27.         Scale = 1.6
  28.         DISTRIBUTION = 0.5
  29.         INSTANCING = False
  30.  
  31.         If DEBUGLEVEL > 1 Then
  32.  
  33.                 COLORED = True
  34.                 TEXTURED = False
  35.  
  36.                 If DEBUGLEVEL > 2 Then
  37.  
  38.                         HOMING = False
  39.                         FADE = False
  40.  
  41.                 EndIf
  42.  
  43.         EndIf
  44.  
  45. EndIf
  46.  
  47. ' ----------------------------------------------------------------------------
  48. ' Global variables
  49. ' ----------------------------------------------------------------------------
  50. Global localx:Float, localy:Float, localz:Float
  51. Global globalx:Float, globaly:Float, globalz:Float
  52. Global simx:Float, simy:Float, simz:Float
  53. Global xspeed:Float, yspeed:Float, zspeed:Float, rspeed:Float
  54. Global xadd:Float, yadd:Float, zadd:Float, radd:Float, tadd:Float
  55.  
  56. Global FPS:TFPS = New TFPS
  57. Global MS:Int = MilliSecs()
  58.  
  59. ' ----------------------------------------------------------------------------
  60. ' Init scene
  61. ' ----------------------------------------------------------------------------
  62. Global masterpivot:TPivot = CreatePivot()
  63.  
  64. Global cam:TCamera = CreateCamera()
  65. CameraRange cam, 1, DIMENSION * 8
  66. PositionEntity cam, 0, 0, 0
  67.  
  68. Local tex:TTexture = CreateSunTexture(512, 128, 128, 128)
  69. TextureBlend tex, 3
  70.  
  71. ' ----------------------------------------------------------------------------
  72. ' Duplicate Quad mesh in a 9x9x9 matrix
  73. ' ----------------------------------------------------------------------------
  74. Global meshlist:TList = CreateList()
  75. Global quadlist:TList = CreateList()
  76. Global quadsourcelist:TList = CreateList()
  77. Global lx:Float, ly:Float, lz:Float
  78.  
  79. Local entities:TEntity[9, 9, 9]
  80. Local meshes:TMesh[9, 9, 9]
  81.  
  82. Local mesh:TMesh
  83.  
  84. ' star cluster properties
  85. mesh = CreateMesh()
  86. EntityFX mesh, 1 + 2
  87. EntityBlend mesh, 3
  88. If TEXTURED Then EntityTexture mesh, tex
  89. HideEntity mesh
  90.  
  91. ' create blueprint star cluster
  92. For Local i:Int = 1 To STARS
  93.        
  94.         CreateStar(mesh)
  95.                
  96. Next
  97.  
  98. ' fix for OpenB3D to enable Texture Blending and Alpha?
  99. SetBlend ALPHABLEND
  100.  
  101. ' create 5x5x5 = 125 cluster
  102. For Local x:Int = 0 To 4 Step 1
  103.                
  104.         For Local y:Int = 0 To 4 Step 1
  105.  
  106.                 For Local z:Int = 0 To 4 Step 1
  107.  
  108.                         ' create a mesh and duplicate its properties = FAST
  109.                         If INSTANCING Then
  110.  
  111.                                 entities[x, y, z] = CopyEntity(mesh)
  112.  
  113.                                 PositionEntity entities[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION
  114.  
  115.                                 If COLORED Then
  116.  
  117.                                         EntityColor entities[x, y, z], Rand(64, 255), Rand(64, 255), Rand(64, 255)
  118.  
  119.                                 Else
  120.  
  121.                                         EntityColor entities[x, y, z], 255, 255, 255
  122.  
  123.                                 EndIf
  124.  
  125.                                 ListAddLast(meshlist, entities[x, y, z])
  126.  
  127.                         ' create many unique meshes without instancing = SLOW
  128.                         Else
  129.  
  130.                                 ' new mesh
  131.                                 meshes[x, y, z] = CreateMesh()
  132.                                 EntityFX meshes[x, y, z], 1
  133.                                 EntityBlend meshes[x, y, z], 3
  134.                                 If TEXTURED Then
  135.                                
  136.                                         EntityTexture meshes[x, y, z], tex
  137.                                         EntityFX meshes[x, y, z], 1 + 2
  138.                                        
  139.                                 EndIf
  140.        
  141.                                 ' duplicate blueprint cluster
  142.                                 For Local s:TQuad = EachIn quadsourcelist
  143.  
  144.                                         Local q:TQuad = New TQuad
  145.  
  146.                                         q.mesh = meshes[x, y, z]
  147.                                         q.x = s.x
  148.                                         q.y = s.y
  149.                                         q.z = s.z
  150.                                         q.scalex = s.scalex
  151.                                         q.scaley = s.scaley
  152.                                         q.RGB = s.RGB
  153.  
  154.                                         q.Add()
  155.                                         q.Update(cam)
  156.  
  157.                                         ListAddLast(quadlist, q)
  158.                                        
  159.                                 Next
  160.                                
  161.                                 PositionEntity meshes[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION
  162.  
  163.                                 If COLORED Then
  164.  
  165.                                         EntityColor meshes[x, y, z], Rand(128, 255), Rand(128, 255), Rand(128, 255)
  166.  
  167.                                 Else
  168.  
  169.                                         EntityColor meshes[x, y, z], 255, 255, 255
  170.  
  171.                                 EndIf
  172.  
  173.                                 ListAddLast(meshlist, meshes[x, y, z])
  174.  
  175.                         EndIf
  176.  
  177.                         RenderWorld
  178.  
  179.                         Flip False
  180.  
  181.                 Next
  182.  
  183.         Next
  184.  
  185. Next
  186.  
  187. ' Fix to really center the mouse (otherwise it "jumps" a little bit initially)
  188. MoveMouse(GraphicsWidth() / 2, GraphicsHeight() / 2) ; Flip
  189. MouseX()
  190. MouseY()
  191. MouseXSpeed()
  192. MouseYSpeed()
  193. Flip
  194.  
  195. MS = MilliSecs() - MS
  196.  
  197. ' ----------------------------------------------------------------------------
  198. ' Main Loop
  199. ' ----------------------------------------------------------------------------
  200. While Not AppTerminate()
  201.  
  202.         If KeyHit(KEY_ESCAPE) Then End
  203.  
  204.         ' axis rotation
  205.         Local pitch:Float = Normalize(MouseY(), 0, GraphicsHeight() - 1, -2, 2)
  206.         Local yaw:Float = Normalize(MouseX(), 0, GraphicsWidth() - 1, 2, -2)
  207.         Local roll:Int = KeyDown(KEY_Q) - KeyDown(KEY_E)
  208.  
  209.         ' XYZ movement
  210.         Local xmove:Int = KeyDown(KEY_D) - KeyDown(KEY_A)
  211.         Local ymove:Int = KeyDown(KEY_R) - KeyDown(KEY_F)
  212.         Local zmove:Int = KeyDown(KEY_W) - KeyDown(KEY_S)
  213.         Local turbo:Int = KeyDown(KEY_TAB)
  214.  
  215.         If xmove = 0 And xadd <> 0 Then xadd = 0 Else If xmove And xadd = 0 Then xadd = 0.001
  216.         If ymove = 0 And yadd <> 0 Then yadd = 0 Else If ymove And yadd = 0 Then yadd = 0.001
  217.         If zmove = 0 And zadd <> 0 Then zadd = 0 Else If zmove And zadd = 0 Then zadd = 0.001
  218.         If roll = 0 And radd <> 0 Then radd = 0 Else If roll And radd = 0 Then radd = 0.01
  219.         If turbo = 0 And tadd <> 0 Then tadd:*0.9 Else If turbo And tadd = 0 Then tadd = 0.1
  220.  
  221.         If tadd < 0.01 Then tadd = 0.0
  222.  
  223.         If Abs(xmove) Then xadd:+0.01
  224.         If Abs(ymove) Then yadd:+0.01
  225.         If Abs(zmove) Then zadd:+0.01
  226.         If Abs(roll) Then radd:+0.025
  227.         If Abs(turbo) Then tadd:+0.05
  228.  
  229.         xadd:*1.025
  230.         yadd:*1.025
  231.         zadd:*1.025
  232.         radd:*1.025
  233.         tadd:*1.025
  234.  
  235.         If xadd > 2.0 Then xadd = 2.0
  236.         If yadd > 2.0 Then yadd = 2.0
  237.         If zadd > 2.0 Then zadd = 2.0
  238.         If radd > 1.5 Then radd = 1.5
  239.         If tadd > 25.0 Then tadd = 25.0
  240.  
  241.         ' calculate movespeed/rollspeed
  242.         If Abs(xmove) Then xspeed = xadd * SPEED * Sgn(xmove) * (1.0 + tadd)
  243.         If Abs(ymove) Then yspeed = yadd * SPEED * Sgn(ymove) * (1.0 + tadd)
  244.         If Abs(zmove) Then zspeed = zadd * SPEED * Sgn(zmove) * (1.0 + tadd)
  245.         If Abs(roll) Then rspeed = radd * Sgn(roll)
  246.  
  247.         ' perform rotation and motion
  248.         Turn(cam, pitch, yaw, rspeed)
  249.         MoveEntity cam, xspeed, yspeed, zspeed
  250.  
  251.         ' keep camera at home
  252.         If HOMING Then Home(cam, masterpivot, DIMENSION)
  253.  
  254.         ' only the master instance quads are facing to the camera
  255.         For Local q:TQuad = EachIn quadlist
  256.  
  257.                 q.Update(cam)
  258.  
  259.         Next
  260.  
  261.         ' fade mesh according to its distance
  262.         If FADE Then
  263.  
  264.                 For Local e:TEntity = EachIn meshlist
  265.  
  266.                         Local d:Float = EntityDistance(cam, e)
  267.                         Local a:Float = Normalize(d, DIMENSION * 1.0, DIMENSION * 2.0, 1.0, 0.0)
  268.                         EntityAlpha e, a
  269.  
  270.                 Next
  271.  
  272.         EndIf
  273.  
  274.         RenderWorld
  275.  
  276.         FPS.Update()
  277.  
  278.         ' fix for OpenB3D to have vertex colors enabled (otherwise its greyscale)
  279.         Begin2D()
  280.  
  281.                 DrawText("FPS [Init]..: " + FPS.FPS + " [" + MS + "ms]", 0, 0)
  282.                 DrawText("Star Cluster: " + STARS, 0, 15)
  283.                 DrawText("Stars Total.: " + (STARS * 5 * 5 * 5), 0, 30)
  284.  
  285.         End2D()
  286.        
  287.         Flip VSYNC
  288.  
  289.         ' decrease speed
  290.         xspeed:*BRAKE
  291.         yspeed:*BRAKE
  292.         zspeed:*BRAKE
  293.         rspeed:*BRAKE
  294.  
  295. Wend
  296.  
  297. End
  298.  
  299. ' creates a single star quad
  300. Function CreateStar(mesh:TMesh, surf:TSurface = Null, xoff:Float = 0.0:Float, yoff:Float = 0.0, zoff:Float = 0.0)
  301.  
  302.         Local q:TQuad = New TQuad
  303.  
  304.         q.mesh = mesh
  305.         q.surf = surf
  306.  
  307.         q.x = Rnd(-DIMENSION / 2, DIMENSION / 2) + xoff
  308.         q.y = Rnd(-DIMENSION / 2, DIMENSION / 2) + yoff
  309.         q.z = Rnd(-DIMENSION / 2, DIMENSION / 2) + zoff
  310.        
  311.         ' randomized clustering
  312.         If Rnd(1) > 1 - DISTRIBUTION Then
  313.  
  314.                 Local d:Float = Rnd(0.0001, 0.05)
  315.  
  316.                 q.x = lx + Rnd(-DIMENSION * d, DIMENSION * d) + xoff
  317.                 q.y = ly + Rnd(-DIMENSION * d, DIMENSION * d) + yoff
  318.                 q.z = lz + Rnd(-DIMENSION * d, DIMENSION * d) + zoff
  319.  
  320.         EndIf
  321.  
  322.         q.scalex = Rnd(1, Rnd(2, Rnd(4, Rnd(8, Rnd(16, 32))))) * Scale
  323.         q.scaley = q.scalex
  324.  
  325.         Local c:Float = (1.0 / q.scalex)
  326.         If Rnd(1) > 0.9 And c < 0.70 Then c = 1 - c             ' 10% Giants
  327.         If c >= 0.0 And c < 0.35 Then q.RGB = [255, 64, 0]      ' 35% Class M
  328.         If c >= 0.35 And c < 0.50 Then q.RGB = [255, 128, 32]   ' 15% Class K
  329.         If c >= 0.50 And c < 0.60 Then q.RGB = [255, 255, 64]   ' 10% Class G
  330.         If c >= 0.60 And c < 0.70 Then q.RGB = [255, 255, 128]  ' 10% Class F
  331.         If c >= 0.70 And c < 0.80 Then q.RGB = [255, 255, 255]  ' 10% Class A
  332.         If c >= 0.80 And c < 0.90 Then q.RGB = [0, 64, 255]     ' 10% Class B
  333.         If c >= 0.90 And c <= 1.00 Then q.RGB = [0, 0, 255]     ' 10% Class O
  334.  
  335.         q.Add()
  336.         q.Update(cam)
  337.  
  338.         ListAddLast(quadlist, q)
  339.         ListAddLast(quadsourcelist, q)
  340.        
  341.         lx = q.x
  342.         ly = q.y
  343.         lz = q.z
  344.  
  345. End Function
  346.  
  347. ' keeps the player in a predefined cubic area
  348. Function Home(target:TEntity, world:TEntity, homesize:Int = 100)
  349.  
  350.         ' store Local player Position
  351.         Local localx:Double = EntityX(target)
  352.         Local localy:Double = EntityY(target)
  353.         Local localz:Double = EntityZ(target)
  354.  
  355.         ' Check X axis
  356.         While localx > homesize
  357.  
  358.                 globalx:+homesize
  359.                 localx:-homesize
  360.                 PositionEntity target, localx, localy, localz
  361.                 MoveEntity world, -homesize, 0, 0
  362.                
  363.         Wend
  364.  
  365.         While localx < - homesize
  366.  
  367.                 globalx:-homesize
  368.                 localx:+homesize
  369.                 PositionEntity target, localx, localy, localz
  370.                 MoveEntity world, homesize, 0, 0
  371.  
  372.         Wend
  373.  
  374.         ' Check Y axis
  375.         While localy > homesize
  376.  
  377.                 globaly:+homesize
  378.                 localy:-homesize
  379.                 PositionEntity target, localx, localy, localz
  380.                 MoveEntity world, 0, -homesize, 0
  381.  
  382.         Wend
  383.  
  384.         While localy < - homesize
  385.  
  386.                 globaly:-homesize
  387.                 localy:+homesize
  388.                 PositionEntity target, localx, localy, localz
  389.                 MoveEntity world, 0, homesize, 0
  390.  
  391.         Wend
  392.  
  393.         ' Check Z axis
  394.         While localz > homesize
  395.  
  396.                 globalz:+homesize
  397.                 localz:-homesize
  398.                 PositionEntity target, localx, localy, localz
  399.                 MoveEntity world, 0, 0, -homesize
  400.  
  401.         Wend
  402.  
  403.         While localz < - homesize
  404.  
  405.                 globalz:-homesize
  406.                 localz:+homesize
  407.                 PositionEntity target, localx, localy, localz
  408.                 MoveEntity world, 0, 0, homesize
  409.  
  410.         Wend
  411.  
  412.         ' store simulated player Position
  413.         simx = localx + globalx
  414.         simy = localy + globaly
  415.         simz = localz + globalz
  416.  
  417. End Function
  418.  
  419. ' ----------------------------------------------------------------------------
  420. ' Normalizes a value to given range
  421. ' ----------------------------------------------------------------------------
  422. Function Normalize:Float(value:Float, vmin:Float, vmax:Float, nmin:Float, nmax:Float)
  423.  
  424.         Return((value - vmin) / (vmax - vmin)) * (nmax - nmin) + nmin
  425.  
  426. End Function
  427.  
  428. ' ----------------------------------------------------------------------------
  429. ' Turn Entity using Quaternions
  430. ' ----------------------------------------------------------------------------
  431. Function Turn(Ent:TEntity, X:Float = 0.0, Y:Float = 0.0, Z:Float = 0.0, Glob:Int = False)
  432.  
  433.         Local Pitch:Float = 0.0
  434.         Local Yaw:Float = 0.0
  435.         Local Roll:Float = 0.0
  436.  
  437.         Local Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)
  438.         Local Turn_Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)
  439.  
  440.         If Glob = False
  441.  
  442.                 Quat = EulerToQuat(EntityPitch(Ent, True), EntityYaw(Ent, True), EntityRoll(Ent, True))
  443.                 Turn_Quat = EulerToQuat(X, Y, Z)
  444.                 Quat = MultiplyQuats(Quat, Turn_Quat)
  445.                 Quat = NormalizeQuat(Quat)
  446.                 QuatToEuler2(Quat.x[0], Quat.y[0], Quat.z[0], Quat.w[0], pitch, yaw, roll)
  447.                 RotateEntity Ent, pitch, yaw, roll
  448.  
  449.         Else
  450.  
  451.                 RotateEntity Ent, EntityPitch(Ent) + X, EntityYaw(Ent) + Y, EntityRoll(Ent) + Z
  452.  
  453.         EndIf
  454.  
  455. End Function
  456.  
  457. ' ----------------------------------------------------------------------------
  458. ' Euler to Quaternion
  459. ' ----------------------------------------------------------------------------
  460. Function EulerToQuat:TQuaternion(pitch:Float, yaw:Float, roll:Float)
  461.  
  462.         Local cr:Float = Cos(-roll / 2.0)
  463.         Local cp:Float = Cos(pitch / 2.0)
  464.         Local cy:Float = Cos(yaw / 2.0)
  465.         Local sr:Float = Sin(-roll / 2.0)
  466.         Local sp:Float = Sin(pitch / 2.0)
  467.         Local sy:Float = Sin(yaw / 2.0)
  468.         Local cpcy:Float = cp * cy
  469.         Local spsy:Float = sp * sy
  470.         Local spcy:Float = sp * cy
  471.         Local cpsy:Float = cp * sy
  472.  
  473.         Local q:TQuaternion = NewQuaternion()
  474.        
  475.         q.w[0] = cr * cpcy + sr * spsy
  476.         q.x[0] = sr * cpcy - cr * spsy
  477.         q.y[0] = cr * spcy + sr * cpsy
  478.         q.z[0] = cr * cpsy - sr * spcy
  479.  
  480.         Return q
  481.  
  482. End Function
  483.  
  484. ' ----------------------------------------------------------------------------
  485. ' Quaternion to Euler
  486. ' ----------------------------------------------------------------------------
  487. Function QuatToEuler2(x:Float, y:Float, z:Float, w:Float, pitch:Float Var, yaw:Float Var, roll:Float Var)
  488.  
  489.         Local QuatToEulerAccuracy:Double = 1.0 / 2 ^ 31
  490.  
  491.         Local sint:Float = (2.0 * w * y) - (2.0 * x * z)
  492.         Local cost_temp:Float = 1.0 - (sint * sint)
  493.         Local cost:Float
  494.  
  495.         If Abs(cost_temp) > QuatToEulerAccuracy
  496.  
  497.                 cost = Sqr(cost_temp)
  498.  
  499.         Else
  500.  
  501.                 cost = 0.0
  502.  
  503.         EndIf
  504.  
  505.         Local sinv:Float, cosv:Float, sinf:Float, cosf:Float
  506.  
  507.         If Abs(cost) > QuatToEulerAccuracy
  508.  
  509.                 sinv = ((2.0 * y * z) + (2.0 * w * x)) / cost
  510.                 cosv = (1.0 - (2.0 * x * x) - (2.0 * y * y)) / cost
  511.                 sinf = ((2.0 * x * y) + (2.0 * w * z)) / cost
  512.                 cosf = (1.0 - (2.0 * y * y) - (2.0 * z * z)) / cost
  513.  
  514.         Else
  515.  
  516.                 sinv = (2.0 * w * x) - (2.0 * y * z)
  517.                 cosv = 1.0 - (2.0 * x * x) - (2.0 * z * z)
  518.                 sinf = 0.0
  519.                 cosf = 1.0
  520.  
  521.         EndIf
  522.  
  523.         pitch = ATan2(sint, cost)
  524.         yaw = ATan2(sinf, cosf)
  525.         roll = -ATan2(sinv, cosv)
  526.  
  527. End Function
  528.  
  529. ' ----------------------------------------------------------------------------
  530. ' Multiply Quaternion
  531. ' ----------------------------------------------------------------------------
  532. Function MultiplyQuats:TQuaternion(q1:TQuaternion, q2:TQuaternion)
  533.  
  534.         Local q:TQuaternion = NewQuaternion()
  535.  
  536.         q.w[0] = q1.w[0] * q2.w[0] - q1.x[0] * q2.x[0] - q1.y[0] * q2.y[0] - q1.z[0] * q2.z[0]
  537.         q.x[0] = q1.w[0] * q2.x[0] + q1.x[0] * q2.w[0] + q1.y[0] * q2.z[0] - q1.z[0] * q2.y[0]
  538.         q.y[0] = q1.w[0] * q2.y[0] + q1.y[0] * q2.w[0] + q1.z[0] * q2.x[0] - q1.x[0] * q2.z[0]
  539.         q.z[0] = q1.w[0] * q2.z[0] + q1.z[0] * q2.w[0] + q1.x[0] * q2.y[0] - q1.y[0] * q2.x[0]
  540.  
  541.         Return q
  542.  
  543. End Function
  544.  
  545. ' ----------------------------------------------------------------------------
  546. ' Normalize Quaternion
  547. ' ----------------------------------------------------------------------------
  548. Function NormalizeQuat:TQuaternion(q:TQuaternion)
  549.  
  550.         Local uv:Float = Sqr(q.w[0] * q.w[0] + q.x[0] * q.x[0] + q.y[0] * q.y[0] + q.z[0] * q.z[0])
  551.  
  552.         q.w[0] = q.w[0] / uv
  553.         q.x[0] = q.x[0] / uv
  554.         q.y[0] = q.y[0] / uv
  555.         q.z[0] = q.z[0] / uv
  556.  
  557.         Return q
  558.  
  559. End Function
  560.  
  561. ' ------------------------------------------------------------------------------------------------
  562. ' Quad Type
  563. ' ------------------------------------------------------------------------------------------------
  564. Type TQuad
  565.  
  566.         Field x:Float = 0.0                                                                             ' position x
  567.         Field y:Float = 0.0                                                                             ' position y
  568.         Field z:Float = 0.0                                                                             ' position z
  569.  
  570.         Field row:Int = 0                                                                               ' texture row
  571.         Field col:Int = 0                                                                               ' texture column
  572.  
  573.         Field scalex:Float = 1.0                                                                ' current size X
  574.         Field scaley:Float = 1.0                                                                ' current size Y
  575.  
  576.         Field RGB:Int[] = [255, 255, 255]                                               ' Vertex Color
  577.         Field Alpha:Float = 1.0                                                                 ' Vertex Alpha
  578.  
  579.         Field v:Int = 0                                                                                 ' vertex counter
  580.         Field mesh:TMesh = Null                                                                 ' mesh pointer
  581.         Field surf:TSurface = Null                                                              ' surface pointer
  582.  
  583.         ' --------------------------------------------------------------------------------------------
  584.         ' METHOD: Add new Quad
  585.         ' --------------------------------------------------------------------------------------------
  586.         Method Add(col:Int = 0, row:Int = 0)
  587.  
  588.                 Local s:Int = CountSurfaces(mesh)
  589.                 If s = 0 Then
  590.                
  591.                         surf = CreateSurface(mesh)
  592.                        
  593.                 Else
  594.                
  595.                         surf = GetSurface(mesh, s)
  596.                        
  597.                 EndIf
  598.                
  599.                 Local i:Int = CountVertices(surf)
  600.                 If i + 4 > 32768 Then
  601.  
  602.                         surf = CreateSurface(mesh)
  603.                         v = 0
  604.  
  605.                 EndIf
  606.  
  607.                 ' add Vertices
  608.                 Local V0:Int = AddVertex(surf, 0, 0, 0, 1, 0)
  609.                 Local V1:Int = AddVertex(surf, 0, 0, 0, 1, 1)
  610.                 Local V2:Int = AddVertex(surf, 0, 0, 0, 0, 1)
  611.                 Local V3:Int = AddVertex(surf, 0, 0, 0, 0, 0)
  612.  
  613.                 ' color vertices
  614.                 VertexColor surf, V0, RGB[0], RGB[1], RGB[2], Alpha
  615.                 VertexColor surf, V1, RGB[0], RGB[1], RGB[2], Alpha
  616.                 VertexColor surf, V2, RGB[0], RGB[1], RGB[2], Alpha
  617.                 VertexColor surf, V3, RGB[0], RGB[1], RGB[2], Alpha
  618.  
  619.                 ' connect triangles
  620.                 AddTriangle surf, V0, V1, V2
  621.                 AddTriangle surf, V0, V2, V3
  622.  
  623.                 VertexTexCoords surf, V0, col + 1, row
  624.                 VertexTexCoords surf, V1, col + 1, row + 1
  625.                 VertexTexCoords surf, V2, col, row + 1
  626.                 VertexTexCoords surf, V3, col, row
  627.  
  628.                 ' increase vertex counter
  629.                 If v >= 4 Then v = V0 + 4 Else v = V0
  630.  
  631.         End Method
  632.  
  633.         ' --------------------------------------------------------------------------------------------
  634.         ' METHOD: Update a Quad
  635.         ' --------------------------------------------------------------------------------------------
  636.         Method Update(target:TEntity)
  637.  
  638.                 TFormVector scalex, 0, 0, target, Null
  639.                 Local X1:Float = TFormedX()
  640.                 Local Y1:Float = TFormedY()
  641.                 Local Z1:Float = TFormedZ()
  642.                
  643.                 TFormVector 0, scaley, 0, target, Null
  644.                 Local X2:Float = TFormedX()
  645.                 Local Y2:Float = TFormedY()
  646.                 Local Z2:Float = TFormedZ()
  647.  
  648.                 ' set vertices
  649.                 VertexCoords surf, v + 0, x - x1 - x2, y - y1 - y2, z - z1 - z2
  650.                 VertexCoords surf, v + 1, x - x1 + x2, y - y1 + y2, z - z1 + z2
  651.                 VertexCoords surf, v + 2, x + x1 + x2, y + y1 + y2, z + z1 + z2
  652.                 VertexCoords surf, v + 3, x + x1 - x2, y + y1 - y2, z + z1 - z2
  653.  
  654.         End Method
  655.  
  656. End Type
  657.  
  658. ' ------------------------------------------------------------------------------------------------
  659. ' Exact FPS counter
  660. ' ------------------------------------------------------------------------------------------------
  661.  
  662. Type TFPS
  663.  
  664.         Global renders:Int = 0
  665.  
  666.         Field FPS:Int = 60                                                                              ' current FPS value
  667.         Field interval:Int = 999
  668.         Field averagefps:Int = 60                                                               ' average FPS value
  669.         Field framedrops:Int = 0                                                                ' dropped frames
  670.         Field oldlooptime:Int = 0
  671.         Field looptime:Int = 0
  672.         Field multi:Float                                                                               ' main loop multiplicator
  673.  
  674.         Field old:Int = MilliSecs()
  675.         Field totalfps:Int = 30
  676.         Field Ticks:Int
  677.  
  678.         ' --------------------------------------------------------------------------------------------
  679.         ' METHOD: Update FPS counter
  680.         ' --------------------------------------------------------------------------------------------
  681.         Method Update()
  682.  
  683.                 renders:+1
  684.  
  685.                 looptime = MilliSecs() - oldlooptime
  686.                 oldlooptime = MilliSecs()
  687.  
  688.                 If MilliSecs() - old >= interval Then
  689.  
  690.                         old = MilliSecs()
  691.  
  692.                         FPS = renders * (1000 / interval)
  693.                         renders = 0
  694.                         totalfps:+FPS
  695.                         Ticks:+1
  696.                        
  697.                         averagefps = totalfps / Ticks
  698.  
  699.                 EndIf
  700.  
  701.         End Method
  702.  
  703. End Type
  704.  
  705. ' Create a stunning star texture
  706. Function CreateSunTexture:TTexture(size:Int = 512, r:Int = 255, g:Int = 255, b:Int = 255)
  707.  
  708.         Local i:Float, j:Int, col:Int, rgb:Int
  709.         Local x:Int, y:Int
  710.        
  711.         Local w:Int = GraphicsWidth()
  712.  
  713.         Local tempcam:TCamera, tempsun:TPivot
  714.         Local pixmap:TPixmap = CreatePixmap(size, size, PF_RGBA8888)
  715.         Local tex:TTexture = CreateTexture(size, size, 1 + 8)
  716.  
  717.         For j = 0 To (size / 2) - 1
  718.  
  719.                 col = 255 - Normalize(j, 0, (size / 2.0) - 1, 0, 255)
  720.                 If col > 255 Then col = 255
  721.                 rgb = col * $1000000 + col * $10000 + col * $100 + col
  722.  
  723.                 For i = 0 To 360 Step 0.1
  724.  
  725.                         WritePixel(pixmap, (size / 2) + (Sin(i) * j), (size / 2) + (Cos(i) * j), rgb)
  726.  
  727.                 Next
  728.  
  729.         Next
  730.        
  731.         PixmapToTexture(pixmap, tex)
  732.         'SavePixmapPNG(pixmap, "proceduralstar1.png", 0)
  733.  
  734.         ' temp camera
  735.         tempcam = CreateCamera()
  736.         CameraRange tempcam, 1, w * 2
  737.        
  738.         ' fix for OpenB3D to simulate MiniB3D's Cameraviewport handling
  739.         CameraViewport tempcam, 0, GraphicsHeight() - size, size, size
  740.  
  741.         ' temp pivot
  742.         tempsun = CreatePivot()
  743.  
  744.         ' Create 4 body quads
  745.         CreateQuad(tempsun, size * 1.0, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
  746.         CreateQuad(tempsun, size * 1.5, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
  747.         CreateQuad(tempsun, size * 2.0, tex, 3, 1 + 8 + 16, r * 0.75, g * 0.75, b * 0.50, 0.75)
  748.         CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, r * 0.50, g * 0.50, b * 0.50, 0.50)
  749.  
  750.         ' create 4 ray quads
  751.         Local ray1:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
  752.         Local ray2:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
  753.         Local ray3:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)
  754.         Local ray4:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)
  755.  
  756.         ' rescale and rotate rays
  757.         ScaleEntity ray1, size * 2, size / 32, size
  758.         ScaleEntity ray2, size / 32, size * 2, size
  759.         ScaleEntity ray3, size, size / 32, size
  760.         ScaleEntity ray4, size, size / 32, size
  761.         RotateEntity ray3, 0, 0, 45
  762.         RotateEntity ray4, 0, 0, 135
  763.        
  764.         PositionEntity tempsun, 0, 0, w
  765.  
  766.         ' render star
  767.         RenderWorld
  768.         RenderWorld
  769.  
  770.         ' grab image
  771.         pixmap = GrabPixmap(0, 0, size, size)
  772.         For x = 0 To size - 1
  773.  
  774.                 For y = 0 To size - 1
  775.  
  776.                         rgb = ReadPixel(pixmap, x, y)
  777.  
  778.                         r = (rgb & $ff0000) / $10000
  779.                         g = (rgb & $ff00) / $100
  780.                         b = (rgb & $ff)
  781.  
  782.                         ' rgb
  783.                         rgb = (r + g + b) / 3 * $1000000 + r * $10000 + g * $100 + b
  784.  
  785.                         WritePixel(pixmap, x, y, rgb)
  786.  
  787.                 Next
  788.  
  789.         Next
  790.  
  791.         PixmapToTexture(pixmap, tex)
  792.         'SavePixmapPNG(pixmap, "proceduralstar2.png", 0)
  793.  
  794.         ' Delete pixmap, pivot and temp cam
  795.         pixmap = Null
  796.         FreeEntity tempsun
  797.         FreeEntity tempcam
  798.  
  799.         Return tex
  800.  
  801. End Function
  802.  
  803. ' custom quad creation
  804. Function CreateQuad:Tmesh(parent:TEntity, scale:Float = 1.0, tex:TTexture = Null, blend:Int = False, fx:Int = False, r:Int = 255, g:Int = 255, b:Int = 255, a:Float = 1.0)
  805.  
  806.         Local mesh:TMesh = CreateMesh()
  807.         Local surf:TSurface = CreateSurface(mesh)
  808.         Local v0:Int, v1:Int, v2:Int, v3:Int
  809.  
  810.         v0 = AddVertex(surf, 1, 1, 0, 0, 0)
  811.         v1 = AddVertex(surf, -1, 1, 0, 1, 0)
  812.         v2 = AddVertex(surf, -1, -1, 0, 1, 1)
  813.         v3 = AddVertex(surf, 1, -1, 0, 0, 1)
  814.  
  815.         AddTriangle surf, v0, v1, v2
  816.         AddTriangle surf, v0, v2, v3
  817.  
  818.         If parent Then EntityParent Mesh, parent
  819.         If fx Then EntityFX Mesh, fx
  820.         If tex Then EntityTexture Mesh, tex
  821.         If blend Then EntityBlend Mesh, blend
  822.  
  823.         EntityColor Mesh, r, g, b
  824.         EntityAlpha Mesh, a
  825.  
  826.         VertexColor surf, v0, r, g, b, a
  827.         VertexColor surf, v1, r, g, b, a
  828.         VertexColor surf, v2, r, g, b, a
  829.         VertexColor surf, v3, r, g, b, a
  830.  
  831.         ScaleEntity Mesh, Scale, Scale, Scale
  832.  
  833.         Return Mesh
  834.  
  835. End Function
  836.  
  837. ' creates a texture from a pixmap
  838. Function PixmapToTexture(pixmap:TPixmap, tex:TTexture)
  839.  
  840.         If PixmapFormat(pixmap) <> PF_RGBA8888 Then pixmap = ConvertPixmap(pixmap, PF_RGBA8888)
  841.  
  842.         ' OpenB3D only function to copy pixmap to texture
  843.         BufferToTex tex, PixmapPixelPtr(pixmap, 0, 0)
  844.  
  845.         ' MiniB3D workaround to copy pixmap to texture
  846.         'glBindTexture (GL_TEXTURE_2D, tex.gltex[0])
  847.         'gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, PixmapPixelPtr(pixmap, 0, 0))
  848.  
  849. End Function
  850.  
  851. ' --------------------------------------------------------------------------------
  852. ' Fixed BeginMax2D()
  853. ' --------------------------------------------------------------------------------
  854. Function Begin2D()
  855.  
  856.         Local x:Int, y:Int, w:Int, h:Int
  857.         GetViewport(x, y, w, h)
  858.  
  859.         'glPopClientAttrib()
  860.         'glPopAttrib()
  861.         glMatrixMode(GL_MODELVIEW)
  862.         glPopMatrix()
  863.         glMatrixMode(GL_PROJECTION)
  864.         glPopMatrix()
  865.         glMatrixMode(GL_TEXTURE)
  866.         glPopMatrix()
  867.         glMatrixMode(GL_COLOR)
  868.         glPopMatrix()
  869.        
  870.         glDisable(GL_LIGHTING)
  871.         glDisable(GL_DEPTH_TEST)
  872.         glDisable(GL_SCISSOR_TEST)
  873.         glDisable(GL_FOG)
  874.         glDisable(GL_CULL_FACE)
  875.  
  876.         glMatrixMode GL_TEXTURE
  877.         glLoadIdentity
  878.  
  879.         glMatrixMode GL_PROJECTION
  880.         glLoadIdentity
  881.         glOrtho 0, GraphicsWidth(), GraphicsHeight(), 0, -1, 1
  882.  
  883.         glMatrixMode GL_MODELVIEW
  884.         glLoadIdentity
  885.  
  886.         SetViewport x, y, w, h
  887.  
  888.         Local MaxTex:Int
  889.         glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(MaxTex))
  890.  
  891.         For Local Layer:Int = 0 Until MaxTex
  892.  
  893.                 glActiveTexture(GL_TEXTURE0+Layer)
  894.  
  895.                 glDisable(GL_TEXTURE_CUBE_MAP)
  896.                 glDisable(GL_TEXTURE_GEN_S)
  897.                 glDisable(GL_TEXTURE_GEN_T)
  898.                 glDisable(GL_TEXTURE_GEN_R)
  899.  
  900.                 glDisable(GL_TEXTURE_2D)
  901.  
  902.         Next
  903.  
  904.         glActiveTexture(GL_TEXTURE0)
  905.  
  906.         glViewport(0, 0, GraphicsWidth(), GraphicsHeight())
  907.         glScissor(0, 0, GraphicsWidth(), GraphicsHeight())
  908.  
  909.         glEnable GL_BLEND
  910.         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
  911.         glEnable(GL_TEXTURE_2D)
  912.  
  913. End Function
  914.  
  915. ' --------------------------------------------------------------------------------
  916. ' Fixed EndMax2D()
  917. ' --------------------------------------------------------------------------------
  918. Function End2D()
  919.  
  920.         ' save the Max2D settings for later
  921.         'glPushAttrib(GL_ALL_ATTRIB_BITS)
  922.         'glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
  923.         glMatrixMode(GL_MODELVIEW)
  924.         glPushMatrix()
  925.         glMatrixMode(GL_PROJECTION)
  926.         glPushMatrix()
  927.         glMatrixMode(GL_TEXTURE)
  928.         glPushMatrix()
  929.         glMatrixMode(GL_COLOR)
  930.         glPushMatrix()
  931.                
  932.         glDisable(GL_TEXTURE_CUBE_MAP)
  933.         glDisable(GL_TEXTURE_GEN_S)
  934.         glDisable(GL_TEXTURE_GEN_T)
  935.         glDisable(GL_TEXTURE_GEN_R)
  936.  
  937.         glDisable(GL_TEXTURE_2D)
  938.         glDisable(GL_BLEND)
  939.  
  940.         TGlobal.EnableStates()
  941.         'glDisable(GL_TEXTURE_2D)
  942.  
  943.         ' only needed for OpenB3D
  944.         TGlobal.alpha_enable[0] = 0     ' alpha blending was disabled by Max2d (GL_BLEND)
  945.         TGlobal.blend_mode[0] = 1       ' force alpha blending
  946.         TGlobal.fx1[0] = 0                      ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
  947.         TGlobal.fx2[0] = 1                      ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)
  948.  
  949.         glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)
  950.         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)
  951.  
  952.         glClearDepth(1.0)
  953.         glDepthFunc(GL_LEQUAL)
  954.         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
  955.  
  956.         glAlphaFunc(GL_GEQUAL, 0.5)
  957.  
  958.         ' only needed for OpenB3D
  959.         For Local cam:TCamera=EachIn TCamera.cam_list
  960.                
  961.                  ' active camera - was if cam.hide[0]=0
  962.                  If cam = TGlobal.camera_in_use
  963.                
  964.                         ' fog with Max2d fix
  965.                         cam.UpdateFog()
  966.                         Exit
  967.                        
  968.                 EndIf
  969.                
  970.         Next
  971.  
  972. End Function
Title: Re: OpenB3D Questions
Post by: Flanker on January 05, 2019, 02:17:03 AM
Nice demo here, instancing is very powerful. You're not the only one using OpenB3D, I've totally abandon Blitz3D for OpenB3D because I prefer Blitzmax coding and because GLSL (or shaders in general) are amazing.

1) The only problem if I comment "SetBlend ALPHABLEND" is that there is no alpha when building the mesh at startup but after that it works well. However I also noticed a problem with alpha textures on my side a few weeks ago when I tried to code a 3D snow fall effect with OpenB3D. I had to use EntityAlpha to be able to activate texture alpha, wich is strange.

2) I remember using instancing with CopyEntity() in Blitz3D to make an "ocean" from one single animated mesh, and as you mentioned, in Blitz3D when you modify the source mesh, all instancies are also affected (useful to animate a lot of vertices). Maybe it's just not implemented here.

5) Funny to see that you also have a fix before the main loop to prevent the camera from spinning at the start. I think there is also a problem with MouseXSpeed()/MouseYSpeed() and MoveMouse(), or at least it works differently than Blitz3D.
Title: Re: OpenB3D Questions
Post by: Krischan on January 05, 2019, 11:21:54 AM
The mouse fix is needed both in MiniB3D and OpenB3D, but I don't know why this happens. And the two Flips before and after the Mouse Commands are important or it won't work. I had blending problems with OpenB3D since I first saw it - I created a few workarounds but this should be fixed in general IMHO. And yes, GLSL shaders are amazing with OpenB3D but a big problem with GLSL is that I hate to code without the possibility to debug values onscreen - you need tricks or hints to see what's wrong. But this is not a problem of OpenB3D ;D

Another problem I had already pointed out to mark is a strange bug in my game with reloaded Textures on B3D Models. In my game, when a new level is loaded, a BSP file is parsed and created as a mesh, gets textured and then I load a B3D model like a chest or a torch template and use CopyEntity to spread it across the level. After entering another level, all loaded assets are deleted and recreated. This worked until May 18 2017.

Now with the latest versions, either the models are completely untextured, I see only the normalmap or the normalmap+diffusemap in a random manner, but only on the B3D models - the level geometry is still fine. I've checked the OpenB3D source changes since the May 18 2017 version which is the last one where it worked (and it was the last one I could compile with my old BMK until he fixed this in the more current versions). I've sent my whole game project to Mark a few months ago and hope he will find some time to find the error as I failed with it.

But beside all these annoyances Blitzmax+OpenB3D is still a great combo and my first choice. On the other hand I spend more time to create workarounds in OpenB3D than creating progress in the game engine and game logic, which is not good.
Title: Re: OpenB3D Questions
Post by: markcwm on January 06, 2019, 01:48:05 AM
Hi Krischan,

I'll just reply to point 8 for now, yes I'll be continuing development on Openb3dmax in my spare time, in fact I have been working on it these last few days and have an update to the 1.25 source coming, but I've a few nasty bugs to fix first, shaders and b3d files are crashing!

Well I'll more fully explain why development stopped, about the start of September I got sciatica in my lower back lifting about 20kg, so yes about 4 months ago, this is a recurring injury and I just lifted something too heavy. So I was in too much pain to concentrate for coding, now I still have sciatica quite bad but I've found ibuprofen gel which makes the pain manageable so I can do a bit of coding now.

I sorry you've had so many problems with Openb3d, it's always been a WIP but it is starting to mature into something like Blitz3d. It has great potential as Angros has done an awesome job on the OpenGL, all it needs is a bit more work, well quite a bit really!

Also sorry I never got back to you on LOF, I ran the exe but it just crashed when I launched a level. I'll have another look at it soon.
Title: Re: OpenB3D Questions
Post by: Krischan on January 07, 2019, 08:06:57 PM
Mark, your health is more important than our projects - don't worry, take the time you need and get well soon! I'll continue developing the game with the old April 30 version which seemed stable enough for me. I know that OpenB3D is not finished but it already creates stunning results. I/we really appreciate your work and if you get LOF running you can see what can be done with it by a single enthusiast (but I don't think I can already tap the full potential yet and my shaders are a mess). For the LOF crash: I've re-uploaded my complete Blitzmax+LOF environment and sent you a PM with some instructions how to setup. I think it makes sense to have the same basis here to hunt the bugs.

Beside that I found an interesting issue today:

9) I tried MSI Afterburner on LOF today - works fine until I switch with "Escape" into the game menu (which uses 2D) - the MSI overlay turns into filled quads and stays filled until I end+restart the game (see attached screenshots). This happens too when I replace my custom Begin2D()+End2D() functions with BeginMax2D()+EndMax2D(). Can somebody confirm this with another demo or could it be a bug in my game?
Title: Re: OpenB3D Questions
Post by: markcwm on January 11, 2019, 03:44:20 AM
Hi Krischan,

thanks for your consideration of my health, I am really not too bad so work will continue, albeit at a slow pace.

I have a fix up for the B3D textures not reloaded bug in LOF, it appears to have been the texture ref not getting returned from LoadTexture in TB3D, it's strange though as the ref *should* be the same and not need to be returned, anyway I'm pretty sure that was the problem.

Note that the latest version is now updated to Openb3d 1.25 so it will need LinkShader(s) called after AttachVertShader and AttachFragShader. The most interesting new feature is the PostFX functions which I'll need to make an example for. Also the GLES2 stuff, so it might build for Android now but I haven't tested.

Also I noticed your LOF shaders are written for GL3 which is what was crashing the game, so I just edited a few things to get it to compile on GL2.1:
Code: [Select]
//#version 130
//precision mediump float;
replace "in" with "varying"
replace "out" with "varying"

@Point 7: yes gltex[] was removed by Angros but I can add that back in to the streamed texture functions.
Title: Re: OpenB3D Questions
Post by: Krischan on January 11, 2019, 10:02:59 AM
Hi Mark,

great that you found time to add these fixes. It compiles and runs here, I've changed my shaders and added the LinkShader to the AssembleMap() Method in TBSP.bmx.

But when I switch the level it crashes at the ParseTextures() method - it seems to load the first texture but the next one crashes (in Renderworld() - inside the texture load function are some calls to UpdateLoader() which updates the Loading Screen with the spinning compass which needs a render pass in the loop there). This worked before and happens before the shaders are re-applied again.

I've added the patched Source, just overwrite the Dev project I've sent you.
Title: Re: OpenB3D Questions
Post by: markcwm on January 11, 2019, 09:12:49 PM
Hi Krischan,

thanks, I can't reproduce this so I'm guessing it's a shader crash, you should try reverting to your original GLSL 130 syntax. I haven't tried your patch yet so I'll do that now.
Title: Re: OpenB3D Questions
Post by: Krischan on January 11, 2019, 10:55:42 PM
It didn't work with the original shader, too. It only "works" (=no crash) if I uncomment my ApplyShaderCache() Method - but then I don't have any level textures anymore. My current level loader is quite complex, but as far as I remember it works like that (it's all in the source but I try to describe it with my own words):

Global Shader Variables in the Type:

Code: BlitzMax
  1. Field VERTEXSHADER_SOURCE:String
  2. Field FRAGMENTSHADER_SOURCE:String
  3. Field MAINSHADER:TShader
  4. Field VERTEXSHADER_COMPILED:TShaderObject
  5. Field FRAGMENTSHADER_COMPILED:TShaderObject
  6. Field SHADERLIST:TList
  7. Field SHADERCACHED:TList

The BSP level geometry consists of several meshes and these can have different diffuse textures while the doors share the same texture but doors must be additional single meshes (not part of the level geometry mesh) to make alpha / Z-Index work on them (you can actually see through some of them). As I have many doors but only some level geometry meshes, I try to reuse the door shader using a cache to load the level faster. But I use only ONE shader source for both use cases (geometry and doors).

I first load the fragment+vertex shader source once (VERTEXSHADER_SOURCE+FRAGMENTSHADER_SOURCE), create a shader material (MAINSHADER), compile both sources once and attach the compiled shaders (VERTEXSHADER_COMPILED+FRAGMENTSHADER_COMPILED) to the MAINSHADER material. With your additions I then use the new LinkShader command on the MAINSHADER material? Is this correct?

Code: BlitzMax
  1. s = ReadFile(PATH_SHADER + filename + ".vert")
  2. VERTEXSHADER_SOURCE = ReadString(s, FileSize(PATH_SHADER + filename + ".vert"))
  3. s = ReadFile(PATH_SHADER + filename + ".vert")
  4. FRAGMENTSHADER_SOURCE = ReadString(s, FileSize(PATH_SHADER + filename + ".frag"))
  5. MAINSHADER = CreateShaderMaterial("")
  6. FRAGMENTSHADER_COMPILED = CreateFragShaderString(MAINSHADER, FRAGMENTSHADER_SOURCE)
  7. VERTEXSHADER_COMPILED = CreateVertShaderString(MAINSHADER, VERTEXSHADER_SOURCE)
  8. AttachFragShader(MAINSHADER, FRAGMENTSHADER_COMPILED)
  9. AttachVertShader(MAINSHADER, VERTEXSHADER_COMPILED)
  10. LinkShader(MAINSHADER)

The Shader cache works like this:
When a mesh gets assembled (geometry or door), on every new surface with different textures I create a new TShaderCache TMap Object and add all detail information about this surface to it (diffuse map, normal map, light map, surface id, mesh num and so on). I use a MD5 string of the diffuse filename plus the surface ID as a GUID key to distinguish between the same texture combinations and add new combinations to the SHADERLIST TList. This is because I don't want to create a new surface if it already exists. For example Walls should share the same shader while carpets or painting have their own shader. I think this is the best way to speed things up. And I've saved a lot of new surfaces with this algorithm.

After creating all meshes I use the ApplyShaderCache() Method. It iterates through all SHADERLIST objects and creates new shaders from the shader sources only for these surfaces. It adds the textures and variables to the shader and uses the ShadeSurface command to apply it to the cached surface. If it is a door, the MAINSHADER is applied instead.

I don't know why I don't compile this new created shader at this point (it is only created from the source) but I think I've had a big problem here I can't remember and needed to bypass it somehow (compiling here leads to a instant crash loading the initial level). I don't know if this is part of the problem:

Code: BlitzMax
  1. s.shader = CreateShader("", VERTEXSHADER_SOURCE, FRAGMENTSHADER_SOURCE)
  2. ShaderTexture(s.shader, s.dm, "diffuseMap", 0)
  3. ShaderTexture(s.shader, s.nm, "normalMap", 1)
  4. ShaderTexture(s.shader, s.lm, "lightMap", 2)
  5. ...
  6. ShadeSurface(s.surf, s.shader)

This new s.shader is then added to the SHADERCACHED TList for the next cache loop. The doors all use the precompiled global MAINSHADER instead of the newly created shaders. I don't know why but I had to create it this way but it really worked fast and flawless. When entering a new level, everything I created on the Load() Method is unloaded, cleared, nullified and destroyed. It is a large function but I think I didn't missed something and this worked before, too.

Currently I don't know what to change in my source to make it work again. So a very simple example would be nice: how to properly create, load, apply and unload/recreate a Vert+Frag Shader on a mesh with the same or a different texture without leaving shader, mesh or texture garbage behind before loading a new level - ideally with some kind of caching like I tried. A simple level loader/unloader with shaded meshes. I'm really confused how to use the shaders in such a complex but common scenario. But with such an example, I might be able to understand the problem better.
Title: Re: OpenB3D Questions
Post by: markcwm on January 12, 2019, 12:20:48 AM
Hi Krischan,

well it's probably a bug in the Openb3d 1.25 code as the usematrix example is crashing, so  somethings wrong somewhere and I haven't figured it out yet, however your patch works perfectly here in win32 GL2.1. I suggest you test this by reverting to before the 1.25 update which is 12 sep 18 (https://github.com/markcwm/openb3dmax.mod/tree/275310e439f275480a136581345d5d8af3000706).
Title: Re: OpenB3D Questions
Post by: markcwm on January 18, 2019, 03:50:11 AM
Hi Krischan,

here's an update on my progress, still lots to do...

I added the missing tex.gltex[0], Angros renamed it to frames so you can use that too, gltex just points to frames. Edit: actually only working with anim textures but fixed in latest commit.

Also added is tex.no_mipmaps[0] but it's calculated rather than counted at generation like Minib3d.

BeginMax2D now has a version parameter 0 for old one, 1 for your latest code, which I've credited you for in the source. So thanks. Your version definitely works better with 2d text so it should really be the default.

Other changes are error messages if mesh or texture urls are bad, this is essential functionality, of course Blitz3d does this.

And the 3DS loader is fixed (edit: well nearly) it's a port from Openb3d but with a few changes, texture v's are flipped so words read from left-right, mesh transforms are enabled with MeshLoader "trans" and there's a second 3DS loader from Warner which is improved and basically should now work the same as the default one, it's enabled by MeshLoader "3ds2".

Then there's MeshDebug 1 to enable extra mesh debug info (edit: changed to MeshLoader "debug").

And then LightMesh ported from Blitz3d. And a fix for FreeSurface crashing.
Title: Re: OpenB3D Questions
Post by: Krischan on January 18, 2019, 08:59:01 AM
Thanks for the update - it builds but I can't compile my game anymore:

C:/Apps/Coding/BlitzMax/mod/openb3dmax.mod/openb3dmax.mod/openb3dmax.release.win32.x86.a(openb3dmax.bmx.release.win32.x86.o):(code+0x1ca5b): undefined reference to `Log2_'
Build Error: Failed to link C:/LOF/Legend of Faerghail.exe

I compiled it like I did with all previous versions, cross-tested it with the 30 apr 18 version (everything is fine) and the 12 sep 18 version works, too (still with the texture/model bug).
bmk makemods -a -r openb3dmax
bmk makemods -a -d openb3dmax

By the way, does LOF work for you now? Another suggestion for future versions: sometimes OpenB3D shows error messages, sometimes they are commented in the CPP sources. For example in texture.cpp all errors are commented while in file.cpp there are some outputs.

It would be nice if this would be uniform across all sources and that you could switch it on/off with a global command, like let's say ShowDebugErrors() / HideDebugErrors(). But this is only a nice-to-have feature.
Title: Re: OpenB3D Questions
Post by: markcwm on January 19, 2019, 06:22:04 AM
Yes sorry, I forgot a file yesterday and didn't double-check.

The latest version replaces Log2 to Mipmaps. Also BeginMax2D now defaults to 1 which is your version. And another update to the 3DS loader, LoadMesh loads one mesh with many surfaces, LoadAnimMesh loads many meshes with one surface, CollapseAnimMesh was used before but wasn't working in bmx, it's a wierd function though so I'm not sure what it does. And shaders now debug errors when the filename is wrong.

Yes, LOF works with this latest commit so I'm not sure what's up but it may be a GL3 issue as I'm in GL2. You could try commenting out all ShadeSurface but I've just tested and that was working. Is it crashing exactly at the ShadeSurface function? It also might be the shader matrix code, so try running shader/bumpmap as it has some mat3 code.
Title: Re: OpenB3D Questions
Post by: Krischan on January 20, 2019, 11:53:05 AM
First - the model texture bug has vanished now - so the model textures are applied correct again after loading another level. Great.

But it still crashes after loading the next level. It only "works" when I comment the two ShadeSurface() commands in the ApplyShaderCache() Method in include\types\TBSP.bmx. The level geometry is untextured then, well at least I have some distance fog ;-) So Shadesurface crashes the texture loader in the second run. But why? I've tested it on an old nVidia GTX 780M with a very outdated driver (398.82) and a brandnew GTX 2080 with the newest driver (417.71) which still has the same problem. So is it a bug in LOF or in OpenB3D? I don't know.

And I think my custom Begin/End commands are not complete yet as I'm still having the MSI Afterburner OSD bug after entering the menu. The bug vanishes when I uncomment the glActiveTexture(GL_TEXTURE0) in BeginMax2D(), but then all menu textures vanish, too. Does anybody know why or how to fix it? And it is risky to use my own functions in OpenB3D as I really didn't knew what excactly to do there - it is the result of try and error only.

So it would make sense if someone who knows more about OpenGL than I do would take a look at it.

Code: BlitzMax
  1. Rem
  2. bbdoc: Blitz2D
  3. EndRem
  4. Type TBlitz2D
  5.  
  6.         Function BeginMax2D( version:Int=1 )
  7.        
  8.                 Select version
  9.                
  10.                 Case 0 ' Old begin function (by Oddball)
  11.                        
  12.                         glPopClientAttrib()
  13.                         glPopAttrib()
  14.                         glMatrixMode(GL_MODELVIEW)
  15.                         glPopMatrix()
  16.                         glMatrixMode(GL_PROJECTION)
  17.                         glPopMatrix()
  18.                         glMatrixMode(GL_TEXTURE)
  19.                         glPopMatrix()
  20.                         glMatrixMode(GL_COLOR)
  21.                         glPopMatrix()
  22.                        
  23.                 Case 1 ' New begin function, allows instant resolution switch (by Krischan)
  24.                        
  25.                         Local x:Int, y:Int, w:Int, h:Int
  26.                         GetViewport(x, y, w, h)
  27.                        
  28.                         'glPopClientAttrib()
  29.                         'glPopAttrib()
  30.                         glMatrixMode(GL_MODELVIEW)
  31.                         glPopMatrix()
  32.                         glMatrixMode(GL_PROJECTION)
  33.                         glPopMatrix()
  34.                         glMatrixMode(GL_TEXTURE)
  35.                         glPopMatrix()
  36.                         glMatrixMode(GL_COLOR)
  37.                         glPopMatrix()
  38.                          
  39.                         glDisable(GL_LIGHTING)
  40.                         glDisable(GL_DEPTH_TEST)
  41.                         glDisable(GL_SCISSOR_TEST)
  42.                         glDisable(GL_FOG)
  43.                         glDisable(GL_CULL_FACE)
  44.                        
  45.                         glMatrixMode GL_TEXTURE
  46.                         glLoadIdentity
  47.                        
  48.                         glMatrixMode GL_PROJECTION
  49.                         glLoadIdentity
  50.                         glOrtho(0, TGlobal.width[0], TGlobal.height[0], 0, -1, 1) ' TGlobal.w/h instead of GraphicsW/H for MaxGUI
  51.                        
  52.                         glMatrixMode GL_MODELVIEW
  53.                         glLoadIdentity
  54.                        
  55.                         SetViewport x, y, w, h
  56.                        
  57.                         Local MaxTex:Int
  58.                         glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(MaxTex))
  59.                        
  60.                         For Local Layer:Int = 0 Until MaxTex
  61.                                 glActiveTexture(GL_TEXTURE0+Layer)
  62.                        
  63.                                 glDisable(GL_TEXTURE_CUBE_MAP)
  64.                                 glDisable(GL_TEXTURE_GEN_S)
  65.                                 glDisable(GL_TEXTURE_GEN_T)
  66.                                 glDisable(GL_TEXTURE_GEN_R)
  67.                        
  68.                                 glDisable(GL_TEXTURE_2D)
  69.                         Next
  70.                        
  71.                         glActiveTexture(GL_TEXTURE0)
  72.                        
  73.                         glViewport(0, 0, TGlobal.width[0], TGlobal.height[0])
  74.                         glScissor(0, 0, TGlobal.width[0], TGlobal.height[0])
  75.                        
  76.                         glEnable GL_BLEND
  77.                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
  78.                         glEnable(GL_TEXTURE_2D)
  79.                        
  80.                 End Select
  81.                
  82.         End Function
  83.        
  84.         ' Old end Max2d function
  85.         Function EndMax2D( version:Int=1 )
  86.        
  87.                 Select version
  88.                
  89.                 Case 0 ' Old end function (by Oddball)
  90.                
  91.                         ' save the Max2D settings for later
  92.                         glPushAttrib(GL_ALL_ATTRIB_BITS)
  93.                         glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
  94.                         glMatrixMode(GL_MODELVIEW)
  95.                         glPushMatrix()
  96.                         glMatrixMode(GL_PROJECTION)
  97.                         glPushMatrix()
  98.                         glMatrixMode(GL_TEXTURE)
  99.                         glPushMatrix()
  100.                         glMatrixMode(GL_COLOR)
  101.                         glPushMatrix()
  102.                        
  103.                         TGlobal.EnableStates() ' enables normals and vertex colors
  104.                         glDisable(GL_TEXTURE_2D) ' needed as Draw in Max2d enables it, but doesn't disable after use
  105.                        
  106.                         ' set render state flags (crash if fx2 is not set)
  107.                         TGlobal.alpha_enable[0]=0 ' alpha blending was disabled by Max2d (GL_BLEND)
  108.                         TGlobal.blend_mode[0]=1 ' force alpha blending
  109.                         TGlobal.fx1[0]=0 ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
  110.                         TGlobal.fx2[0]=1 ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)
  111.                        
  112.                         glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
  113.                         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)
  114.                        
  115.                         glClearDepth(1.0)                                              
  116.                         glDepthFunc(GL_LEQUAL)
  117.                         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
  118.                        
  119.                         glAlphaFunc(GL_GEQUAL,0.5)
  120.                        
  121.                         For Local cam:TCamera=EachIn TCamera.cam_list
  122.                                 If cam=TGlobal.camera_in_use ' active camera - was if cam.hide[0]=0
  123.                                         cam.UpdateFog() ' fog with Max2d fix
  124.                                         Exit
  125.                                 EndIf
  126.                         Next
  127.                        
  128.                 Case 1 ' New end function, allows instant resolution switch (by Krischan)
  129.                
  130.                         ' save the Max2D settings for later
  131.                         'glPushAttrib(GL_ALL_ATTRIB_BITS)
  132.                         'glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
  133.                         glMatrixMode(GL_MODELVIEW)
  134.                         glPushMatrix()
  135.                         glMatrixMode(GL_PROJECTION)
  136.                         glPushMatrix()
  137.                         glMatrixMode(GL_TEXTURE)
  138.                         glPushMatrix()
  139.                         glMatrixMode(GL_COLOR)
  140.                         glPushMatrix()
  141.                          
  142.                         glDisable(GL_TEXTURE_CUBE_MAP)
  143.                         glDisable(GL_TEXTURE_GEN_S)
  144.                         glDisable(GL_TEXTURE_GEN_T)
  145.                         glDisable(GL_TEXTURE_GEN_R)
  146.                        
  147.                         glDisable(GL_TEXTURE_2D)
  148.                         glDisable(GL_BLEND)
  149.                        
  150.                         TGlobal.EnableStates()
  151.                        
  152.                         ' set render state flags (crash if fx2 is not set)
  153.                         TGlobal.alpha_enable[0]=0 ' alpha blending was disabled by Max2d (GL_BLEND)
  154.                         TGlobal.blend_mode[0]=1 ' force alpha blending
  155.                         TGlobal.fx1[0]=0 ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
  156.                         TGlobal.fx2[0]=1 ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)
  157.                        
  158.                         glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)
  159.                         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)
  160.                        
  161.                         glClearDepth(1.0)
  162.                         glDepthFunc(GL_LEQUAL)
  163.                         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
  164.                        
  165.                         glAlphaFunc(GL_GEQUAL, 0.5)
  166.                        
  167.                         For Local cam:TCamera=EachIn TCamera.cam_list ' active camera - was if cam.hide[0]=0
  168.                                 If cam = TGlobal.camera_in_use ' fog with Max2d fix
  169.                                         cam.UpdateFog()
  170.                                         Exit
  171.                                 EndIf
  172.                         Next
  173.                        
  174.                 End Select
  175.                
  176.         End Function
  177.        
  178. End Type
Title: Re: OpenB3D Questions
Post by: markcwm on January 22, 2019, 04:34:00 AM
Hi Krischan,

I think I have a fix for the ShadeSurface crash now, I was able to reproduce it, as it turns out the shader/usematrix crash is the same bug, which is a crash if a b3d model had no texture, it happened in shader render TurnOn. The fix skips rendering if there's no texture for shader, brush and surface brush.

Then there's a fix for the vertex color breaking with Max2D, it happens if the mesh is the last in the list, some state is not being set/reset but I couldn't figure out what so I settled for just rendering a dummy mesh after everything.

Also BeginMax2d has the glPopAttrib/glPushAttrib code back in because this may fix your MSI Afterburner issue, if you don't do this the blend state isn't saved and can be affected by other code, Text doesn't do this and it changes depending on the last blend used, see standard/alphamap. I wasn't able to test with Afterburner as I don't know what that is, so please let me know how that goes. Thanks!

I also noticed in LOF when you reload a level sometimes a letter is blocked out in the menu text, like it was a C today but an S last time, I think it must be a LOF bug as it happens randomly.
Title: Re: OpenB3D Questions
Post by: Krischan on January 22, 2019, 07:34:50 AM
Thanks Mark - I'll give it a try this evening. Looks like OpenB3D gets better every day :-) The MSI Afterburner is a free tool for overclocking but has the nice feature of this overlay for DX/OGL, too. You can display a lot of data like FPS, CPU/GPU usage, Core temp/clock and so on which is very useful for developing. You can download it here:

http://download.msi.com/uti_exe//vga/MSIAfterburnerSetup.zip (http://download.msi.com/uti_exe//vga/MSIAfterburnerSetup.zip)

Here is a short video how to set it up:


For the letter bug in LOF, do you have a screenshot? I haven't noticed this. There is a hidden debug mode for the menu screen - press the ^ circumflex key to see the menu text layout borders and change the resolution with 1,2,3 or 4 to see if it works (see attachment).
Title: Re: OpenB3D Questions
Post by: Krischan on January 22, 2019, 11:38:46 PM
I've tested the current version, the OSD works fine now, but it is still crashing here at Renderworld when loading a new level. Again, commenting the two ShadeSurface commands in the ApplyShaderCache Method "fix" the crash. I've used the LOFDEV_2019_01_07.zip with the LOF_DevPatch001.zip applied to make sure we have the same version for testing.
Title: Re: OpenB3D Questions
Post by: markcwm on January 23, 2019, 01:46:05 AM
Bummer. Okay since i can't reproduce try this please. Goto openb3dlib.mod/openb3d/src/material.cpp line 458
Code: [Select]
if (brush->tex[ix]==0 && surf->brush->tex[ix]==0 && Shader_Tex[ix]==0) return; // fixes crash if no texturesand comment that and replace with just "return;" and rebuild (without -a for quick build). Then uncomment your ShadeSurface and test, it shouldn't crash then.

 If that works then try debugging so go to the top of material.cpp and add
Code: [Select]
#include <stdio.h> then before the same return add
Code: [Select]
printf("%p %p %p \n",brush->tex[ix],surf->brush->tex[ix],Shader_Tex[ix]); and replace the return with the commented line above, build that and run until it crashes, then post the bottom 30 lines of the output window, hopefully there will be some (Nil) pointers. Thanks.
Title: Re: OpenB3D Questions
Post by: Krischan on January 23, 2019, 07:45:41 AM
Mark, I hope I followed your instructions correctly (it's early in the morning here ;D ). Commenting line 458 leads to the same result like commenting the two shadesurface commands - the models stay while all other textures vanish. Reloading is possible then.

Sometimes it loads the first level, sometimes it crashes without a warning, perhaps because there is too much output to the console window (the whole system hangs then for a while).

I've added some Screenshots including the complete log of a successful debug run trying to load the next level. I hope you can see the problem, I see only a bunch of digits ???
Title: Re: OpenB3D Questions
Post by: markcwm on January 24, 2019, 03:30:10 AM
Hi Krischan,

thanks for the output window text, I've a new fix up for this ShadeSurface no tex bug. Your debug shows first if there's a shadertex, then brushtex, then surfacetex, it suggests you're not applying a ShaderTexture at all, so that may be a bug in your BSP code but it still shouldn't crash. I didn't notice until now but TurnOn was changed in Openb3d 1.25 and a small mistake made which should now be 100% fixed, but if it still crashes goto material.cpp line 459 and edit it to be just:
Code: [Select]
if(Shader_Tex[ix]==0) break;
here's a screenie of the text bug, it appears after reloading a level but not at first load, it seems to keep to the same letter all the time but the color of the block often changes to black/purple or white.
(https://www.syntaxbomb.com/gallery/39_24_01_19_3_10_08.jpeg)

Title: Re: OpenB3D Questions
Post by: Krischan on January 26, 2019, 12:47:53 AM
Mark, I hate to say it but it still crashes here - there must be another problem. The question is why the April 30 version works. On the other hand, I've never seen the bug in your screenshot and I can't explain what could be wrong there. So why is only the "T" missing here? This makes no sense. It's a simple TTF font converted to OTF and using LoadImageFont, nothing special.
Title: Re: OpenB3D Questions
Post by: markcwm on January 26, 2019, 04:44:26 AM
Hi Krischan,

okay, I just noticed a bug in Surface constructor where vbo_id[] is set out of bounds, that may be crashing things for you. I also added new code to shader TurnOn which should be correct in theory and works here.

The text bug happens with other letters too, it just seems to be random, it may be something wierd in my Blitzmax install, I'll rebuild modules and see if it goes away.
Title: Re: OpenB3D Questions
Post by: Krischan on January 27, 2019, 10:33:19 PM
Crash ;D Is there any way that I can help you debugging this? All other OpenGL games work perfect, even the very old RTCW or ET. Do you test on nVidia or Ati? And you're using my Blitzmax setup?
Title: Re: OpenB3D Questions
Post by: markcwm on January 28, 2019, 02:28:20 AM
Hi Krischan,

yes that's disappointing! Well simplifying problems is always best, so can you confirm this crash is with the latest commit which is now fix 5 for this issue. To help you could run all shader examples in openb3dmax.docs to see if any crash, also you could test the texture loader in standard/lightmap, etc. Then you could go to material.cpp and at line 458 add a newline and paste:
Code: [Select]
if(Shader_Tex[ix]==0) break;What happened was Angros added code for brush and surface.brush properties to Shader::TurnOn which is still there but I've tried to make it safe. I don't really understand why he did this as a normal texture shouldn't really be used as a shader texture if not specified. The next step is to just revert to the old version.
Title: Re: OpenB3D Questions
Post by: Krischan on January 28, 2019, 07:26:16 AM
Hi Mark,

yes, I always use the latest commit. I've run all shader samples now in Debug mode, they work perfect except this one:

pixellight2.bmx crashes in line 54 (BrushFX) and according to debuglog in the function Shadesurface. Uncommenting Line 53-55 shows the tree, pressing P two times = crash. Hmm, sounds common? ;-)

The textureloader seems to work. Adding the line to material.cpp has no effect at all.
Title: Re: OpenB3D Questions
Post by: markcwm on January 30, 2019, 03:14:43 AM
Hi Krischan,

Hah, yes too common really! :P Well in this case the example is just referencing the wrong surface, so that's fixed now.

Thanks for testing, strange that the edit to material.cpp doesn't work when a return in the same place did, I have reverted Shader::TurnOn to the earlier (Apr 30) version, I also fixed a bug in LoadTexture, ApplyAlpha was accessing pixels outside bounds. There was also some bones code commented out in TB3D and I never noticed, animations I tested worked though.

I added a new CollapseAnimMesh for LoadMesh because it seemed to not be working properly, at least on 3ds files, the new function is working much better. It also transforms mesh vertices in case they have entity positions. T3DS has had it's multi-surface code removed now that CollapseAnimMesh works.
Title: Re: OpenB3D Questions
Post by: Krischan on January 30, 2019, 06:17:55 PM
There is an error compiling the current version in TSurface.bmx;151;3. Unable to convert from 'Byte Ptr' to 'String'

As it is only a debug function and I didn't know how to fix it I've REMarked the whole function to test the reverted shader functions - and guess what? It WORKS reloading the level, including the models and MSI Afterburner. Great. :o And the pixellight2.bmx example works too.
Title: Re: OpenB3D Questions
Post by: markcwm on February 01, 2019, 12:12:27 AM
Hi Krischan,

well that's a relief as I was beginning to wonder if I was ever going to fix that! :o

The string error is a BRL Bmax issue where you have to cast byte ptr to int, NG Bmax doesn't need that, I think it might auto-cast pointers. I added a StringPtr function for the fix.

Well I've a new commit fixing a few more things, first the previous ApplyAlpha fix was bad, it was a for..until loop and I thought it was a for..to loop so I added -1 which left alpha textures with 2 black edges.

Then I added alpha to LightMesh, it takes the value from EntityAlpha or BrushAlpha.

The other fix is for vertex colors and normals render states, I've let the library completely manage vertex colors, this was the only way I could find to fix your Starfield demo where it lost vertex colors after loading and also the samples/fakelight example. So there should be no need for SetBlend ALPHABLEND at init now.

For normals, I disabled them in the library and manage them from Bmax in BeginMax2d, the problem was that the metal torches with reflection maps in Romanbath.b3d were blank if managed by the library.
Title: Re: OpenB3D Questions
Post by: markcwm on February 02, 2019, 05:07:20 AM
Hi Krischan,

I've another small update, but nothing for the CopyEntity issue as I don't understand the problem yet.

CameraViewport is like in Minib3d now, I'm not sure if this fixes your problem as it seems to work the same for me. CameraPick and BackBufferToTex were also changed, all in the library instead of the wrapper.

DebugObject for Texture and Brush were added.

A fix for tex.gltex which wasn't working for normal single-frame textures.

A slight change to Graphics3D, GraphicsInit is now after the library function, as it should store the render states but it didn't seem to make any difference.
Title: Re: OpenB3D Questions
Post by: Krischan on February 03, 2019, 01:08:15 PM
There is still no crash, but a new bug in LOF: switching the resolution with keys 1-4 creates a "black bar" on the screen and the camera positioning goes wrong. This worked before.

Engine workflow: Key Press > call SetResolution(x,y) in main file > function SetResolution in include/system.bmx > calls SetGadgetShape, CameraViewport, CameraZoom

Title: Re: OpenB3D Questions
Post by: markcwm on February 04, 2019, 05:30:18 AM
Hi Krischan,

Quote
There is still no crash, but a new bug in LOF: switching the resolution with keys 1-4 creates a "black bar" on the screen and the camera positioning goes wrong. This worked before.

Engine workflow: Key Press > call SetResolution(x,y) in main file > function SetResolution in include/system.bmx > calls SetGadgetShape, CameraViewport, CameraZoom

well this isn't actually a bug in Openb3dmax, it's because you're not updating TGlobal.height[0]=height before CameraViewport, so either do that in TCam Update() or System SetResolution().

It worked before because CameraViewport was bottom-up OpenGL coords, I tested with minib3d/tex_render and it's now top-down screen coords like Minib3d. To invert we need to use "vy=TGlobal.height-h-vy" which is why it has to be updated when switching graphics resolution.

I've pushed a commit with some convenience functions to help make this clearer, they are GlobalResolution(w,h) to set, and GlobalWidth, GlobalHeight to get. I also moved GraphicsInit back to where it was, before states are set in Global::Graphics.
Title: Re: OpenB3D Questions
Post by: Krischan on February 04, 2019, 07:53:05 AM
That's why I wrote "a bug in LOF" ;D Adding TGlobal.Height[0] = Height or GlobalResolution(width, Height) to the TCam Update() function fixed the problem, thanks.

But there is another issue I can't fix without your help. Switch to higher resolutions (keys 3,4) and the second magic sphere camera and the hand light vanish. Going back to lower resolutions (1,2) and they are there again. Hmm... They are stored in the MINIMAP_CAMERA and MINIMAP_HANDLIGHT variables, init at GUI.bmx, function InitMinimap(), update occurs in TPlayer.bmx UpdateMinimap() function using the BackBufferToTex() function. Z-Order is off for the hand pivot children to make the hand visible over the rest of the 3D stuff. The compass (switch with key M) works. Could be a problem grabbing the texture in a higher resolution with wrong camera settings.
Title: Re: OpenB3D Questions
Post by: markcwm on February 06, 2019, 12:14:00 AM
Hi Krischan,

well I get the spheremap on keys 1,2 and 4 but not on 3 where it's also not even shown on screen, I had to drop the camera zoom to see it. I found out the resolution you're setting wasn't right, when I changed 1920,1200 to 1920,1080 then the spheremap worked.
Title: Re: OpenB3D Questions
Post by: Krischan on February 06, 2019, 07:32:34 PM
I think I must rethink my second camera concept. Strange enough it worked before but it fails now in higher resolutions. The texture grabbing seems to work, it looks like the camera position goes totally wrong but I dunno why. When I start the game from the beginning in the higher resolutions (the ones which fail later) - everything is fine, until I switch to a lower and back.

EDIT: I think I've found a workaround. I must call CameraViewport(MINIMAP_CAMERA, 0, 0, MINIMAP_RESOLUTION, MINIMAP_RESOLUTION) in the PositionMinimap() function which is called in the SetResolution() function. It only repositions the hand according to the current/new aspect ratio. But the MINIMAP_RESOLUTION value never changes even after switching the resolution (it is always 512) so it shouldn't be necessary there.
Title: Re: OpenB3D Questions
Post by: markcwm on February 12, 2019, 03:52:07 AM
Quote
2) Line 111 / 257 / TQuad Type: why are the vertex coordinate changes in CopyEntity not copied to all children meshes live like in MiniB3D? I manipulate the quads only in the source mesh, but the copies are ignored? Is it a bug? Or still not implemented? This is IMHO a very important feature of 3D graphics.

Hi Krischan,

I've fixed CopyEntity in the latest commit, Angros had it working with RepeatMesh but he made a mistake with CopyEntity thinking it was CopyMesh that did instancing in Blitz3d but it's not, well that or the docs are wrong.

So I made CopyMesh what CopyEntity was and made CopyEntity instance surfaces, this causes issues when using FreeEntity, I tried managing it with a list of surfaces but it was too complex so I decided the rule is you can't free a mesh before the copies or it will crash (unless you free them all at the same time).

CopyMesh in Minib3d doesn't copy entity data so I replaced it. Then RepeatMesh instances both surfaces and anim surfaces, I'm not sure what Angros was doing there as animation appears to not be smooth, but it works with FreeEntity now.
Title: Re: OpenB3D Questions
Post by: Krischan on February 12, 2019, 09:00:32 PM
That's good news Mark - instancing is very important. A quick miniB3D/OpenB3D comparison shows 108FPS vs. 133FPS @ 3840x1600 here - so OpenB3D is about 25% faster. Great. I only had to fix the code in Line 739 in the initial post to make it work again to CameraViewport tempcam, 0, 0, size, size.

What's not so great: LOF crashes again loading the next level (last Log entry is "Shaders deleted") :-((( Debug Error is "EXCEPTION BREAKPOINT" in the TEntity -> FreeEntity Method.

Another thing which is not a bug in OpenB3D but perhaps you or somebody else knows the answer - the OpenB3D starfield demo is not running smoothly, it has some kind of microstuttering when moving. I've played around with many of the nVidia settings but nothing helped. Flip true or false makes no difference, Fast/Quality settings neither. The MiniB3D demo has the same problem. But: starting a game like Everspace (D3D) or the old Wolfenstein Enemy Territory (OpenGL) with the same settings always run incredible smooth. The stuttering is best visible when moving the mouse around while moving. What could be the problem here?

Here's the modifed code to run with the latest OpenB3D commit:

Code: BlitzMax
  1. SuperStrict
  2.  
  3. Import openb3dmax.B3dglgraphics
  4.  
  5. Graphics3D DesktopWidth() / 1.0, DesktopHeight() / 1.0, 32, 2
  6.  
  7. ClearTextureFilters()
  8.  
  9. Global STARS:Int = 50000        ' number of stars per cluster part
  10. Global DIMENSION:Int = 2000     ' cluster dimension
  11. Global DISTRIBUTION:Float = 0.99' star distribution (0...1 = random...clustered)
  12. Global SPEED:Float = 1.0        ' overall move speed multiplicator
  13. Global BRAKE:Float = 0.95       ' brake multiplicator
  14. Global VSYNC:Int = True        ' Vertical Sync
  15. Global HOMING:Int = True        ' turn homing on/off
  16. Global COLORED:Int = False      ' colorize clusters
  17. Global TEXTURED:Int = True      ' use star texture
  18. Global Scale:Float = 0.5        ' star scale factor
  19. Global FADE:Int = True          ' fade distant clusters
  20. Global INSTANCING:Int = True    ' duplicate source mesh
  21.  
  22. Global DEBUGLEVEL:Int = 0       ' 0=off, 1=no instancing, 2=colored, 3=scene
  23.  
  24. If DEBUGLEVEL > 0 Then
  25.  
  26.         STARS = 1000
  27.         Scale = 1.6
  28.         DISTRIBUTION = 0.5
  29.         INSTANCING = False
  30.  
  31.         If DEBUGLEVEL > 1 Then
  32.  
  33.                 COLORED = True
  34.                 TEXTURED = False
  35.  
  36.                 If DEBUGLEVEL > 2 Then
  37.  
  38.                         HOMING = False
  39.                         FADE = False
  40.  
  41.                 EndIf
  42.  
  43.         EndIf
  44.  
  45. EndIf
  46.  
  47. ' ----------------------------------------------------------------------------
  48. ' Global variables
  49. ' ----------------------------------------------------------------------------
  50. Global localx:Float, localy:Float, localz:Float
  51. Global globalx:Float, globaly:Float, globalz:Float
  52. Global simx:Float, simy:Float, simz:Float
  53. Global xspeed:Float, yspeed:Float, zspeed:Float, rspeed:Float
  54. Global xadd:Float, yadd:Float, zadd:Float, radd:Float, tadd:Float
  55.  
  56. Global FPS:TFPS = New TFPS
  57. Global MS:Int = MilliSecs()
  58.  
  59. ' ----------------------------------------------------------------------------
  60. ' Init scene
  61. ' ----------------------------------------------------------------------------
  62. Global masterpivot:TPivot = CreatePivot()
  63.  
  64. Global cam:TCamera = CreateCamera()
  65. CameraRange cam, 1, DIMENSION * 8
  66. PositionEntity cam, 0, 0, 0
  67.  
  68. Local tex:TTexture = CreateSunTexture(512, 128, 128, 128)
  69. TextureBlend tex, 3
  70.  
  71. ' ----------------------------------------------------------------------------
  72. ' Duplicate Quad mesh in a 9x9x9 matrix
  73. ' ----------------------------------------------------------------------------
  74. Global meshlist:TList = CreateList()
  75. Global quadlist:TList = CreateList()
  76. Global quadsourcelist:TList = CreateList()
  77. Global lx:Float, ly:Float, lz:Float
  78.  
  79. Local entities:TEntity[9, 9, 9]
  80. Local meshes:TMesh[9, 9, 9]
  81.  
  82. Local mesh:TMesh
  83.  
  84. ' star cluster properties
  85. mesh = CreateMesh()
  86. EntityFX mesh, 1 + 2
  87. EntityBlend mesh, 3
  88. If TEXTURED Then EntityTexture mesh, tex
  89. HideEntity mesh
  90.  
  91. ' create blueprint star cluster
  92. For Local i:Int = 1 To STARS
  93.        
  94.         CreateStar(mesh)
  95.                
  96. Next
  97.  
  98. ' fix for OpenB3D to enable Texture Blending and Alpha?
  99. SetBlend ALPHABLEND
  100.  
  101. ' create 5x5x5 = 125 cluster
  102. For Local x:Int = 0 To 4 Step 1
  103.                
  104.         For Local y:Int = 0 To 4 Step 1
  105.  
  106.                 For Local z:Int = 0 To 4 Step 1
  107.  
  108.                         ' create a mesh and duplicate its properties = FAST
  109.                         If INSTANCING Then
  110.  
  111.                                 entities[x, y, z] = CopyEntity(mesh)
  112.  
  113.                                 PositionEntity entities[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION
  114.  
  115.                                 If COLORED Then
  116.  
  117.                                         EntityColor entities[x, y, z], Rand(64, 255), Rand(64, 255), Rand(64, 255)
  118.  
  119.                                 Else
  120.  
  121.                                         EntityColor entities[x, y, z], 255, 255, 255
  122.  
  123.                                 EndIf
  124.  
  125.                                 ListAddLast(meshlist, entities[x, y, z])
  126.  
  127.                         ' create many unique meshes without instancing = SLOW
  128.                         Else
  129.  
  130.                                 ' new mesh
  131.                                 meshes[x, y, z] = CreateMesh()
  132.                                 EntityFX meshes[x, y, z], 1
  133.                                 EntityBlend meshes[x, y, z], 3
  134.                                 If TEXTURED Then
  135.                                
  136.                                         EntityTexture meshes[x, y, z], tex
  137.                                         EntityFX meshes[x, y, z], 1 + 2
  138.                                        
  139.                                 EndIf
  140.        
  141.                                 ' duplicate blueprint cluster
  142.                                 For Local s:TQuad = EachIn quadsourcelist
  143.  
  144.                                         Local q:TQuad = New TQuad
  145.  
  146.                                         q.mesh = meshes[x, y, z]
  147.                                         q.x = s.x
  148.                                         q.y = s.y
  149.                                         q.z = s.z
  150.                                         q.scalex = s.scalex
  151.                                         q.scaley = s.scaley
  152.                                         q.RGB = s.RGB
  153.  
  154.                                         q.Add()
  155.                                         q.Update(cam)
  156.  
  157.                                         ListAddLast(quadlist, q)
  158.                                        
  159.                                 Next
  160.                                
  161.                                 PositionEntity meshes[x, y, z], (x - 2) * DIMENSION, (y - 2) * DIMENSION, (z - 2) * DIMENSION
  162.  
  163.                                 If COLORED Then
  164.  
  165.                                         EntityColor meshes[x, y, z], Rand(128, 255), Rand(128, 255), Rand(128, 255)
  166.  
  167.                                 Else
  168.  
  169.                                         EntityColor meshes[x, y, z], 255, 255, 255
  170.  
  171.                                 EndIf
  172.  
  173.                                 ListAddLast(meshlist, meshes[x, y, z])
  174.  
  175.                         EndIf
  176.  
  177.                         RenderWorld
  178.  
  179.                         Flip False
  180.  
  181.                 Next
  182.  
  183.         Next
  184.  
  185. Next
  186.  
  187. ' Fix to really center the mouse (otherwise it "jumps" a little bit initially)
  188. MoveMouse(GraphicsWidth() / 2, GraphicsHeight() / 2) ; Flip
  189. MouseX()
  190. MouseY()
  191. MouseXSpeed()
  192. MouseYSpeed()
  193. Flip
  194.  
  195. Global timer:TTimer = CreateTimer(60)
  196.  
  197. MS = MilliSecs() - MS
  198.  
  199. ' ----------------------------------------------------------------------------
  200. ' Main Loop
  201. ' ----------------------------------------------------------------------------
  202. While Not AppTerminate()
  203.  
  204.         If KeyHit(KEY_ESCAPE) Then End
  205.  
  206.         ' axis rotation
  207.         Local pitch:Float = Normalize(MouseY(), 0, GraphicsHeight() - 1, -2, 2)
  208.         Local yaw:Float = Normalize(MouseX(), 0, GraphicsWidth() - 1, 2, -2)
  209.         Local roll:Int = KeyDown(KEY_Q) - KeyDown(KEY_E)
  210.  
  211.         ' XYZ movement
  212.         Local xmove:Int = KeyDown(KEY_D) - KeyDown(KEY_A)
  213.         Local ymove:Int = KeyDown(KEY_R) - KeyDown(KEY_F)
  214.         Local zmove:Int = KeyDown(KEY_W) - KeyDown(KEY_S)
  215.         Local turbo:Int = KeyDown(KEY_TAB)
  216.  
  217.         If xmove = 0 And xadd <> 0 Then xadd = 0 Else If xmove And xadd = 0 Then xadd = 0.001
  218.         If ymove = 0 And yadd <> 0 Then yadd = 0 Else If ymove And yadd = 0 Then yadd = 0.001
  219.         If zmove = 0 And zadd <> 0 Then zadd = 0 Else If zmove And zadd = 0 Then zadd = 0.001
  220.         If roll = 0 And radd <> 0 Then radd = 0 Else If roll And radd = 0 Then radd = 0.01
  221.         If turbo = 0 And tadd <> 0 Then tadd:*0.9 Else If turbo And tadd = 0 Then tadd = 0.1
  222.  
  223.         If tadd < 0.01 Then tadd = 0.0
  224.  
  225.         If Abs(xmove) Then xadd:+0.01
  226.         If Abs(ymove) Then yadd:+0.01
  227.         If Abs(zmove) Then zadd:+0.01
  228.         If Abs(roll) Then radd:+0.025
  229.         If Abs(turbo) Then tadd:+0.05
  230.  
  231.         xadd:*1.025
  232.         yadd:*1.025
  233.         zadd:*1.025
  234.         radd:*1.025
  235.         tadd:*1.025
  236.  
  237.         If xadd > 2.0 Then xadd = 2.0
  238.         If yadd > 2.0 Then yadd = 2.0
  239.         If zadd > 2.0 Then zadd = 2.0
  240.         If radd > 1.5 Then radd = 1.5
  241.         If tadd > 25.0 Then tadd = 25.0
  242.  
  243.         ' calculate movespeed/rollspeed
  244.         If Abs(xmove) Then xspeed = xadd * SPEED * Sgn(xmove) * (1.0 + tadd)
  245.         If Abs(ymove) Then yspeed = yadd * SPEED * Sgn(ymove) * (1.0 + tadd)
  246.         If Abs(zmove) Then zspeed = zadd * SPEED * Sgn(zmove) * (1.0 + tadd)
  247.         If Abs(roll) Then rspeed = radd * Sgn(roll)
  248.  
  249.         ' perform rotation and motion
  250.         Turn(cam, pitch, yaw, rspeed)
  251.         MoveEntity cam, xspeed, yspeed, zspeed
  252.  
  253.         ' keep camera at home
  254.         If HOMING Then Home(cam, masterpivot, DIMENSION)
  255.  
  256.         ' only the master instance quads are facing to the camera
  257.         For Local q:TQuad = EachIn quadlist
  258.  
  259.                 q.Update(cam)
  260.  
  261.         Next
  262.  
  263.         ' fade mesh according to its distance
  264.         If FADE Then
  265.  
  266.                 For Local e:TEntity = EachIn meshlist
  267.  
  268.                         Local d:Float = EntityDistance(cam, e)
  269.                         Local a:Float = Normalize(d, DIMENSION * 1.0, DIMENSION * 2.0, 1.0, 0.0)
  270.                         EntityAlpha e, a
  271.  
  272.                 Next
  273.  
  274.         EndIf
  275.  
  276.         RenderWorld
  277.  
  278.         FPS.Update()
  279.  
  280.         ' fix for OpenB3D to have vertex colors enabled (otherwise its greyscale)
  281.         Begin2D()
  282.  
  283.                 DrawText("FPS [Init]..: " + FPS.FPS + " [" + MS + "ms]", 0, 0)
  284.                 DrawText("Star Cluster: " + STARS, 0, 15)
  285.                 DrawText("Stars Total.: " + (STARS * 5 * 5 * 5), 0, 30)
  286.  
  287.         End2D()
  288.        
  289.         Flip VSYNC
  290.  
  291.         ' decrease speed
  292.         xspeed:*BRAKE
  293.         yspeed:*BRAKE
  294.         zspeed:*BRAKE
  295.         rspeed:*BRAKE
  296.  
  297. Wend
  298.  
  299. End
  300.  
  301. ' creates a single star quad
  302. Function CreateStar(mesh:TMesh, surf:TSurface = Null, xoff:Float = 0.0:Float, yoff:Float = 0.0, zoff:Float = 0.0)
  303.  
  304.         Local q:TQuad = New TQuad
  305.  
  306.         q.mesh = mesh
  307.         q.surf = surf
  308.  
  309.         q.x = Rnd(-DIMENSION / 2, DIMENSION / 2) + xoff
  310.         q.y = Rnd(-DIMENSION / 2, DIMENSION / 2) + yoff
  311.         q.z = Rnd(-DIMENSION / 2, DIMENSION / 2) + zoff
  312.        
  313.         ' randomized clustering
  314.         If Rnd(1) > 1 - DISTRIBUTION Then
  315.  
  316.                 Local d:Float = Rnd(0.0001, 0.05)
  317.  
  318.                 q.x = lx + Rnd(-DIMENSION * d, DIMENSION * d) + xoff
  319.                 q.y = ly + Rnd(-DIMENSION * d, DIMENSION * d) + yoff
  320.                 q.z = lz + Rnd(-DIMENSION * d, DIMENSION * d) + zoff
  321.  
  322.         EndIf
  323.  
  324.         q.scalex = Rnd(1, Rnd(2, Rnd(4, Rnd(8, Rnd(16, 32))))) * Scale
  325.         q.scaley = q.scalex
  326.  
  327.         Local c:Float = (1.0 / q.scalex)
  328.         If Rnd(1) > 0.9 And c < 0.70 Then c = 1 - c             ' 10% Giants
  329.         If c >= 0.0 And c < 0.35 Then q.RGB = [255, 64, 0]      ' 35% Class M
  330.         If c >= 0.35 And c < 0.50 Then q.RGB = [255, 128, 32]   ' 15% Class K
  331.         If c >= 0.50 And c < 0.60 Then q.RGB = [255, 255, 64]   ' 10% Class G
  332.         If c >= 0.60 And c < 0.70 Then q.RGB = [255, 255, 128]  ' 10% Class F
  333.         If c >= 0.70 And c < 0.80 Then q.RGB = [255, 255, 255]  ' 10% Class A
  334.         If c >= 0.80 And c < 0.90 Then q.RGB = [0, 64, 255]     ' 10% Class B
  335.         If c >= 0.90 And c <= 1.00 Then q.RGB = [0, 0, 255]     ' 10% Class O
  336.  
  337.         q.Add()
  338.         q.Update(cam)
  339.  
  340.         ListAddLast(quadlist, q)
  341.         ListAddLast(quadsourcelist, q)
  342.        
  343.         lx = q.x
  344.         ly = q.y
  345.         lz = q.z
  346.  
  347. End Function
  348.  
  349. ' keeps the player in a predefined cubic area
  350. Function Home(target:TEntity, world:TEntity, homesize:Int = 100)
  351.  
  352.         ' store Local player Position
  353.         Local localx:Double = EntityX(target)
  354.         Local localy:Double = EntityY(target)
  355.         Local localz:Double = EntityZ(target)
  356.  
  357.         ' Check X axis
  358.         While localx > homesize
  359.  
  360.                 globalx:+homesize
  361.                 localx:-homesize
  362.                 PositionEntity target, localx, localy, localz
  363.                 MoveEntity world, -homesize, 0, 0
  364.                
  365.         Wend
  366.  
  367.         While localx < - homesize
  368.  
  369.                 globalx:-homesize
  370.                 localx:+homesize
  371.                 PositionEntity target, localx, localy, localz
  372.                 MoveEntity world, homesize, 0, 0
  373.  
  374.         Wend
  375.  
  376.         ' Check Y axis
  377.         While localy > homesize
  378.  
  379.                 globaly:+homesize
  380.                 localy:-homesize
  381.                 PositionEntity target, localx, localy, localz
  382.                 MoveEntity world, 0, -homesize, 0
  383.  
  384.         Wend
  385.  
  386.         While localy < - homesize
  387.  
  388.                 globaly:-homesize
  389.                 localy:+homesize
  390.                 PositionEntity target, localx, localy, localz
  391.                 MoveEntity world, 0, homesize, 0
  392.  
  393.         Wend
  394.  
  395.         ' Check Z axis
  396.         While localz > homesize
  397.  
  398.                 globalz:+homesize
  399.                 localz:-homesize
  400.                 PositionEntity target, localx, localy, localz
  401.                 MoveEntity world, 0, 0, -homesize
  402.  
  403.         Wend
  404.  
  405.         While localz < - homesize
  406.  
  407.                 globalz:-homesize
  408.                 localz:+homesize
  409.                 PositionEntity target, localx, localy, localz
  410.                 MoveEntity world, 0, 0, homesize
  411.  
  412.         Wend
  413.  
  414.         ' store simulated player Position
  415.         simx = localx + globalx
  416.         simy = localy + globaly
  417.         simz = localz + globalz
  418.  
  419. End Function
  420.  
  421. ' ----------------------------------------------------------------------------
  422. ' Normalizes a value to given range
  423. ' ----------------------------------------------------------------------------
  424. Function Normalize:Float(value:Float, vmin:Float, vmax:Float, nmin:Float, nmax:Float)
  425.  
  426.         Return((value - vmin) / (vmax - vmin)) * (nmax - nmin) + nmin
  427.  
  428. End Function
  429.  
  430. ' ----------------------------------------------------------------------------
  431. ' Turn Entity using Quaternions
  432. ' ----------------------------------------------------------------------------
  433. Function Turn(Ent:TEntity, X:Float = 0.0, Y:Float = 0.0, Z:Float = 0.0, Glob:Int = False)
  434.  
  435.         Local Pitch:Float = 0.0
  436.         Local Yaw:Float = 0.0
  437.         Local Roll:Float = 0.0
  438.  
  439.         Local Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)
  440.         Local Turn_Quat:TQuaternion = EulerToQuat(0.0, 0.0, 0.0)
  441.  
  442.         If Glob = False
  443.  
  444.                 Quat = EulerToQuat(EntityPitch(Ent, True), EntityYaw(Ent, True), EntityRoll(Ent, True))
  445.                 Turn_Quat = EulerToQuat(X, Y, Z)
  446.                 Quat = MultiplyQuats(Quat, Turn_Quat)
  447.                 Quat = NormalizeQuat(Quat)
  448.                 QuatToEuler2(Quat.x[0], Quat.y[0], Quat.z[0], Quat.w[0], pitch, yaw, roll)
  449.                 RotateEntity Ent, pitch, yaw, roll
  450.  
  451.         Else
  452.  
  453.                 RotateEntity Ent, EntityPitch(Ent) + X, EntityYaw(Ent) + Y, EntityRoll(Ent) + Z
  454.  
  455.         EndIf
  456.  
  457. End Function
  458.  
  459. ' ----------------------------------------------------------------------------
  460. ' Euler to Quaternion
  461. ' ----------------------------------------------------------------------------
  462. Function EulerToQuat:TQuaternion(pitch:Float, yaw:Float, roll:Float)
  463.  
  464.         Local cr:Float = Cos(-roll / 2.0)
  465.         Local cp:Float = Cos(pitch / 2.0)
  466.         Local cy:Float = Cos(yaw / 2.0)
  467.         Local sr:Float = Sin(-roll / 2.0)
  468.         Local sp:Float = Sin(pitch / 2.0)
  469.         Local sy:Float = Sin(yaw / 2.0)
  470.         Local cpcy:Float = cp * cy
  471.         Local spsy:Float = sp * sy
  472.         Local spcy:Float = sp * cy
  473.         Local cpsy:Float = cp * sy
  474.  
  475.         Local q:TQuaternion = NewQuaternion()
  476.        
  477.         q.w[0] = cr * cpcy + sr * spsy
  478.         q.x[0] = sr * cpcy - cr * spsy
  479.         q.y[0] = cr * spcy + sr * cpsy
  480.         q.z[0] = cr * cpsy - sr * spcy
  481.  
  482.         Return q
  483.  
  484. End Function
  485.  
  486. ' ----------------------------------------------------------------------------
  487. ' Quaternion to Euler
  488. ' ----------------------------------------------------------------------------
  489. Function QuatToEuler2(x:Float, y:Float, z:Float, w:Float, pitch:Float Var, yaw:Float Var, roll:Float Var)
  490.  
  491.         Local QuatToEulerAccuracy:Double = 1.0 / 2 ^ 31
  492.  
  493.         Local sint:Float = (2.0 * w * y) - (2.0 * x * z)
  494.         Local cost_temp:Float = 1.0 - (sint * sint)
  495.         Local cost:Float
  496.  
  497.         If Abs(cost_temp) > QuatToEulerAccuracy
  498.  
  499.                 cost = Sqr(cost_temp)
  500.  
  501.         Else
  502.  
  503.                 cost = 0.0
  504.  
  505.         EndIf
  506.  
  507.         Local sinv:Float, cosv:Float, sinf:Float, cosf:Float
  508.  
  509.         If Abs(cost) > QuatToEulerAccuracy
  510.  
  511.                 sinv = ((2.0 * y * z) + (2.0 * w * x)) / cost
  512.                 cosv = (1.0 - (2.0 * x * x) - (2.0 * y * y)) / cost
  513.                 sinf = ((2.0 * x * y) + (2.0 * w * z)) / cost
  514.                 cosf = (1.0 - (2.0 * y * y) - (2.0 * z * z)) / cost
  515.  
  516.         Else
  517.  
  518.                 sinv = (2.0 * w * x) - (2.0 * y * z)
  519.                 cosv = 1.0 - (2.0 * x * x) - (2.0 * z * z)
  520.                 sinf = 0.0
  521.                 cosf = 1.0
  522.  
  523.         EndIf
  524.  
  525.         pitch = ATan2(sint, cost)
  526.         yaw = ATan2(sinf, cosf)
  527.         roll = -ATan2(sinv, cosv)
  528.  
  529. End Function
  530.  
  531. ' ----------------------------------------------------------------------------
  532. ' Multiply Quaternion
  533. ' ----------------------------------------------------------------------------
  534. Function MultiplyQuats:TQuaternion(q1:TQuaternion, q2:TQuaternion)
  535.  
  536.         Local q:TQuaternion = NewQuaternion()
  537.  
  538.         q.w[0] = q1.w[0] * q2.w[0] - q1.x[0] * q2.x[0] - q1.y[0] * q2.y[0] - q1.z[0] * q2.z[0]
  539.         q.x[0] = q1.w[0] * q2.x[0] + q1.x[0] * q2.w[0] + q1.y[0] * q2.z[0] - q1.z[0] * q2.y[0]
  540.         q.y[0] = q1.w[0] * q2.y[0] + q1.y[0] * q2.w[0] + q1.z[0] * q2.x[0] - q1.x[0] * q2.z[0]
  541.         q.z[0] = q1.w[0] * q2.z[0] + q1.z[0] * q2.w[0] + q1.x[0] * q2.y[0] - q1.y[0] * q2.x[0]
  542.  
  543.         Return q
  544.  
  545. End Function
  546.  
  547. ' ----------------------------------------------------------------------------
  548. ' Normalize Quaternion
  549. ' ----------------------------------------------------------------------------
  550. Function NormalizeQuat:TQuaternion(q:TQuaternion)
  551.  
  552.         Local uv:Float = Sqr(q.w[0] * q.w[0] + q.x[0] * q.x[0] + q.y[0] * q.y[0] + q.z[0] * q.z[0])
  553.  
  554.         q.w[0] = q.w[0] / uv
  555.         q.x[0] = q.x[0] / uv
  556.         q.y[0] = q.y[0] / uv
  557.         q.z[0] = q.z[0] / uv
  558.  
  559.         Return q
  560.  
  561. End Function
  562.  
  563. ' ------------------------------------------------------------------------------------------------
  564. ' Quad Type
  565. ' ------------------------------------------------------------------------------------------------
  566. Type TQuad
  567.  
  568.         Field x:Float = 0.0                                                                             ' position x
  569.         Field y:Float = 0.0                                                                             ' position y
  570.         Field z:Float = 0.0                                                                             ' position z
  571.  
  572.         Field row:Int = 0                                                                               ' texture row
  573.         Field col:Int = 0                                                                               ' texture column
  574.  
  575.         Field scalex:Float = 1.0                                                                ' current size X
  576.         Field scaley:Float = 1.0                                                                ' current size Y
  577.  
  578.         Field RGB:Int[] = [255, 255, 255]                                               ' Vertex Color
  579.         Field Alpha:Float = 1.0                                                                 ' Vertex Alpha
  580.  
  581.         Field v:Int = 0                                                                                 ' vertex counter
  582.         Field mesh:TMesh = Null                                                                 ' mesh pointer
  583.         Field surf:TSurface = Null                                                              ' surface pointer
  584.  
  585.         ' --------------------------------------------------------------------------------------------
  586.         ' METHOD: Add new Quad
  587.         ' --------------------------------------------------------------------------------------------
  588.         Method Add(col:Int = 0, row:Int = 0)
  589.  
  590.                 Local s:Int = CountSurfaces(mesh)
  591.                 If s = 0 Then
  592.                
  593.                         surf = CreateSurface(mesh)
  594.                        
  595.                 Else
  596.                
  597.                         surf = GetSurface(mesh, s)
  598.                        
  599.                 EndIf
  600.                
  601.                 Local i:Int = CountVertices(surf)
  602.                 If i + 4 > 32768 Then
  603.  
  604.                         surf = CreateSurface(mesh)
  605.                         v = 0
  606.  
  607.                 EndIf
  608.  
  609.                 ' add Vertices
  610.                 Local V0:Int = AddVertex(surf, 0, 0, 0, 1, 0)
  611.                 Local V1:Int = AddVertex(surf, 0, 0, 0, 1, 1)
  612.                 Local V2:Int = AddVertex(surf, 0, 0, 0, 0, 1)
  613.                 Local V3:Int = AddVertex(surf, 0, 0, 0, 0, 0)
  614.  
  615.                 ' color vertices
  616.                 VertexColor surf, V0, RGB[0], RGB[1], RGB[2], Alpha
  617.                 VertexColor surf, V1, RGB[0], RGB[1], RGB[2], Alpha
  618.                 VertexColor surf, V2, RGB[0], RGB[1], RGB[2], Alpha
  619.                 VertexColor surf, V3, RGB[0], RGB[1], RGB[2], Alpha
  620.  
  621.                 ' connect triangles
  622.                 AddTriangle surf, V0, V1, V2
  623.                 AddTriangle surf, V0, V2, V3
  624.  
  625.                 VertexTexCoords surf, V0, col + 1, row
  626.                 VertexTexCoords surf, V1, col + 1, row + 1
  627.                 VertexTexCoords surf, V2, col, row + 1
  628.                 VertexTexCoords surf, V3, col, row
  629.  
  630.                 ' increase vertex counter
  631.                 If v >= 4 Then v = V0 + 4 Else v = V0
  632.  
  633.         End Method
  634.  
  635.         ' --------------------------------------------------------------------------------------------
  636.         ' METHOD: Update a Quad
  637.         ' --------------------------------------------------------------------------------------------
  638.         Method Update(target:TEntity)
  639.  
  640.                 TFormVector scalex, 0, 0, target, Null
  641.                 Local X1:Float = TFormedX()
  642.                 Local Y1:Float = TFormedY()
  643.                 Local Z1:Float = TFormedZ()
  644.                
  645.                 TFormVector 0, scaley, 0, target, Null
  646.                 Local X2:Float = TFormedX()
  647.                 Local Y2:Float = TFormedY()
  648.                 Local Z2:Float = TFormedZ()
  649.  
  650.                 ' set vertices
  651.                 VertexCoords surf, v + 0, x - x1 - x2, y - y1 - y2, z - z1 - z2
  652.                 VertexCoords surf, v + 1, x - x1 + x2, y - y1 + y2, z - z1 + z2
  653.                 VertexCoords surf, v + 2, x + x1 + x2, y + y1 + y2, z + z1 + z2
  654.                 VertexCoords surf, v + 3, x + x1 - x2, y + y1 - y2, z + z1 - z2
  655.  
  656.         End Method
  657.  
  658. End Type
  659.  
  660. ' ------------------------------------------------------------------------------------------------
  661. ' Exact FPS counter
  662. ' ------------------------------------------------------------------------------------------------
  663.  
  664. Type TFPS
  665.  
  666.         Global renders:Int = 0
  667.  
  668.         Field FPS:Int = 60                                                                              ' current FPS value
  669.         Field interval:Int = 999
  670.         Field averagefps:Int = 60                                                               ' average FPS value
  671.         Field framedrops:Int = 0                                                                ' dropped frames
  672.         Field oldlooptime:Int = 0
  673.         Field looptime:Int = 0
  674.         Field multi:Float                                                                               ' main loop multiplicator
  675.  
  676.         Field old:Int = MilliSecs()
  677.         Field totalfps:Int = 30
  678.         Field Ticks:Int
  679.  
  680.         ' --------------------------------------------------------------------------------------------
  681.         ' METHOD: Update FPS counter
  682.         ' --------------------------------------------------------------------------------------------
  683.         Method Update()
  684.  
  685.                 renders:+1
  686.  
  687.                 looptime = MilliSecs() - oldlooptime
  688.                 oldlooptime = MilliSecs()
  689.  
  690.                 If MilliSecs() - old >= interval Then
  691.  
  692.                         old = MilliSecs()
  693.  
  694.                         FPS = renders * (1000 / interval)
  695.                         renders = 0
  696.                         totalfps:+FPS
  697.                         Ticks:+1
  698.                        
  699.                         averagefps = totalfps / Ticks
  700.  
  701.                 EndIf
  702.  
  703.         End Method
  704.  
  705. End Type
  706.  
  707. ' Create a stunning star texture
  708. Function CreateSunTexture:TTexture(size:Int = 512, r:Int = 255, g:Int = 255, b:Int = 255)
  709.  
  710.         Local i:Float, j:Int, col:Int, rgb:Int
  711.         Local x:Int, y:Int
  712.        
  713.         Local w:Int = GraphicsWidth()
  714.  
  715.         Local tempcam:TCamera, tempsun:TPivot
  716.         Local pixmap:TPixmap = CreatePixmap(size, size, PF_RGBA8888)
  717.         Local tex:TTexture = CreateTexture(size, size, 1 + 8)
  718.  
  719.         For j = 0 To (size / 2) - 1
  720.  
  721.                 col = 255 - Normalize(j, 0, (size / 2.0) - 1, 0, 255)
  722.                 If col > 255 Then col = 255
  723.                 rgb = col * $1000000 + col * $10000 + col * $100 + col
  724.  
  725.                 For i = 0 To 360 Step 0.1
  726.  
  727.                         WritePixel(pixmap, (size / 2) + (Sin(i) * j), (size / 2) + (Cos(i) * j), rgb)
  728.  
  729.                 Next
  730.  
  731.         Next
  732.        
  733.         PixmapToTexture(pixmap, tex)
  734.         SavePixmapPNG(pixmap, "proceduralstar1.png", 0)
  735.  
  736.         ' temp camera
  737.         tempcam = CreateCamera()
  738.         CameraRange tempcam, 1, w * 2
  739.        
  740.         ' fix for OpenB3D to simulate MiniB3D's Cameraviewport handling
  741.         CameraViewport tempcam, 0, 0, size, size
  742.  
  743.         ' temp pivot
  744.         tempsun = CreatePivot()
  745.  
  746.         ' Create 4 body quads
  747.         CreateQuad(tempsun, size * 1.0, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
  748.         CreateQuad(tempsun, size * 1.5, tex, 3, 1 + 8 + 16, r * 1.00, g * 1.00, b * 1.00, 1.00)
  749.         CreateQuad(tempsun, size * 2.0, tex, 3, 1 + 8 + 16, r * 0.75, g * 0.75, b * 0.50, 0.75)
  750.         CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, r * 0.50, g * 0.50, b * 0.50, 0.50)
  751.  
  752.         ' create 4 ray quads
  753.         Local ray1:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
  754.         Local ray2:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 1)
  755.         Local ray3:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)
  756.         Local ray4:TMesh = CreateQuad(tempsun, size * 4.0, tex, 3, 1 + 8 + 16, 255, 255, 255, 0.5)
  757.  
  758.         ' rescale and rotate rays
  759.         ScaleEntity ray1, size * 2, size / 32, size
  760.         ScaleEntity ray2, size / 32, size * 2, size
  761.         ScaleEntity ray3, size, size / 32, size
  762.         ScaleEntity ray4, size, size / 32, size
  763.         RotateEntity ray3, 0, 0, 45
  764.         RotateEntity ray4, 0, 0, 135
  765.        
  766.         PositionEntity tempsun, 0, 0, w
  767.  
  768.         ' render star
  769.         RenderWorld
  770.         RenderWorld
  771.  
  772.         ' grab image
  773.         pixmap = GrabPixmap(0, 0, size, size)
  774.         For x = 0 To size - 1
  775.  
  776.                 For y = 0 To size - 1
  777.  
  778.                         rgb = ReadPixel(pixmap, x, y)
  779.  
  780.                         r = (rgb & $ff0000) / $10000
  781.                         g = (rgb & $ff00) / $100
  782.                         b = (rgb & $ff)
  783.  
  784.                         ' rgb
  785.                         rgb = (r + g + b) / 3 * $1000000 + r * $10000 + g * $100 + b
  786.  
  787.                         WritePixel(pixmap, x, y, rgb)
  788.  
  789.                 Next
  790.  
  791.         Next
  792.  
  793.         PixmapToTexture(pixmap, tex)
  794.         'SavePixmapPNG(pixmap, "proceduralstar2.png", 0)
  795.  
  796.         ' Delete pixmap, pivot and temp cam
  797.         pixmap = Null
  798.         FreeEntity tempsun
  799.         FreeEntity tempcam
  800.  
  801.         Return tex
  802.  
  803. End Function
  804.  
  805. ' custom quad creation
  806. Function CreateQuad:Tmesh(parent:TEntity, scale:Float = 1.0, tex:TTexture = Null, blend:Int = False, fx:Int = False, r:Int = 255, g:Int = 255, b:Int = 255, a:Float = 1.0)
  807.  
  808.         Local mesh:TMesh = CreateMesh()
  809.         Local surf:TSurface = CreateSurface(mesh)
  810.         Local v0:Int, v1:Int, v2:Int, v3:Int
  811.  
  812.         v0 = AddVertex(surf, 1, 1, 0, 0, 0)
  813.         v1 = AddVertex(surf, -1, 1, 0, 1, 0)
  814.         v2 = AddVertex(surf, -1, -1, 0, 1, 1)
  815.         v3 = AddVertex(surf, 1, -1, 0, 0, 1)
  816.  
  817.         AddTriangle surf, v0, v1, v2
  818.         AddTriangle surf, v0, v2, v3
  819.  
  820.         If parent Then EntityParent Mesh, parent
  821.         If fx Then EntityFX Mesh, fx
  822.         If tex Then EntityTexture Mesh, tex
  823.         If blend Then EntityBlend Mesh, blend
  824.  
  825.         EntityColor Mesh, r, g, b
  826.         EntityAlpha Mesh, a
  827.  
  828.         VertexColor surf, v0, r, g, b, a
  829.         VertexColor surf, v1, r, g, b, a
  830.         VertexColor surf, v2, r, g, b, a
  831.         VertexColor surf, v3, r, g, b, a
  832.  
  833.         ScaleEntity Mesh, Scale, Scale, Scale
  834.  
  835.         Return Mesh
  836.  
  837. End Function
  838.  
  839. ' creates a texture from a pixmap
  840. Function PixmapToTexture(pixmap:TPixmap, tex:TTexture)
  841.  
  842.         If PixmapFormat(pixmap) <> PF_RGBA8888 Then pixmap = ConvertPixmap(pixmap, PF_RGBA8888)
  843.  
  844.         ' OpenB3D only function to copy pixmap to texture
  845.         BufferToTex tex, PixmapPixelPtr(pixmap, 0, 0)
  846.  
  847.         ' MiniB3D workaround to copy pixmap to texture
  848.         'glBindTexture (GL_TEXTURE_2D, tex.gltex[0])
  849.         'gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, PixmapPixelPtr(pixmap, 0, 0))
  850.  
  851. End Function
  852.  
  853. ' --------------------------------------------------------------------------------
  854. ' Fixed BeginMax2D()
  855. ' --------------------------------------------------------------------------------
  856. Function Begin2D()
  857.  
  858.         Local x:Int, y:Int, w:Int, h:Int
  859.         GetViewport(x, y, w, h)
  860.  
  861.         'glPopClientAttrib()
  862.         'glPopAttrib()
  863.         glMatrixMode(GL_MODELVIEW)
  864.         glPopMatrix()
  865.         glMatrixMode(GL_PROJECTION)
  866.         glPopMatrix()
  867.         glMatrixMode(GL_TEXTURE)
  868.         glPopMatrix()
  869.         glMatrixMode(GL_COLOR)
  870.         glPopMatrix()
  871.        
  872.         glDisable(GL_LIGHTING)
  873.         glDisable(GL_DEPTH_TEST)
  874.         glDisable(GL_SCISSOR_TEST)
  875.         glDisable(GL_FOG)
  876.         glDisable(GL_CULL_FACE)
  877.  
  878.         glMatrixMode GL_TEXTURE
  879.         glLoadIdentity
  880.  
  881.         glMatrixMode GL_PROJECTION
  882.         glLoadIdentity
  883.         glOrtho 0, GraphicsWidth(), GraphicsHeight(), 0, -1, 1
  884.  
  885.         glMatrixMode GL_MODELVIEW
  886.         glLoadIdentity
  887.  
  888.         SetViewport x, y, w, h
  889.  
  890.         Local MaxTex:Int
  891.         glGetIntegerv(GL_MAX_TEXTURE_UNITS, Varptr(MaxTex))
  892.  
  893.         For Local Layer:Int = 0 Until MaxTex
  894.  
  895.                 glActiveTexture(GL_TEXTURE0+Layer)
  896.  
  897.                 glDisable(GL_TEXTURE_CUBE_MAP)
  898.                 glDisable(GL_TEXTURE_GEN_S)
  899.                 glDisable(GL_TEXTURE_GEN_T)
  900.                 glDisable(GL_TEXTURE_GEN_R)
  901.  
  902.                 glDisable(GL_TEXTURE_2D)
  903.  
  904.         Next
  905.  
  906.         glActiveTexture(GL_TEXTURE0)
  907.  
  908.         glViewport(0, 0, GraphicsWidth(), GraphicsHeight())
  909.         glScissor(0, 0, GraphicsWidth(), GraphicsHeight())
  910.  
  911.         glEnable GL_BLEND
  912.         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
  913.         glEnable(GL_TEXTURE_2D)
  914.  
  915. End Function
  916.  
  917. ' --------------------------------------------------------------------------------
  918. ' Fixed EndMax2D()
  919. ' --------------------------------------------------------------------------------
  920. Function End2D()
  921.  
  922.         ' save the Max2D settings for later
  923.         'glPushAttrib(GL_ALL_ATTRIB_BITS)
  924.         'glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS)
  925.         glMatrixMode(GL_MODELVIEW)
  926.         glPushMatrix()
  927.         glMatrixMode(GL_PROJECTION)
  928.         glPushMatrix()
  929.         glMatrixMode(GL_TEXTURE)
  930.         glPushMatrix()
  931.         glMatrixMode(GL_COLOR)
  932.         glPushMatrix()
  933.                
  934.         glDisable(GL_TEXTURE_CUBE_MAP)
  935.         glDisable(GL_TEXTURE_GEN_S)
  936.         glDisable(GL_TEXTURE_GEN_T)
  937.         glDisable(GL_TEXTURE_GEN_R)
  938.  
  939.         glDisable(GL_TEXTURE_2D)
  940.         glDisable(GL_BLEND)
  941.  
  942.         TGlobal.EnableStates()
  943.         'glDisable(GL_TEXTURE_2D)
  944.  
  945.         ' only needed for OpenB3D
  946.         TGlobal.alpha_enable[0] = 0     ' alpha blending was disabled by Max2d (GL_BLEND)
  947.         TGlobal.blend_mode[0] = 1       ' force alpha blending
  948.         TGlobal.fx1[0] = 0                      ' full bright/surface normals was enabled by EnableStates (GL_NORMAL_ARRAY)
  949.         TGlobal.fx2[0] = 1                      ' vertex colors was enabled by EnableStates (GL_COLOR_ARRAY)
  950.  
  951.         glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)
  952.         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE)
  953.  
  954.         glClearDepth(1.0)
  955.         glDepthFunc(GL_LEQUAL)
  956.         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
  957.  
  958.         glAlphaFunc(GL_GEQUAL, 0.5)
  959.  
  960.         ' only needed for OpenB3D
  961.         For Local cam:TCamera=EachIn TCamera.cam_list
  962.                
  963.                  ' active camera - was if cam.hide[0]=0
  964.                  If cam = TGlobal.camera_in_use
  965.                
  966.                         ' fog with Max2d fix
  967.                         cam.UpdateFog()
  968.                         Exit
  969.                        
  970.                 EndIf
  971.                
  972.         Next
  973.  
  974. End Function

Title: Re: OpenB3D Questions
Post by: markcwm on February 13, 2019, 03:52:47 AM
Quote
What's not so great: LOF crashes again loading the next level (last Log entry is "Shaders deleted") :-((( Debug Error is "EXCEPTION BREAKPOINT" in the TEntity -> FreeEntity Method.

Hi Krischan,

well I thought this was due to deleting surfaces but it seems not, I uncommented the code to delete bones, now I see why it was commented. :) So a quick fix, is goto mesh.cpp line 331 in FreeEntity and comment out "delete bone". This should be in though so I'll have to have a go at fixing it properly.

Re: microstuttering, I don't really follow you, are you sure it's not just low FPS?
Title: Re: OpenB3D Questions
Post by: Krischan on February 13, 2019, 07:47:00 AM
Uncommenting didn't help. The Feb 9, 2019 commit (Added DebugFields/Globals, TVector wrapped, Terrain vertices) and the second Feb 10, 2019 commit (Fix CopyEntity causing FreeEntity crash) work, the latest one and the first Feb 10, 2019 commit (Fixed CopyEntity not instancing, CopyMesh now full copy) crash.

And do you think that 133FPS @ 3840x1600 is too low? :o

EDIT: Anyway, we shouldn't pay too much attention to the microstutters as it could be related to my GPU/Display combination. Such a large display can have unwanted side effects unless it has 144Hz (I have "only" 75Hz)
Title: Re: OpenB3D Questions
Post by: markcwm on February 14, 2019, 05:07:04 AM
I'm sure the latest crashes are due to me un-commenting the delete bones code in Mesh::Freeentity, as I've been able to reproduce it with LOF and fix it by removing that code, the bones are stored in the entity child_list and also in the mesh bones list, which is what I didn't realize, so yeah it was double freeing. That was a bit stupid of me, oh well I learned some new stuff.
Title: Re: OpenB3D Questions
Post by: Krischan on February 15, 2019, 10:17:28 AM
Your latest commit fixed it again. So what problems are left, I've lost track of things ??? I think it is only point 5) with the barely noticeable moving of the mouse pointer after centering (Line 187 ff.)

Change the lines like this and the mouse is moving:

Code: BlitzMax
  1. ' Fix to really center the mouse (otherwise it "jumps" a little bit initially)
  2. MoveMouse(GraphicsWidth() / 2, GraphicsHeight() / 2)' ; Flip
  3. 'MouseX()
  4. 'MouseY()
  5. 'MouseXSpeed()
  6. 'MouseYSpeed()
  7. 'Flip
Title: Re: OpenB3D Questions
Post by: markcwm on February 15, 2019, 02:03:55 PM
Phew, that's great, thanks Krischan! :)

Re: MouseMove, I don't think this is a bug at all, when you use the mouse to move the camera you have to do that sort of thing to take control, there are demos in Blitz3d that do the same thing.

Edit: also I notice DrawText doesn't work with the current BeginMax2d, this is because it needs GL_TEXTURE_2D enabled, GLDrawText doesn't so I'll push that fix with the next feature, which will be Minib3d's AntiAlias code.
Title: Re: OpenB3D Questions
Post by: Krischan on February 15, 2019, 02:36:45 PM
Well, the code worked in miniB3D without a workaround like Flip/Reset/Flip :P The problem is when the program starts and the user takes no action there is movement where it shouldn't.
Title: Re: OpenB3D Questions
Post by: markcwm on February 17, 2019, 12:25:16 AM
Quote
5) Line 205-206: in OpenB3D the mouse pointer moves slightly after initialization, this can only be fixed by NOT subtracting -1 in GraphicsHeight() - in MiniB3D it works (and would also be mathematically correct) - is it a rounding bug?

Hmm, well I had another look at this. I can't really follow your GraphicsHeight-1 fix but I think you mean for the pitch/yaw variables. I found no difference subtracting -1 and I found no difference at all between Minib3d and Openb3d, also there's not really anything I can do about this as they are Brl.System commands, but if you place MoveMouse before the first Renderworld then you don't see the jump, although you do see the mouse pointer move.
Title: Re: OpenB3D Questions
Post by: Krischan on February 17, 2019, 01:29:59 AM
Hmm looks you're right - I can't reproduce it here now. I swear I had this problem on my old rig and checked it many times. Anyway, I've fixed it now in my code by checking too small numbers:

If Abs(pitch) < 0.005 Then pitch = 0
If Abs(yaw) < 0.005 Then yaw = 0

Well I think afaik all known bugs are fixed now. Time for new bugs, we're running out of bugs ;D
Title: Re: OpenB3D Questions
Post by: markcwm on February 17, 2019, 04:29:09 AM
I tried the pitch/yaw fix but it still moved at render init, it might have been an issue on a previous version but it's good to know it's now working like Minib3d.

I'm really happy I could fix all these bugs and thanks to you Krischan for your assistance and persistence which I'm sure was not easy. I don't really thank people enough for their help fixing these bugs some people have been amazingly helpful in the past, I think good feedback can be as valuable as the fix.

I'm glad you can now carry on with your project which I think looks great, although maybe we should look at fixing that bumpmap issue, what shader are you using, is it test.frag?

Also, Minib3d's AntiAlias is now in with the latest commit and example, it's the same speed as in Minib3d but quite slow compared to the shader fxaa example by RonTek.
Title: Re: OpenB3D Questions
Post by: Krischan on February 17, 2019, 12:00:52 PM
No Mark, I have to thank you. With OpenB3D, my project looks much better than all MiniB3D tests before. Optimizing the shader is a good idea, yes it is test.frag. I'm still not very good writing shaders and this one became complex. I'd like to have a shader style like in "Legend of Grimrock" (it looks very similar but the name is a coincidence and my game will work different than LOG), with nice lighting and shadows but I never achieved it, not even close. So more help is welcome and appreaciated.

As you can see in the test.frag I'm using Distance Fog, Tone Mapping, some kind of flashlight illumination/attenuation and a fake bumpmap to create depth. It looks somehow nice but is far away from a really good looking shader. And I had problems to make the shadows work with my level geometry.

I think another important point are very good normal textures, I'm using my own "Legend of Faerghail Normalmap Generator.bmx" to save time by converting a diffuse map into a normalmap, but all normalmap textures should be drawn by hand according to the diffuse map to have better detail (though my tool already creates nice results in a single mouseclick). To make it work again you must comment the "Import brl.d3d9max2d" and uncomment the "Import brl.glmax2d" line, I don't know what happened there (I'm getting a _d3dDev.Reset failed)

Title: Re: OpenB3D Questions
Post by: markcwm on February 23, 2019, 11:12:20 PM
Hi Krischan,

yes that does look awesome, much better than LOF. I have been kind of distracted getting multisample antialiasing (for Windows) running and fixing several bugs with ClearWorld, which is still not finished.

I think the soft shadows there are shader based, I was talking to RonTek about this and he posted some code which I'll try to convert to Openb3dmax, here's the link (https://www.blitzcoder.org/forum/topic.php?id=156).
Title: Re: OpenB3D Questions
Post by: Qube on February 23, 2019, 11:20:01 PM
@Krischan - That looks really impressive and highly professional, nice work indeed :)
Title: Re: OpenB3D Questions
Post by: Derron on February 23, 2019, 11:31:49 PM
@Krischan - That looks really impressive and highly professional, nice work indeed :)

Are you talking about the screenshots (Krischan's work) or the gameplay video (of another game) ?


bye
Ron
Title: Re: OpenB3D Questions
Post by: Qube on February 23, 2019, 11:43:22 PM
Quote
Are you talking about the screenshots (Krischan's work) or the gameplay video (of another game) ?
Krischan's work of course. I do know that LOG is not his :P. I kinda missed this thread and only just read through it.
Title: Re: OpenB3D Questions
Post by: Krischan on February 24, 2019, 12:58:38 AM
Thanks Qube, you should see it in action (if it runs, see PM). But I didn't make any progress in the last months as Mark and I had to find out and fix some nasty OpenB3D bugs first, which is this topic about.

And without Mark, it would not exist in this form. So thanks again to Mark for OpenB3D at this point ;D
Title: Re: OpenB3D Questions
Post by: Krischan on February 24, 2019, 01:15:42 AM
yes that does look awesome, much better than LOF.
Very true, but it hurts :P. To distinguish the two games better I've switched the name to "Faerghail" only. Faerghail already looks nice but it could look even nicer. Perhaps you have an idea how to pimp it.

I think the soft shadows there are shader based, I was talking to RonTek about this and he posted some code which I'll try to convert to Openb3dmax, here's the link (https://www.blitzcoder.org/forum/topic.php?id=156).
Yes, Grimrock is using shaders for everything - and they have very nice and clean normalmaps (see attachment). For OpenB3D I would prefer a simple shadow solution that I could add to the game without having to rewrite much of it.
Title: Re: OpenB3D Questions
Post by: Qube on February 24, 2019, 01:39:33 AM
Quote
Thanks Qube, you should see it in action (if it runs, see PM).
Thanks for the PM :) - I wasn't aware of the original but was that an Amiga emulator in an exe? lol, so cool. Where are such magics from? ( so behind the times )

I tried your other zip file in both VM and native boot but each one failed unfortunately. They both got as far as showing the screen res options > loading splash screen with compass and then an "EXPECTION_ACCESS_VIOLATION" error.

I only have Windows 7 via VM and Windows 10 as a native boot so if you want me to install any bits and pieces or debug stuff then feel free to send as much as you want :)

*edit* - The other exe's in the zip file for the maps and stuff appeared to run fine though.
Title: Re: OpenB3D Questions
Post by: markcwm on February 24, 2019, 02:09:13 AM
Qube, it could be the shader code, it only runs in GL 2.1.

Krischan, yeah don't get me wrong I think the art in Faergail is fine but it needs nicer bumpmapping code, which would be correct angle calculations and less glossy, maybe the lighting is a bit better too.
Title: Re: OpenB3D Questions
Post by: Qube on February 24, 2019, 02:24:31 AM
Quote
Qube, it could be the shader code, it only runs in GL 2.1.
Does that not work on Window 10?
Title: Re: OpenB3D Questions
Post by: Krischan on February 24, 2019, 11:19:11 AM
Qube, it should work on a native system but not in a VM, perhaps VMware but I don't own it. Which graphics card do you have: ATI/nVidia/Model? GPU RAM size? Here it is working on Windows 10 x64 Pro 1809 with a nVidia RTX 2080/8GB, Driver version 417.71 which is not the newest but still new enough.

And yes, the Amiga emulator is WinUAE (here the old version 3.4) which comes in a single exe today, I've only renamed it. The harddrive setup was complex but it runs very good and fast. You can restore an old savegame like "Aktuell" or "Schloss" which is inside the castle to see the difference between the original and Faerghail. But don't expect too much, this game is 30 years old now, this is "gaming stone age".

Mark, I know the bumpmapping is not correct, there is much room for improvements or we should use a complete new shader. I was starting with the bumpmap2.frag example, wasn't happy with it and rewrote everything to meet my needs. But writing shaders, I'm still a newbie. They are hard to debug and there are a lot of mathemetics and procedures inside I don't understand yet.
Title: Re: OpenB3D Questions
Post by: Qube on February 24, 2019, 02:02:20 PM
Windows 10 is native and not VM. I tried native first and then a VM but both failed. I have a few games installed on Windows 10 so all needed bits should be present.

GPU is a Radeon RX580 8GB which should be up to the task :)
Title: Re: OpenB3D Questions
Post by: Krischan on February 24, 2019, 03:15:30 PM
Then it must be the shader itself as I can't check the game on a ATI card here (I can only debug the shader source using the included glslangvalidator.exe which says it has some errors inside but works so far, at least on my rig). I decided to keep Intel+nVidia for my new rig as this combination never made any problems (even if it is much more expensive than AMD) and got rid of all AMD stuff years ago. Perhaps I'll buy a smaller rig with AMD/ATI only for my wife in the future to test the games there, but not yet.

However, you can change the EXE with the attached one, which is a recompile with the basic.frag shader which has no compilation errors, perhaps it works. But it looks not so good like the test shader. Or fix the shader bug to make it run with ATI and recompile it with BlitzmaxOS and the latest OpenB3D by yourself, the full source is included. ;D
Title: Re: OpenB3D Questions
Post by: Qube on February 24, 2019, 10:14:48 PM
That one worked fine, thanks. Still looks really good without a fancy shader :)

Quote
I decided to keep Intel+nVidia for my new rig as this combination never made any problems (even if it is much more expensive than AMD)
Mine is a special Apple version in an iMac so it's super expensive for what it is :P
Title: Re: OpenB3D Questions
Post by: Krischan on February 24, 2019, 11:12:41 PM
Good to hear that it works now. Looks like I have to put more effort into the shader QA. Ok, new release date for Faerghail is set to Fall 2059, after my funeral :o

I abandoned iMac after they decided to go for Intel+AMD, a bad combination IMHO - either one should use the overexpensive Intel+nVidia combo or go for the cheaper rebels from AMD instead. But don't mix it. And I still remember the problems I had back in 2001 with my Radeon 8500, never again, they've lost me as a customer forever.

My previous iMac was the Late 2013 (i7-4770+nVidia 780M) which is still a really good machine but after 5 years it became "too slow" for me (I know, first world problems :D) so I sold it and got my new rig which is really up to date now. And now as they'll go for ARM in the Macs, Apple is history to me. Good luck without Steve Jobs, I'm off.

If I want to take a look into Mojave I now start Virtualbox and there is my old system again (thanks to Disk2VHD) which is now encapsulated as a slave of Win10 :-D Was not that easy but it's working. But I'm working 99% on Windows, so it is merely a waste of SSD space, I've been just curious if it works.
Title: Re: OpenB3D Questions
Post by: Qube on February 25, 2019, 12:10:02 AM
Quote
Good to hear that it works now. Looks like I have to put more effort into the shader QA. Ok, new release date for Faerghail is set to Fall 2059, after my funeral :o
Don't forget to post about it here :P

Quote
I abandoned iMac after they decided to go for Intel+AMD, a bad combination IMHO - either one should use the overexpensive Intel+nVidia combo
I'd of preferred Intel + nVidia too but I am impressed how well the RX580 preforms compared to my earlier iMac which had a pretty naff nVidia GPU ( 740M I think it was ). This is the first iMac that's actually decent at running modern games to any decent frame rate.

Quote
And now as they'll go for ARM in the Macs, Apple is history to me.
I'm not sure about that move as it'll mean the end to dual booting Windows and MacOS which many people do. Also for those who use Windows via Parallels will get screwed too as there is no way you're going to get perfect X86 emulation under ARM at anywhere near native speeds. It'll be a really dumb move if they do replace Intel CPU's with ARM ones.
Title: Re: OpenB3D Questions
Post by: Krischan on February 25, 2019, 06:00:30 AM
I am impressed how well the RX580 preforms compared to my earlier iMac which had a pretty naff nVidia GPU ( 740M I think it was ). This is the first iMac that's actually decent at running modern games to any decent frame rate.

Yes, even the Late 2013 was a gaming machine, too (with at least High Details in modern games). But the RTX 2080 is a beast and wants Ultra only, so I don't really miss it - like the 16:9 screen (21:9 is more immersive but hard to configure in older games) :P The ARM decision reminds me of Hitchhiker's Guide to the Galaxy:

"The story so far: In the beginning Apple switched to ARM. This has made a lot of people very angry and been widely regarded as a bad move." :P
Title: Re: OpenB3D Questions
Post by: Steve Elliott on February 25, 2019, 09:18:31 AM
Quote
And now as they'll go for ARM in the Macs, Apple is history to me.

I'm not sure about that move as it'll mean the end to dual booting Windows and MacOS which many people do. Also for those who use Windows via Parallels will get screwed too as there is no way you're going to get perfect X86 emulation under ARM at anywhere near native speeds. It'll be a really dumb move if they do replace Intel CPU's with ARM ones.

"The story so far: In the beginning Apple switched to ARM. This has made a lot of people very angry and been widely regarded as a bad move." :P

That would be a very bad move IMO too.



Title: Re: OpenB3D Questions
Post by: Naughty Alien on February 25, 2019, 02:01:03 PM
@Krischan

..those dungeons looks fantastic..very nice..
Title: Re: OpenB3D Questions
Post by: Krischan on March 01, 2019, 03:12:25 PM
Thanks Naughty Alien, I hope you mean my project, not the LOG video (which looks even more fantastic). :))

Mark, I have another suggestion about an issue which is bugging me since MiniB3D, perhaps you have an elegant solution for this. In TTexture.bmx line 573-589 (https://github.com/markcwm/openb3dmax.mod/blob/master/openb3dmax.mod/inc/TTexture.bmx) a check is performed if a texture has been already loaded before and uses the loaded one if yes, like an instance. This is a nice feature to save VRAM but can bring the coder (me!) in trouble when you need to treat the same texture with two different blend modes. So when I'm loading a texture file and set its blend mode to 2 and load the same file again but with a different handle and set its blend mode to 3, the blend mode of the first texture handle becomes 3, too. That is bad.

I've avoided this by just eliminating the whole check in Line 574 with

Code: BlitzMax
  1. Local old_tex:TTexture'=tex.TexInList()

which makes every loaded texture unique, but I'm not happy with this solution as in other cases the check could be useful. Perhaps we can add a flag to the LoadTexture function or create a global function so switch it on/off before loading such a multi-role texture. You know what I mean?

EDIT: or a new function "CopyTexture" to copy an already loaded texture to a different, unique handle which is independant from the original texture.
Title: Re: OpenB3D Questions
Post by: markcwm on March 02, 2019, 04:21:16 AM
Hi Krischan,

yes that's not something that occurred to me before, the simplest way round this is to save the same image with different filenames, but I have a fix uploaded now which uses your ideas, which is a good solution. So you use CopyTexture() and there's an internal global to disable TexInList() when copying, it works in the library as well as BMax.
Title: Re: OpenB3D Questions
Post by: Krischan on March 02, 2019, 11:00:42 AM
Thanks Mark. But there is a new compile error:

Compile Error: Identifier 'glClearDepthf' not found
[c:/Apps/Coding/BlitzMax/mod/openb3dmax.mod/openb3dmax.mod/inc/TGlobal.bmx;268;3]
Build Error: failed to compile c:/Apps/Coding/BlitzMax/mod/openb3dmax.mod/openb3dmax.mod/openb3dmax.bmx

As it fails on a single OpenGL command - do I need to update another module or is it O3D related?

Commenting this line shows a second error (and perhaps there can be more):

Compile Error: Unable to convert from 'Byte Ptr' to 'String'
[c:/Apps/Coding/BlitzMax/mod/openb3dmax.mod/openb3dmax.mod/inc/TTexture.bmx;1006;5]
Build Error: failed to compile c:/Apps/Coding/BlitzMax/mod/openb3dmax.mod/openb3dmax.mod/openb3dmax.bmx

So I can't test it right now.
Title: Re: OpenB3D Questions
Post by: markcwm on March 02, 2019, 05:21:22 PM
Hi Krischan,

sorry, I should have tested it in BRL BMax. It should be fixed now.

glClearDepthf isn't declared in BRL pub.glew (nor in Maxmods glew) but it is declared in NG pub.glew. I copied code from the library where it is declared from GLee.
Title: Re: OpenB3D Questions
Post by: Krischan on March 02, 2019, 09:29:20 PM
Ok, works now - thanks! A question: I wondered if it is possible to have load flags like in LoadTexture in this function, like tex=CopyTexture(tex,1+2+8). If there are no new flags given, the flags of the original texture are used. This makes the function more flexible. Here's my attempt, if you think it is ok you can add it:

functions.bmx
Code: BlitzMax
  1. Rem
  2. bbdoc: Returns a copy of the new texture
  3. End Rem
  4. Function CopyTexture:TTexture( tex:TTexture, flags:Int )
  5.         Return tex.Copy(flags)
  6. End Function

TTexture.bmx
Code: BlitzMax
  1.         Method Copy:TTexture(copyflags:Int=Null)
  2.                
  3.                 Select TGlobal.Texture_Loader
  4.                
  5.                         Case 2 ' library
  6.                                 Local inst:Byte Ptr=TextureCopy_( GetInstance(Self) )
  7.                                 Return CreateObject(inst)
  8.                                
  9.                         Default ' wrapper
  10.                                 Local tex:TTexture=NewTexture()
  11.                                
  12.                                 tex.SetString(tex.file,GetString(file))
  13.                                 tex.SetString(tex.file_abs,FileAbs(GetString(file))) ' returns absolute path of file if relative
  14.                                 tex.blend[0]=blend[0]
  15.                                 tex.coords[0]=coords[0]
  16.                                 tex.u_scale[0]=u_scale[0]
  17.                                 tex.v_scale[0]=v_scale[0]
  18.                                 tex.u_pos[0]=u_pos[0]
  19.                                 tex.v_pos[0]=v_pos[0]
  20.                                 tex.angle[0]=angle[0]
  21.                                
  22.                                 ' added by Krischan to use new flags instead of the original ones
  23.                                 If copyflags then flags[0]=copyflags
  24.                                
  25.                                 TTexture.is_unique=True
  26.                                 If no_frames[0]<2
  27.                                         LoadAnimTextureStream(GetString(file),flags[0],0,0,0,1,tex)
  28.                                 Else
  29.                                         LoadAnimTextureStream(GetString(file),flags[0],width[0],height[0],0,no_frames[0],tex)
  30.                                 EndIf
  31.                                 TTexture.is_unique=False
  32.                                 Return tex
  33.                                
  34.                 EndSelect
  35.                
  36.         End Method
Title: Re: OpenB3D Questions
Post by: markcwm on March 03, 2019, 02:10:37 AM
Hi Krischan,

Great! Okay I can add flags if you think this is needed, there is no command to set flags as such so other than adding a TextureFlags function there is no way to alter flags other than with tex.flags[0].
Title: Re: OpenB3D Questions
Post by: Krischan on March 04, 2019, 07:46:46 AM
Yes, I'd appreciate if you add this in the next update if there's nothing else against it. Sometimes I reuse a texture, for example a texture is loaded with alpha flag (1+2+8) and again without (1+8) and this would save diskspace or I'd need to save the same texture twice with different filenames like you described it to keep the "texture instance" feature.

In Faerghail, I'm using this feature for my loading screen - the loader pic in the middle is the version without alpha and I use the same picture with an alpha flag zoomed in a larger size, blended with another texture as a background filler because a simple wall texture or just a black screen is too boring ;D
Title: Re: OpenB3D Questions
Post by: markcwm on March 06, 2019, 03:57:07 AM
Hi Krischan,

sure I'll add your fix in to the next commit, I just realized there is a TextureFlags function already in there but certainly no reason not to add it to CopyTexture.

I'm currently struggling a bit with Adam Redwoods awesome batch sprites. I can get it working in Minib3d but Openb3d works a bit different, especially with sprites so I'm just trying to fix that so we can have better single-surface options.
Title: Re: OpenB3D Questions
Post by: markcwm on March 10, 2019, 12:16:49 AM
Hi Krischan,

CopyTexture(flags) is now in along with batch sprites from minib3d-monkey, this exposed a fix for AddVertex/Triangle which over-resizes arrays to prevent crashes, which is what Minib3d does.

The batch sprite port is in Blitzmax but there's a few issues, first it's not as fast as Minib3d and second there's a render bug which changes the orientation of sprites/meshes at a certain angle, but this is a general bug and nothing to do with batch sprite code. See docs example samples/mak/firepaint3d. There's also an unfinished port to c++ which I may fix later.

Re: your screenies, I can't really follow what you mean but I do think your loading screens are awesome.
Title: Re: OpenB3D Questions
Post by: markcwm on March 13, 2019, 01:16:17 AM
Hi Krischan,

I've another update which fixes the batch sprites bugs, it seems the "render bug which changes the orientation of sprites/meshes at a certain angle" was actually a bug with the Blitzmax port but that code is replaced with the C++ port which works perfectly and is actually faster than Minib3d, roughly twice as fast, so that's the icing on the cake for me! I didn't expect that, interesting for anyone wondering if C++ is faster than Blitzmax.
Title: Re: OpenB3D Questions
Post by: Krischan on March 13, 2019, 10:12:52 PM
Great, though I haven't used the Batchsprites yet. Oh, and Faerghail still works but I hadn't much time to work on it :-D So what comes next? I'm still unsure how to create a better looking RPG style torchlight shader with shadows to illuminate my levels properly. Perhaps like in this demo video with multiple lights and shadows. The bumpmap.bmx example in OpenB3D is nice to learn the basics but could be better in this point.

Title: Re: OpenB3D Questions
Post by: markcwm on March 16, 2019, 02:04:59 AM
Hi Krischan,

thanks nice video. Yes I'm going to have a go at soft shadows soon, first I'm tidying up some shader examples by RonTek and then I think we really need an example of the new Postfx functions.
Title: Re: OpenB3D Questions
Post by: markcwm on June 03, 2019, 11:18:06 PM
Hello Krischan,

I don't think I'll be able to work on soft shadows and bump maps for a while yet, but let me know if you get anything done.
Title: Re: OpenB3D Questions
Post by: Krischan on June 28, 2019, 09:56:43 AM
Thanks for the notice. I'll continue programming it without the shaders for now, but at the moment I've stopped the development, I've had enough other problems and no nerves at the moment. But I'd love to hear if/when you continue working on the shaders.
Title: Re: OpenB3D Questions
Post by: angros47 on July 03, 2019, 07:29:00 PM
Bump map and soft shadows are features (experimental) in OpenB3D Plus 0.1