News:

One Minute Game Review by The Happy Friar: https://ugetube.com/@OneMinteGameReviews
Also on Rumble: https://rumble.com/c/c-1115371

idTech 4 (aka Doom 3 tech) Discord Server! https://discord.gg/9wtCGHa

Main Menu

LOD system

Started by argoon, November 23, 2016, 10:08:21 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

argoon

Hello guys i made a LOD system for my mod using script and it works, more or less, the lod change works the problem i'm getting is that when the model changes it shivers for a moment and is very obvious, do you guys have any idea on how to smooth that transition?

here is the script code


/***********************************************************************

lod_object_base.script

self script contains any LOD's specific code.

revision = 0.1

***********************************************************************/


#define LOD_LEVEL_0 1
#define LOD_LEVEL_1 2
#define LOD_LEVEL_2 3

object lod_object_base {
// bool to control the while loop
    boolean isON;

// lod0 position for the other lod's
vector currObjPos;

float currentLOD;

string lod0_model;
string lod1_model;
string lod2_model;


// player entity
entity lod_player;

// enable or disable the LOD check, no need to do it on objects with no lod's
float lod_enabled;

// show distances
float lod1_dis;
float lod2_dis;
// player distance from lod object
float pldistance;



void init();

void lodUpdate();
void checkLOD();

};


void lod_object_base::checkLOD() {

pldistance = self.distanceTo(lod_player); // check lod obj pos distance to player1 pos

if( pldistance < lod1_dis && currentLOD != LOD_LEVEL_0 ){
currentLOD = LOD_LEVEL_0;
self.setModel(lod0_model);
}
else if ( pldistance >= lod1_dis && pldistance < lod2_dis && currentLOD != LOD_LEVEL_1 ){
currentLOD = LOD_LEVEL_1;
self.setModel(lod1_model);
}
else if ( pldistance >= lod2_dis && currentLOD != LOD_LEVEL_2 ){
currentLOD = LOD_LEVEL_2;
self.setModel(lod2_model);
//self.setKey("noShadows", "1"); doesn't work at runtime :(
}
}

/*
============
lod_object_base::lodUpdate
============
*/
void lod_object_base::lodUpdate() {

lod_enabled = self.getIntKey("lod"); // get the spawn lod value

// if spawnarg lod is 0 disable the while loop
if(lod_enabled == 0){
isON = false;
}

// gets the lod0 world position
currObjPos = self.getWorldOrigin();

// not run this on the loop or it will not work.
currentLOD = LOD_LEVEL_2;

// get the models can be set on the editor if using the def key "editor_model"
lod0_model = self.getKey("model");
lod1_model = self.getKey("model_lod1");
lod2_model = self.getKey("model_lod2");
// then get lod distance values
lod1_dis = self.getIntKey("lod1_distance");
lod2_dis = self.getIntKey("lod2_distance");

// this gets the player entity
    lod_player = sys.getEntity("player1");


// runtime loop to check for the player position and set the lod objs
while ( isON ){ // while isON == true
if( lod_enabled ){ // if lod0 has the spawnarg lod_enabled with value 1 then run if not stop
checkLOD();
}
waitFrame();
}
}

/*
===============
initialisation
================
*/

void lod_object_base::init()
    {
waitFrame();
isON = true;
thread lodUpdate();
    }

The Happy Friar

Model switching should be instantious, not sure what you mean by a "shiver."

argoon

#2
Yes is true is instantaneous, when i said shivers is not really accurate is more it flickers like the material gets lighter then darker again, will try to make a video and show it.

Ok here is a video.

https://drive.google.com/open?id=0B_xD8k_3dkNpa053MXFiRUhwREk

The Happy Friar

looks to me like for a game frame the model dissapears & the new one appears the frame after, so there's a blank model there.   Or the models are in the same space & some kind of fighting going on there.

Try using the avidemo/game command @ 60fps & it might be easier to see if it's having a blank space or fighting visually.  com_avidemotics 4 should record the demo @ 60fps.

argoon

#4
Thanks for the hint, yes the models are in the same space, they should be i'm just swapping the visual model for the entity, visually they are the same object but with LOD levels (less geometry for the lod1 and lod2), i will go experiment with that command and see what i find, thanks for the help. :)


edit- Yep you were right there's indeed a empty frame between the model swaps, when swamping to different unrelated models is not obvious but when used on a real LOD it is, how can i solve that? Is the waitFrame() command doing that in the loop?

Btw was unable to use the aviDemo command, add to use Fraps, the recordDemo worked but the aviDemo that makes the TGA images from the .demo just crashed, always, i'm using fhdoom.

The Happy Friar

I use stock D3, not fhdoom, so I'm not sure if avidemo/game works in there.

I think Motorsep got a working LOD system in his D3BFG engine, not 100% sure though.

