• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

3D Best way to store external 3d models RAM?

V

Vikom

Guest
Hi!
I have a dilema about storing 3d models in my game.
I'm making a game that will contain a variety of 3d models like buildings, cars, trees... so, I believe I should approach it in a clever way. I have an universal "obj_building" object who's instances load external models.

The first idea was quite simple: just use a string to define a way to load the external model. It works quite well - easy implementation but it needs unnecessary amount of RAM when every instance stores the model.

The second idea is: there's one instance (object "models") that stores all the models and the instance that needs a model, loads it from there like... model = models.familyhouse3;
I've tried it and the RAM is much better.

The problem is, I don't know how to store it effectively.
My idea was that the "models" object would store them this way...
Code:
familyhouse1 = d3d_model_create();
familyhouse2 = d3d_model_create();
...
store1= d3d_model_create();
store2= d3d_model_create();
and the "obj_building" would have a string var with a name of the model and somehow converted the string into var's name like...
Code:
modelname = "familyhouse1";
model = models.str_to_var(modelname);     //model = models.familyhouse1;
The problem is, I found nothing like the "str_to_var".
Also, now the "models" would have to load all the models right at the beginning of the game which would cause an unnecessarily long loading time in case of higher numbers.

Do you have any idea how to solve it or even a better idea how to reach it?

Maybe I got one while writing this but I'll have to think about it first how to make it. I'll let you know and eventually explain it.

Still, I'll be happy for any suggestions.
 
W

warenhuis

Guest
Depending on how large the map is, you could consider only loading models within viewing range and unloading models that were loaded earlier but no longer inside the viewing range.
This only works if you have a way to guarantuee that certain models will not be visible in the distance (think of distance fog, or an elevated horizon, etc.).
An alternative is to use low-resolution versions of models in the distance, which would also require less memory.

Also forgive me if I misunderstood this, but why do you use strings instead of variables directly?
Why can't it be:
Code:
model = models.familyhouse1;     //model = models.familyhouse1;
 

sylvain_l

Member
If you can don't store your 3d data in all your instances of obj_building, that will duplicate a lot of 3D infos

edit: yeh, I overcomplicate the thing; @warenhuis is right just ref the instance var

use a ds_map in your models instance to store the models

Code:
my_ds_map[? "familyhouse1"] = ...
etc...


and in your obj_building you just store the key of the my_ds_map that is:
Code:
modelname = "Family house 1";
modelkey = "familyhouse1";
than
in the drawing you'll just ref to the right 3D info
Code:
...
draw the models.my_ds_map[? modelkey]
...
 
V

Vikom

Guest
Sorry, forgot to mention few important things.
I made/I'm making a built in map editor for the game, so the models for the buildings are determined right in the game.
The map is planned to be infinite...I'll explain. The map is meant to be split into small regions (500x500m) and only the actual region and the ones surrounding this one would be loaded. The rest will be deleted. All the regions would be saved in the game folder.

I was thinking that every region would have an "obj_region" instance which would store only the building models used in the specific region. My idea was to "pair" the buildings with the "obj_region" and use the models like (simplified code)
Code:
myregion = instance_nearest(x, y, obj_region);
d3d_model_draw(myregion.familyhouse1, x, y, 0, txt);
Surprisingly, this had the lowest FPS (tried with 100 identical buildings at once)
But it still sounds in theory like the best idea for me, I'll give it another try.

Why using strings while loading the models?
Every building has its own folder which contains model, textures, 3d details...
The folder with the model building folders contains an .ini file that contains info about number of the folders and names of every of them.
In the built in map editor, when you choose the model, it reads the .ini and shows a list of the models to chose from. It worked with the model for every instance...reads name from the .ini and adds it to the way to the model ("Models\Buildings\Houses\"+string(modelname)+"\model.txt").
I found it to be a bad idea to store the models in "higher instances" as 'model[і]' rather than 'familyhouse1' but it doesn't cooperate with the reading name from .ini.
 
W

warenhuis

Guest
Code:
modelname = familyhouse1;
model = models.modelname;     //model = models.familyhouse1;
Why not use the variables for referencing inside the game and convert the variable name to a string for the folders?
You can simply convert a variable name to a string using string(modelname) which you can then use to construct the path name such as ("Models\Buildings\Houses\"+string(modelname)+"\model.txt"), so there shouldn't be a problem there.

On top of only drawing the regions you need, you should make sure that you don't draw the hidden polygons. Make sure that any polygon outside of the viewport is not drawn (outside of the so-called camera frustum) and that d3d_set_culling() is set to true when you draw closed shapes (such as most buildings) and false when you draw flat surfaces that need to be visible from both sides (such as simple leafes) - this requires that the model has calculated normals. This won't reduce the amount of RAM needed but should dramatically improve the framerate.
 
Last edited by a moderator:
V

Vikom

Guest
No fear, I know about culling.

I'm not sure if I understand correctly.
The obj_region has...
d3d_model_load(familyhouse1, "Models\Buildings\Houses\familyhouse1\model.txt");

and the obj_building has...
modelname = ini_read... //in result modelname = "familyhouse1"

I want to draw the model using 'model = myregion.familyhouse1', if I know right, I can't do 'model = myregion."familyhouse1" ' and I know no better way than...
if modelname == "familyhouse1" then model = myregion.familyhouse1;

Sorry if I misunderstood you.
 
W

warenhuis

Guest
Yeah, I don't see why that would be a bad idea, especially since you'll only use it for choosing model types in some sort of edit mode. You can even do it in scriptform.
Code:
model = scr_model( "familyhouse1")
scr_model:
Code:
switch argument0
{
case "familyhouse1": return myregion.familyhouse1; break;
case "familyhouse2": return myregion.familyhouse2; break;
//etc..
case "store1": return myregion.store1; break;
case "store2": return myregion.store2; break;
//etc..
default: return 'unknown modeltype';
}
 
V

Vikom

Guest
Ok, it doesn't look as bad as I thought.
Since I was introduced the for cycle (and while, of course), I believed that everything like this case can be done by repeating or without using the specific values.

I'll use it.
Thank you for your help.
 
Top