Preloading game content

Blitz3D Forums/Blitz3D Programming/Preloading game content

ZaroSath(Posted 2013) [#1]
Hello, i'm actually from the realmcrafter community.. i'm not sure how the blitz community regards it but suffice it to say its shit, i'm running through the code and want to improve it for fun, maybe even make it usable.. i know blitzbasic is at least.

before going over the spawning/deletion process, i'd like to know if it's possible to preload character models and use them when spawning and removing characters?

in a nutshell, when a character is displayed/removed, its loaded in realtime and that can be very problematic for gameplay if the model is too large, the solution people over at the realmcrafter community have is to just work around it and use character models small enough to not notice any load times, while this works it does not fix the problem and forces less detail in the artwork.

i realize there are limits to how much detail blitzbasic is capable of but this is ridiculous.


GfK(Posted 2013) [#2]
You can load a 3D model and hide it with HideEntity. So it'll exist, but will not be visible and not be involved in any collision checking.

After that you can just make copies with CopyEntity, rather than loading the same thing over and over.


ZaroSath(Posted 2013) [#3]
thanks, that is just what i was looking for. :)

do you know if it will affect performance if there is a lot of content hidden?

edit: on second thought, i suppose it would be no different than the total amount of content you can already load with blitz3d into the game without bad fps


Yasha(Posted 2013) [#4]
Hidden content doesn't get used at all for rendering, so it should have no noticeable effect on performance until you start running out of memory altogether.

It's worth pointing out that CopyEntity is doubly useful because it caches and shares mesh and texture data - if you copy the same character 20 times, only one mesh actually gets created. This is a lot faster than loading or creating 20 of the same mesh.

(Not to be confused with CopyMesh, which actually does copy the mesh data and is mainly useful if you want a copy of the mesh that you intend to modify in some way, without having the modifications affect the original.)


RemiD(Posted 2013) [#5]
If you want to use the same meshes with the same materials ("brushes" in Blitz3d), you want to use CopyEntity().

If you want to use the same meshes but you want to deform the mesh to add some variations, or you want to change the materials, you want to use CopyMesh().

HideEntity() and ShowEntity() will work with both.


ZaroSath(Posted 2013) [#6]
thats really useful but i've got a problem.

i'm having trouble using CopyMesh() so that i can use different materials later, could somebody provide an example?


Yasha(Posted 2013) [#7]
Depends on what kind of problems you're having and what you mean by "materials" (note that "material" is not a formal B3D engine term so it could mean a few different things)...

There are actually two different places brushes and textures - which I assume is what you mean by "material" - can be applied in B3D. They can be attached to the entity, and also to a mesh's surfaces. To understand the difference you need to be familiar with how the B3D mesh and entity system works.

The short version is that an entity is a logical construct that has a few parameters (position, size, etc), and also owns resources (such as a surface made up of verts and tris). When you use CopyEntity on a mesh, a new entity with all of the same properties is created as the original - and these properties include which surfaces it has ownership of (ownership of surfaces can be shared); whereas when you use CopyMesh, all of the mesh properties are copied (so new surfaces are created). Now the important part is that both entities and surfaces have a "brush" parameter, so you can retexture a copied entity without affecting the original as long as you use EntityTexture or PaintEntity instead of PaintSurface (which would affect the brush properties of the surface, which it shares with the original and any other copies).

So if all you want to do is change the colour, texture, shininess etc., you still don't need to use CopyMesh - those properties exist at the entity level and don't need to affect surface data. (In fact it's rare to use the surface versions when the entity versions will do - just means extra difficulty later if you want to share surfaces.)


EDIT: To be more accurate, CopyMesh deep-copies the mesh data but doesn't copy anything else. Animation data is lost (as are textures, colour...). Whether you can recover it or not depends on what kind of animation you're using - if it's a .B3D, you can't easily transfer this at all (it's not intended to be copied like this - animated .B3D meshes only work properly with CopyEntity).


ZaroSath(Posted 2013) [#8]
Edit: oh ok, i think i understand.. i'll see what i can do.

thank you for the prompt response :)


Yue(Posted 2013) [#9]
Local Mesh% = CreateCube()
HideEntity Mesh%
Local Mesh2% = CopyMesh(Mesh%)
Local Texture% = CreateTexture(256,256)
EntityTexture Mesh2%,Texture%



ZaroSath(Posted 2013) [#10]
i realize this is a lot of code at a time but is there something wrong with this?

i'm trying to PaintEntity rather than PaintSurface but i'm getting a memory access violation when using it

		FaceTex = A\FaceTex
		If A\Actor\MaleFaceIDs[FaceTex] = 65535 And FaceTex > 0 Then FaceTex = 0
		BodyTex = A\BodyTex
		If A\Actor\MaleBodyIDs[BodyTex] = 65535 And BodyTex > 0 Then BodyTex = 0
		If CountSurfaces(A\EN) > 1 And A\Actor\MaleFaceIDs[FaceTex] < 65535
			; Find which surface is body
			B = GetSurfaceBrush(GetSurface(A\EN, 1)) : T = GetBrushTexture(B)
			Name$ = TextureName$(T)
			FreeTexture T : FreeBrush(B)
			; Default way round
			FaceSurface = GetSurface(A\EN, 2)
			BodySurface = GetSurface(A\EN, 1)
			; Should be the other way round
			If Instr(Upper$(Name$), "HEAD") > 0
				FaceSurface = GetSurface(A\EN, 1)
				BodySurface = GetSurface(A\EN, 2)
			Else
				B = GetSurfaceBrush(GetSurface(A\EN, 2)) : T = GetBrushTexture(B)
				Name$ = Upper$(TextureName$(T))
				FreeTexture T : FreeBrush(B)
				; A texture is assigned which is not one of the dummy textures, check if it's a body texture
				If Instr(Name$, "HEAD") = 0
					For i = 0 To 4
						Name2$ = Upper$(GetTextureName$(A\Actor\MaleBodyIDs[i]))
						If Name2$ <> ""
							Name2$ = Left$(Name2$, Len(Name2$) - 1)
							If Instr(Name$, Name2$)
								FaceSurface = GetSurface(A\EN, 1)
								BodySurface = GetSurface(A\EN, 2)
								Exit
							EndIf
						EndIf
					Next
				EndIf
			EndIf

			; Paint
			B = CreateBrush()
			Tex = GetTexture(A\Actor\MaleBodyIDs[BodyTex])
			If Tex <> 0
				BrushTexture(B, Tex)
				PaintEntity(BodySurface, B)
			EndIf
			Tex = GetTexture(A\Actor\MaleFaceIDs[FaceTex])
			If Tex <> 0
				BrushTexture(B, Tex)
				PaintEntity(FaceSurface, B)
			EndIf
			FreeBrush(B)
			UnloadTexture(A\Actor\MaleBodyIDs[BodyTex])
			UnloadTexture(A\Actor\MaleFaceIDs[FaceTex])
		Else
			Tex = GetTexture(A\Actor\MaleBodyIDs[BodyTex])
			If Tex <> 0 Then EntityTexture(A\EN, Tex)
			UnloadTexture(A\Actor\MaleBodyIDs[BodyTex])
		EndIf


thanks :D


ZaroSath(Posted 2013) [#11]
after reading up on the manual, it may be caused because it is trying to paint an entity rather than the entities mesh surface.. any easy way around this? i need to texture a specific surface.


RemiD(Posted 2013) [#12]
Usually, to paint the surfaces of a mesh with different materials (brushes), i do something like this :




ZaroSath(Posted 2013) [#13]
Now the important part is that both entities and surfaces have a "brush" parameter, so you can retexture a copied entity without affecting the original as long as you use EntityTexture or PaintEntity instead of PaintSurface (which would affect the brush properties of the surface, which it shares with the original and any other copies).


i cant use PaintSurface ;) i was looking for a way to paint a specific surface using entitytexture or paintentity


ZaroSath(Posted 2013) [#14]
i've tried

head = FindChild(A\EN, "Head")
TextureEntity(head, Texture)


but TextureEntity (or PaintEntity) still causes a memory violation.. can i get some help here? ;)


RemiD(Posted 2013) [#15]
What do you want to do exactly ?

"TextureEntity()" does not exist in Blitz3d (at least this command is not in my Blitz3d docs)
Try EntityTexture() instead.

I don't know if it is possible to retrieve a surface reference by using FindChild() so i can't say.
Normally i use FindChild() to retrieve joints (bones).
I use GetSurface() to retrieve surfaces, as shown in my previous code example.

If it is possible to retrieve a surface reference with FindChild(), you can use DebugLog() or Print() to check if the variable head has retrieved a reference or nothing
head = FindChild(A\EN, "Head")
Debuglog("head reference = "+head) ;or Print("head reference = "+head)


If the head reference is equal to 0, it means that no reference has been retrieved, so if you try to do anything with head, it will cause a mav.

Another possible reason is that the head reference does not correspond to a mesh or a surface but to a pivot/joint and it cannot be textured.


ZaroSath(Posted 2013) [#16]
yeah i typed EntityTexture wrong.

if you read my previous posts, you would know what i'm talking about.

it does find the surface but my problem is i get a memory access violation (mav) when i actually try texturing it without paintsurface, whether with PaintEntity or EntityTexture, identifying the surface with findchild or getsurface, i'm unable to texture the surface without using paintsurface.


RemiD(Posted 2013) [#17]

it does find the surface but my problem is i get a memory access violation (mav) when i actually try texturing it without paintsurface, whether with PaintEntity or EntityTexture, identifying the surface with findchild or getsurface, i'm unable to texture the surface without using paintsurface.


Maybe it is because the reference corresponds to a surface, not to a mesh.


ZaroSath(Posted 2013) [#18]
"after reading up on the manual, it may be caused because it is trying to paint an entity rather than the entities mesh surface.. any easy way around this? i need to texture a specific surface. "

tell me something i dont know :P

again, i need a way to texture a specific surface without replacing the original texture because EntityCopy() shares that stuff.

PaintSurface() unfortunately will change the shared copy.


Yasha(Posted 2013) [#19]
Took me a few reads to get what you meant here...

PaintSurface is for surfaces. PaintEntity is for entities. They are not interchangeable because entities and surfaces are completely different things. The crash itself is straightforward: passing a surface when an entity is expected will break because you're passing the wrong data.

You can't paint a shared surface and have it not affect other uses of the surface. The entire point of surfaces is that they're monolithic: any change to the surface will affect all uses of it. The entire point of having a second brush application point in the containing entity is to solve this problem, by removing the attributes from the shared memory object.

The intuitive solution is that you should redesign the model to suit what you want to do with it - in this case, make 'head' an actual child mesh rather than just a surface. (CopyEntity also copies the child hierarchy.) That way you can use the entity painting commands on it and not affect other instances, because it will have another layer of brush abstraction separate from the one built into the surface proper.

(It's also perfectly possible to code up a solution that would take a mesh and factor surfaces out into child meshes, but it's usually poor design to let your data control your code in this way, so make the change to the actual mesh in your editor program if that's an option, and keep your program code simpler.)


ZaroSath(Posted 2013) [#20]
hmm.. as i'm trying to design this for a established realmcrafter community standard of using surfaces rather than a child mesh, its a bit conflicting but it appears using a child mesh is likely the best solution.

as i'm not very knowledgeable in modeling, could you tell me if it is as simple as setting a surface or would i need to make a completely different mesh? (and would that be a completely different file, or just another object inside the modeling program)

i want you to know i really appreciate your Help Yasha, you add lucidity to my problems ;)