Is this method as efficient as possible?

Blitz3D Forums/Blitz3D Beginners Area/Is this method as efficient as possible?

ColeE(Posted 2016) [#1]
I'm trying to hide entities that aren't visible to increase frame rate, and it increases it a significant amount, but not to the point I'd like it to. I've never written I method like this before, so I don't efficient way to do it, any suggestions?

Function cull()
	For x = 1 To xSize%+3
		For y = 1 To ySize% + 3
			If grid3%(x, y) = 4 Then Goto nextIteration
			If EntityDistance(cam, entityGrid(x, y, 0))> 41*wallThickness#+1 Then
				HideEntity entityGrid(x, y, 0)
				If grid3%(x, y) = 0 Or grid3%(x, y) = 5 Then HideEntity entityGrid(x, y, 1)
			Else 
				ShowEntity entityGrid(x, y, 0)
				If grid3%(x, y) = 0 Or grid3%(x, y) = 5 Then ShowEntity entityGrid(x, y, 1)
			EndIf
			.nextIteration
		Next
	Next
End Function


Would it be better to free and re-create the entities? Or something totally different altogether? Because these entities are placed in a grid, could I use that to my advantage?

The didstance at which I have the entities hidden is the CameraFogRange btw


Kryzon(Posted 2016) [#2]
Hello.
If you are using fog you can also set the CameraRange far value to be the same as the fog far, if you haven't done that already -- if the object is fully within fog the camera shouldn't have to worry about it.

Another change that might do some difference is that since you're just doing a comparison between distances you can compare the squared distances -- the effect is the same and you don't have to use EntityDistance (which involves a square root, a potentially expensive operation).

Something like this...
Local distX# = EntityX( entityGrid( x, y, 0 ), True ) - EntityX( cam, True )
Local distY# = EntityY( entityGrid( x, y, 0 ), True ) - EntityY( cam, True )
Local distZ# = EntityZ( entityGrid( x, y, 0 ), True ) - EntityZ( cam, True )

Const MAXIMUM_DISTANCE_SQUARED# = ( 41 * wallThickness + 1 ) ^ 2

If ( distX*distX + distY*distY + distZ*distZ ) > MAXIMUM_DISTANCE_SQUARED Then
	HideEntity( ... )
I'm not sure if it's a quantifiable improvement, you should profile it.


ColeE(Posted 2016) [#3]
That's an interesting way to look at it. It's cool to see the clever thing people come up with, even if simple. Thanks.


Guy Fawkes(Posted 2016) [#4]
Question though. What's the value for the wallThickness? ;)

~GF


ColeE(Posted 2016) [#5]
It's 3 as I currently have it set. It's the thickness of each of my cubes. Essentially my map is made of blocks, sort of like a corn maze, with the blocks being corn... kinda
I remembered that I already put CameraRange at the max CameraFogRange value, but it made the places where I should see fog black...


ColeE(Posted 2016) [#6]
I think the problem is that fog stops at the horizon, which is why even with the method I have, I sometimes see gaps in the distance :/


RemiD(Posted 2016) [#7]
Some others suggestions to decrease the mstime it takes to render the 3dscene :
->Use copies of a premade entity (with copyentity) rather than creating several different meshes or using copymesh.
->for the static entities which are near enough, try to merge them in one mesh one surface with one texture
->for the turningmoving entities, try to have for each entity one mesh one surface with one texture (if they are identical, use copyentity)
->if possible use zones in which you put static entities (which can never change of zone) and turningmoving entities (which can change of zone). Set each entity which is in the zone as a child of the zone. And each frame hide all zones (and this will hide all the childs entities), determine in which zone the player is, and only update and show the zone where player is and the zones connected to this zone (and this will show all the childs entities of these zones).
For example, you could have 10x10zones on a 100x100units map... (and update and show only the zone where player is and the zones adjacent to this zone)
Or you could have arbitrary shaped zones connected with passages... (and update and show only the zone where player is and the zones connected to this zone)


Omnicode(Posted 2016) [#8]
One method i've used a couple of times is like the grid RemiD talked about.

The map was designed around accessing a 2D array to determine what should be rendered within a certain distance to the Camera. The origin for this distance calc needed me to convert Global Coords into a range x>=0 and y>=0 (as you can't have <0 array position). Avoids squares, any calculus, and is easier to understand. The only limiter for the map being you CANT have Negative Player XZ coords. X->X and Z->Y

You broke up the map into some sort of standard UNIT, you used 3? A 3x3 area makes up a 1x1 unit and a 30x30 area makes up a Zone.

Meaning:
Each Zone is 10x10 but is 30x30 units in global coords
Each Unit is 1x1 but is 3x3 units in global coords

Note: 3 is the scale factor in this example, could be much larger like 16 who knows.

Now determining what units should be displayed.
Convert From Global Coords To Array Grid Format

What Zone Am I In?
Dim Zone_Data$(1,1)
Zone_Data$(0,0)="Town Of Beginnings"
Zone_Data$(0,1)="Hyrule"
Zone_Data$(1,0)="Vonherin"
Zone_Data$(0,1)="River Euclid"
Zone_Data$(1,1)="Great Plains"
;...etc

Global_Zone_X=EntityX(Camera_Entity)/30 
Global_Zone_Z=EntityZ(Camera_Entity)/30


What Unit Within The Zone Am I In?
Dim Unit_Data(10,10)
Unit_Data$(0,0)="LIST OF STUFF IN THIS PIECE OF MAP, CONTAINS MAYBE MODEL NAMES.. -> Functions As A Text-Based Pseudo-Thread?"

Global_ZoneUnit_X=EntityX(Camera_Entity)/3
Global_ZoneUnit_Z=EntityZ(Camera_Entity)/3


Grab The Center Of The Zone
Current_Zone_X=(Global_Zone_X*15)
Current_Zone_Z=(Global_Zone_Z*15)
If Abs(Zones_Needed_To_Be_Loaded_X-Current_Zone_X)<=View_Distance
   If Abs(Zones_Needed_To_Be_Loaded_Z-Current_Zone_Z)<=View_Distance
      ;LOAD THIS ZONE
   Endif
Endif



Note: The code above is but a concept, some of my math may be off. Also, the method where I used this was for a dungeon crawler. Eventually it was expanded into a 3 dimension array (for additional floors being rendered at a time) Worked quite well. Goodluck


Guy Fawkes(Posted 2016) [#9]
You should really make a demo, oh "wise one" depicting your theory. If you have a theory, step up to the plate & prove it. Otherwise, "SCREW YOU GUYS! I'M GOOOOOOOOOOOOIN' HOOOOOOOOOOOOOME!" =D

~GF


ColeE(Posted 2016) [#10]
Is it more efficient to copy cubes made with CreateCube()? Or should I only worry about copying with more advanced meshes like my robots?


RemiD(Posted 2016) [#11]
@GF>>Nobody owes you anything...


@ColeE>>Yes, it is better to create only one cube and use copyentity() to create a copy of the cube (if the cubes are identical with the same material/texture).

What i do is that, at the start of the program, i load premade meshes (with premade textures) and i hide them, and when i need to create an entity with the same shape and same colors, i use copyentity(xmesh)


Guy Fawkes(Posted 2016) [#12]
@RemiD: Don't be a dick. Either contribute or leave. I'm not going to tell you again. If you don't stop being a jerk, I'm going to PURPOSELY become the old me again and tear you a new ***.


Omnicode(Posted 2016) [#13]
CopyEntity is a pretty fast routine from what i've dabbled with and is typically faster than creation routines.


RemiD(Posted 2016) [#14]

Don't be a dick. Either contribute or leave. I'm not going to tell you again. If you don't stop being a jerk, I'm going to PURPOSELY become the old me again and tear you a new ***.



@GF>>You are not a moderator so don't tell me what to do or not do, i don't care. And if you reread my posts and your posts you will see who is the one with an impolite behavior... I repeat : nobody owes you anything.
And personally, i prefer that people describe their methods with words so that i can understand it and then implement my own version with my own code (what you seem to have difficulties to do)


ColeE(Posted 2016) [#15]
Alright cool, I'll try that and see if it speeds up my game a little.

If someone doesn't mind looking at this unrelated function, that would be good, it slows down my game ALOT and it doesn't seem like it should to me. numBots% changes depending on the layout of my procedurally generated map, but it is normally less than 100, and with my current max map size, likely not over 50, so the number of iterations isn't huge. The cull function does 2704 iterations per call, and one call per frame, and has only a slight impact on framerate...

This function is also called once per frame.



Thanks.

(I just realized I've been calling Functions methods, I'm used to talking about java, I caught myself just before I posted this.) :)


RemiD(Posted 2016) [#16]
@ColeE>>after a quick look, 2 simple improvements you can do is to use 2 temporary variables to store the distance3d value and the deltayaw value and only do the calculation once and then use the variables to do the checks ( if( tdisantec3d/tdeltayaw <=> ) )


ColeE(Posted 2016) [#17]
Alright, but do those functions really take that much time?


Cocopino(Posted 2016) [#18]
@ColeE
A trick that could help is a counter that increases on every iteration of your main loop. Find the bottlenecks in your program, then ask yourself: do I really need to run this piece of code every frame or can I skip it sometimes? Separate the really important stuff from the less important stuff like:
'main loop
	counter++
	updateExtremelyImportantStuff
	if counter mod 2 = 0 updateVeryImportantStuff
	if counter mod 3 = 0 updateImportantStuff
	if counter mod 5 = 0 updateLessImportantStuff
	if counter mod 7 = 0 
		updateEvenLessImportantStuff
		counter = 0
	endif
'end main loop


Edit: What happens in enemyShoot(bot(i))?


Guy Fawkes(Posted 2016) [#19]
RemiD, stfu. I'm DONE with your smart-ass comments. Don't talk to me again. Alls you do is harass me. I'm SICK and TIRED of the way people treat other people.


ColeE(Posted 2016) [#20]
enemyShoot(bot(i)) was just there for testing purposes. Now its in a condition in that loop so that it only happens every .6 seconds and when the robot is close enough. It shoots a bullet sprite(500x500 pixels, does the size affect framerate?) from the robot. I'm going to use a counter for it though, I like that solution, and this way it will fire at a speed relative to the framerate.

Btw, are there alternatives to EntityInView()? Thanks for all the help.


Guy Fawkes(Posted 2016) [#21]
Size only affects frame rate if it's way too big, or there's too many within the same area of each other. (Too many being a responsible cap of around 50,000 or so sprites all within a 20 foot radius of each other).

~GF

P.S.

An alternative to EntityInView ( ) would be linepick & collision. If the Z-linepick hits an object, then that would indicate that not only can the object collide with the hit object, but it can also see the other object.

EntityPickMode ( myent, 2, 1 ) ;The one is to enable "obscurer" so that the linepick only hits objects it can "see".

~GF


ColeE(Posted 2016) [#22]
Alright, is LinePick faster?


Guy Fawkes(Posted 2016) [#23]
Not sure. But it's pretty fast to me it seems.

~GF


ColeE(Posted 2016) [#24]
Alright, thx


RemiD(Posted 2016) [#25]

I'm SICK and TIRED of the way people treat other people.


@GF>>I agree, reread your previous posts...


Cocopino(Posted 2016) [#26]
EntityInView should be much faster than Linepick.

You can locate the exact problem by using something like:
function SuspiciousFunction()
	local time1 = Millisecs()

	'function code
	
	debuglog Millisecs() - time1
end function

and narrow it down from there.


RemiD(Posted 2016) [#27]
Something important if you use entityinview : make sure that your meshes are clean (no orphan vertices far from the origine of the mesh), because the function checks if one of the "vertex" of the bounding box is/isnot in the camera fov...


Cocopino(Posted 2016) [#28]
@ColeE

I just now read 500x500 pixels for a sprite, that's a pretty large bullet sprite. Also, it's not a power of 2 which is a good rule of thumb to follow for textures.
What happens if you resize it (I mean manually, before loading it into your program) to 128x128 or even 64x64?


RemiD(Posted 2016) [#29]
Also for texturedsprites/texturedquads it is probably faster to render masked texels (flag 4) than variable alpha texels (flag 2) (not tested but it makes sense that there are less calculations involved with masked texels (alpha0 texels))


Guy Fawkes(Posted 2016) [#30]
Yea. At least I admit it! I used to be that way, but I've changed! I now see it as a waste of my time & effort to fight against sheeple like you.

~GF