Bug in RenderWorld
BlitzMax Forums/MiniB3D Module/Bug in RenderWorld
| ||
here is a program that demonstrates the bug. Press the spacebar to render new cubes. Sometimes it'll crash the first time, sometimes you have to press the spacebar a few times before it crashes. It is crashing with "Unhandled Exception:Attempt to access field or method of Null object" It is stopping in TMesh.bmx, line 1510: red# =brush.red Edit: Changed resolution in the code to something more reasonable than my native wide-screen resolution :) |
| ||
no bug within minib3d I think, it is more a bug or failure in th Garbage Collector of BMax. It seems if you remove an Entity this way sometimes the Delete() Method isn't called properly and the reference to other brushes seems to be deleted. As a workaround don't use FreeEntity within the delete() method. Try this instead: SuperStrict Import sidesign.minib3d Type TCube Field X:Int Field Y:Int Field Z:Int Field Entity:TEntity Function create:TCube(x:Int,y:Int,z:Int) Local Cube:TCube = New TCube Cube.X = X Cube.Y = Y Cube.Z = Z Cube.Entity = CreateCube() Cube.Entity.Brush = CreateBrush() PositionEntity Cube.Entity,X,Y,Z Return Cube End Function End Type Graphics3D 800,600,32,1 Local Camera:TCamera = CreateCamera() PositionEntity Camera,0,0,-20 Local Light:TLight = CreateLight() RotateEntity Light,45,45,0 Local CubeList:TList = CreateList() For Local x:Int = 1 To 10 Local Cube:TCube = TCube.Create(Rand(-10,10),Rand(-10,10),Rand(0,10)) CubeList.AddLast(Cube) Next While Not KeyHit(KEY_ESCAPE) Cls RenderWorld Flip If KeyHit(KEY_SPACE) For Local Cube:TCube = EachIn CubeList If Rand(1,4) = 1 FreeEntity(Cube.Entity) CubeList.Remove(Cube) Local Cube2:TCube = TCube.Create(Rand(-10,10),Rand(-10,10),Rand(0,10)) CubeList.AddLast(Cube2) End If Next End If Wend |
| ||
Weird bug. I was hoping to use FreeEntity() in the Delete() method so I could remove a whole block of entities with something like CubeList.Clear(). The only reason why I could see this fail would be if the GC occured during RenderWorld. I tried putting GCCollect() after the FreeEntity() and still had problems. Then I realized how stupid that was, I was calling the Garbage collector during garbage collection. :D So then I tried putting it after CubeList.Remove(Cube). That didn't work either, although it took longer for the program to crash. Is it possible that calling GCCollect() doesn't necessarily collect everything? So if calling FreeEntity() from a delete method is a bad idea, what would be an easy way to remove all the entities from a list? Or am I stuck iterating through the entire list and calling FreeEntity() on each iteration? Just thinking, I could write a function like this: Function RemoveAllEntities(List:TList) For Local Cube:TCube = Eachin List FreeEntity(Cube.Entity) Next List.Clear() End Function Then I could just pass the list to the function and not need to rewrite the loop 20 times everywhere I want to delete a list of entities in my program. |
| ||
GCCollect does try to collect but it does not do that instantan, it takes a few moments and if renderworld happens within this, you are doomed But you could put GCSuspend and GCResume around renderworld |