What it looks like it's doing is it's removing the existing model & replacing it with another, with that slight pause.  I'm guessing that is because the "setmodel" command changes the entitiys model, but takes a frame to process.

If a model with a nodraw material on it doesn't use any CPU resources, what might be a better idea is to have all the models actually be one model & change the model's skin from nodraw to what it should be.  That might solve the issue.

Another could be to use a separate entity for each model & hide/show as needed.

argoon

#6
QuoteAnother could be to use a separate entity for each model & hide/show as needed.

This doesn't work as well also causes flickering, it seams doomscript is just to slow for this.  :-\

code


/***********************************************************************

lod_object_base.script

self script contains any LOD's specific code.

***********************************************************************/


#define LOD_LEVEL_0 1
#define LOD_LEVEL_1 2
#define LOD_LEVEL_2 3

object lod_object_base {
// bool to control the while loop
    boolean isON;

// enable or disable the LOD check, no need to do it on objects with no lod's
float lod_enabled;

// lod0 position and rotation for the other lod's
vector currObjPos;
vector currObjRot;

// var to control the LOD_LEVEL_x static vars
float currentLOD;

entity lod1;
entity lod2;

string lod1_name;
string lod2_name;

// show distances
float lod1_dis;
float lod2_dis;

// player entity
entity lod_player;

// player distance from lod object
float pldistance;



void init();

void        lodSetup();
void        lod0_Show();
void        lod0_Hide();
void lodUpdate();
void checkLOD();

};

void lod_object_base::lod0_Show(){
self.show();
}

void lod_object_base::lod0_Hide(){
self.hide();
}

void lod_object_base::lodSetup(){
// to be able to spawn a new object i need to get its name, from lod0 def file, as a string,
// for that i use the getkey() function
// then use sys.spawn to spawn the object using that string as a name.
lod1_name = self.getKey("def_LOD1");
lod1 = sys.spawn(lod1_name);
lod1.setWorldOrigin(currObjPos); // makes the lod1 obj have the same position as lod0
lod1.setAngles(currObjRot); // makes the lod1 obj have the same Rotation as lod0
lod1_dis = self.getIntKey("lod1_distance"); // gets from lod0 the lod1 spawnarg show distance
lod1.hide();

lod2_name = self.getKey("def_LOD2");
lod2 = sys.spawn(lod2_name);
lod2.setWorldOrigin(currObjPos);
lod2.setAngles(currObjRot);
lod2_dis = self.getIntKey("lod2_distance");
lod2.hide();
}

/*
============
lod_object_base::checkLOD
============
*/

void lod_object_base::checkLOD()
{

pldistance = self.distanceTo(lod_player); // check lod obj pos distance to player1 pos

if( pldistance < lod1_dis && currentLOD != LOD_LEVEL_0 ){
currentLOD = LOD_LEVEL_0;
lod0_Show();
lod1.hide();
lod2.hide();
}
else if ( pldistance >= lod1_dis && pldistance < lod2_dis && currentLOD != LOD_LEVEL_1 ){
currentLOD = LOD_LEVEL_1;
lod0_Hide();
lod1.show();
lod2.hide();
}
else if ( pldistance >= lod2_dis && currentLOD != LOD_LEVEL_2  ){
currentLOD = LOD_LEVEL_2;
lod2.show();
lod1.hide();
lod0_Hide();
}

}


/*
============
lod_object_base::lodUpdate
============
*/
void lod_object_base::lodUpdate() {

    /////////////////////// LOD's setup
lod_enabled = self.getIntKey("lod"); // get the spawn lod value

// if spawnarg lod is 0 disable the while loop, saves performance
if(lod_enabled == 0){
isON = false;
}

// gets the lod0 world position and rotation
currObjPos = self.getWorldOrigin();
currObjRot = self.getAngles();

currentLOD = LOD_LEVEL_2;

// spawn the lod entities
lodSetup();

// this gets the player entity but is redundant, we could simple use $player1
    lod_player = sys.getEntity("player1");


// runtime loop to check for the player position and spawn the lod objs
while ( isON ){ // while isON == true
checkLOD();
sys.waitFrame();
}
}


/*
===============
initialisation
================
*/

void lod_object_base::init()
    {
sys.waitFrame();
isON = true;
thread lodUpdate();
    }


The Happy Friar

no, it's not to slow.  I've done similar things before via script.  (the video attached).

I'm wondering now if it's a flaw in the custom D3 engine you're using.

argoon

Thanks for the help The Happy Friar but unfortunately this happens with vanilla Doom 3 has well,  the video you posted shows very fast model change indeed but i'm unable to replicate here, perhaps it is because i'm also running a frob check (while loop with a traceline) every frame slowing everything down, need to test disabling the frob script.

motorsep

Quote from: The Happy Friar on November 25, 2016, 05:16:03 PM
I think Motorsep got a working LOD system in his D3BFG engine, not 100% sure though.

