Minib3d copymesh bug

BlitzMax Forums/MiniB3D Module/Minib3d copymesh bug

Trinosis(Posted 2016) [#1]
I've stumbled across a bug in minib3d-v054 when copying meshes.

When creating a cylinder or cone, the countsurfaces() command returns 2 surfaces for each.

If i copy a cylinder or cone mesh and use countsurfaces(), i get 1 surface returned for each copied mesh.

So, creating a mesh returns 2 surfaces and copying a mesh returns 1 surface.

Cubes and spheres seem to be ok though.


This is demonstrated via the code below.




Strict

Import sidesign.minib3d


Graphics3D 1024 , 768 , 32 , 3 , 60



Global created_cylinder:Tmesh = createcylinder()
Global copied_cylinder:Tmesh = copymesh(created_cylinder)

Global created_cone:Tmesh = createcone()
Global copied_cone:Tmesh = copymesh(created_cone)

Global created_sphere:Tmesh = createsphere()
Global copied_sphere:Tmesh = copymesh(created_sphere)

Global created_cube:Tmesh = createcube()
Global copied_cube:Tmesh = copymesh(created_cube)




While KeyDown(KEY_ESCAPE) = False

  RenderWorld

  BeginMax2D()


    SetColor(255 , 255 , 255)

    DrawText("CountSurfaces(created_cylinder) = " + CountSurfaces(created_cylinder) , 0 , 0)
    DrawText("CountSurfaces(copied_cylinder) = " + CountSurfaces(copied_cylinder) , 0 , 20)

    DrawText("CountSurfaces(created_cone) = " + CountSurfaces(created_cone) , 0 , 50)
    DrawText("CountSurfaces(copied_cone) = " + CountSurfaces(copied_cone) , 0 , 70)

    DrawText("CountSurfaces(created_sphere) = " + CountSurfaces(created_sphere) , 0 , 100)
    DrawText("CountSurfaces(copied_sphere) = " + CountSurfaces(copied_sphere) , 0 , 120)

    DrawText("CountSurfaces(created_cube) = " + CountSurfaces(created_cube) , 0 , 150)
    DrawText("CountSurfaces(copied_cube) = " + CountSurfaces(copied_cube) , 0 , 170)


  EndMax2D()



  Flip()


Wend

End




RustyKristi(Posted 2016) [#2]
Same result with OpenB3D btw

Edit: Same with Blitz3D, so I don't think it's a bug anymore.

Maybe someone can explain the underlyings why is this the case.

Graphics3D 800, 600 , 0 , 2 

Global created_cylinder = CreateCylinder()
Global copied_cylinder = CopyMesh(created_cylinder)

Global created_cone = CreateCone()
Global copied_cone = CopyMesh(created_cone)

Global created_sphere = CreateSphere()
Global copied_sphere = CopyMesh(created_sphere)

Global created_cube = CreateCube()
Global copied_cube = CopyMesh(created_cube)




While KeyDown(1) = False

  RenderWorld




    Color(255 , 255 , 255)

    Text  0 , 0,"CountSurfaces(created_cylinder) = " + CountSurfaces(created_cylinder)
    Text  0 , 20,"CountSurfaces(copied_cylinder) = " + CountSurfaces(copied_cylinder) 

    Text  0 , 50,"CountSurfaces(created_cone) = " + CountSurfaces(created_cone)
   Text 0 , 70,"CountSurfaces(copied_cone) = " + CountSurfaces(copied_cone) 

    Text  0 , 100,"CountSurfaces(created_sphere) = " + CountSurfaces(created_sphere) 
    Text  0 , 120,"CountSurfaces(copied_sphere) = " + CountSurfaces(copied_sphere) 

    Text 0 , 150,"CountSurfaces(created_cube) = " + CountSurfaces(created_cube)
    Text 0 , 170,"CountSurfaces(copied_cube) = " + CountSurfaces(copied_cube) 




  Flip()


Wend

End


In Blitz3d, since it does not use variable types like TMesh TEntity etc, if you use CopyEntity it returns 2.


Trinosis(Posted 2016) [#3]
Thanks for the info RustyKristi.

Thats really interesting.

I've just tried your example in Blitz3d and got the same results.
And reading the description in the Blitz3d Commands tells me

"The difference between CopyMesh and CopyEntity is that CopyMesh performs a 'deep' copy of a mesh. "

And indeed CopyEntity returns 2 surfaces whereas copymesh returns 1.

I'm assuming a deep copy means all surfaces and all verticies on those surfaces.

It looks as though for the time being, to be safe, i just need to load my meshes each time, instead of loading one instance and then copying it.

Interesting though, that this occurs in Blitz3d and OpenB3D as well.
Which suggests to me that Minib3d and OpenB3D have been copied from blitz3d.


Kryzon(Posted 2016) [#4]
Internally, MiniB3D uses AddMesh inside the CopyMesh function, and AddMesh itself tries to combine surfaces when the brushes are the same, as an optimisation.

What's possibly happening is that you create a mesh with two surfaces (a cylinder or a cone, they are created with one surface for the sides and one for the caps) and it comes with a default brush (white, no FX flags etc.). When you do a CopyMesh\AddMesh the brushes for all those surfaces are the same, so the surfaces are merged into one.

To test this out, before copying the mesh, try to paint each surface of the original mesh with unique brushes (any brush parameters that are different make a brush unique, like colour for example).
Graphics3D 800, 600 , 0 , 2 

Local brush1 = CreateBrush( 255, 0, 0 ) ;Different colours, enough to make these brushes unique.
Local brush2 = CreateBrush( 0, 0, 255 ) 

Local original_cone = CreateCone() ;Defaults to "solid" (has bottom cap).

;Comment the next two lines to get only 1 surface for the copied mesh.
PaintSurface( GetSurface( original_cone, 1 ), brush1 )
PaintSurface( GetSurface( original_cone, 2 ), brush2 )

Local copied_cone = CopyMesh( original_cone )

Print( "CountSurfaces( original_cone ) = " + CountSurfaces( original_cone ) )
Print( "CountSurfaces( copied_cone ) = " + CountSurfaces( copied_cone ) )

WaitKey()

End



Trinosis(Posted 2016) [#5]
Thanks for the info Kryzon.

Again very informative.

The example code demonstrates your explantion.

I stumbled across this issue when i was copying all of the verticies from a mesh that was created, into a mesh that was copied.

Looping through all surfaces of the created mesh and reading all the verticies on each.

Assuming both meshes were the same, one being copied from the other, i was getting runtime errors writing to a surface in the copied mesh that didn't exist.

I guess it's one of those quirks that hasn't been addressed and has carried over from Blitz3d into Minib3d and OpenB3D.


RemiD(Posted 2016) [#6]
Also, Blitz3d AddMesh() sometimes merges 2 vertices which have the same position but belongs to different triangles... That's why i have coded my own AddSurfaceToOtherSurface() function, which prevents this...


Trinosis(Posted 2016) [#7]
Thanks for the tip RemiD. :)


RemiD(Posted 2016) [#8]
@Trinosis>>take a look at this : http://www.blitzbasic.com/codearcs/codearcs.php?code=3291

and let me know if you find a bug...