We did. Can be easily ported into fhDoom I believe.

The Happy Friar

Quote from: argoon on November 28, 2016, 12:27:33 PM
Thanks for the help The Happy Friar but unfortunately this happens with vanilla Doom 3 has well,  the video you posted shows very fast model change indeed but i'm unable to replicate here, perhaps it is because i'm also running a frob check (while loop with a traceline) every frame slowing everything down, need to test disabling the frob script.

Wouldn't need to do it every frame, maybe even have it check different distances at different frames.  IE closes one every two frame, furthest every 10 frames?

Quote from: motorsep on November 28, 2016, 01:39:46 PM
Quote from: The Happy Friar on November 25, 2016, 05:16:03 PM
I think Motorsep got a working LOD system in his D3BFG engine, not 100% sure though.
We did. Can be easily ported into fhDoom I believe.

Or that.  :)

argoon

Quote from: The Happy Friar on November 28, 2016, 09:23:44 PM
Quote from: argoon on November 28, 2016, 12:27:33 PM
Thanks for the help The Happy Friar but unfortunately this happens with vanilla Doom 3 has well,  the video you posted shows very fast model change indeed but i'm unable to replicate here, perhaps it is because i'm also running a frob check (while loop with a traceline) every frame slowing everything down, need to test disabling the frob script.

Wouldn't need to do it every frame, maybe even have it check different distances at different frames.  IE closes one every two frame, furthest every 10 frames?

Quote from: motorsep on November 28, 2016, 01:39:46 PM
Quote from: The Happy Friar on November 25, 2016, 05:16:03 PM
I think Motorsep got a working LOD system in his D3BFG engine, not 100% sure though.
We did. Can be easily ported into fhDoom I believe.

Or that.  :)

Man this is frustrating i disabled the frob script and my lod system still flickers, and the fps's are above 60 proving that performance is not the problem, perhaps i'm doing something wrong? Is my script missing something? I'm i doing it wrong? Do i need to mess with threads? I don't really understand threads for now.  Could it be because I'm running the mod from a external HDD? But i'm not really spawning anything at run time!? Could the waitframe() be causing the blank frame? Logically it sounds like it, because it makes the loop wait a frame, but when i remove it i get a engine crash with a loop error.

The Happy Friar thank you for your input, i don't really know at the moment how to do what you say but i will try.

About the Motorsep LOD system unfortunately, i don't think eXistence will port it to fhdoom anytime soon and i don't want to mess with the engine source for now, is beyond my coding capacities i'm having problems with doomScript imagine C++.   ;D :P 

The Happy Friar

Does your script work by itself it does it need specific assets?  Could anyone test it out w/o extra content?

argoon

If you want to test then you don't need specific models just use this model def's with any model.  :)


entityDef LOD_base{
    "inherit"   "func_static"
"scriptobject"    "lod_object_base" // name of the lod script
"spawnclass"   "idStaticEntity"

"editor_usage" "LOD enabled entity objects"
"editor_usage1" "def_LOD models most have model name with _lodx sufix"
"editor_var lod1_distance" "distance to show lod1 object"
"editor_var lod2_distance" "distance to show lod2 object"
"editor_bool lod" "set to 1 to enable lod for this entity."
"editor_var def_LOD1"            "chose model def object to be lod1 object"
"editor_var def_LOD2"           "chose model object def to be lod1 object"
"editor_var noShadows"          "disable shadows used mostly for last lod"

"lod"                   "1" // enables or disables the LOD system
"lod1_distance"    "300"
"lod2_distance" "600"
"noShadows" "0"
}

entityDef LOD_testObj {
"inherit" "LOD_base"
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 0"
"editor_maxs" "16 16 32"

"editor_usage" "LOD enabled test object - NOT USE"
"editor_var lod1_distance" "distance to show lod1 object"
"editor_var lod2_distance" "distance to show lod2 object"
"editor_var def_LOD1"            "chose model def object to be lod1 object"
"editor_var def_LOD2"           "chose model object def to be lod2 object"


"model" "lod0 model path"
"def_LOD1" "LOD_testObj_lod1"
"def_LOD2" "LOD_testObj_lod2"
         
          "lod1_distance"    "300"
"lod2_distance" "600"
}

entityDef LOD_testObj_lod1 {
"inherit" "func_static"
"editor_usage" "LOD enabled test object - NOT USE"
"model" "lod1 model path"
}

entityDef LOD_testObj_lod2 {
"inherit" "func_static"
"editor_usage" "LOD enabled test object - NOT USE"
"model" "lod2 model path"
"noShadows" "1"
}


Even tho i already changed the script somewhat you can still use the last script i posted or the first with the setmodel system all display the same behavior on my PC.

VGames

So what kind of FPS boost do you get from this?
Get the latest on Perfected Doom 3 here - http://www.moddb.com/mods/perfected-doom-3-version-500