Exemple #1
0
//******************
// load(const std::string &)
//	Load tree
//	Returns amount of nodes loaded
unsigned long FSModel::load(const std::string & path){
// Will return amount of sub(all)elements
	unsigned long localsize = 0;
	FModel curnode;

/* Set node path and add slash if missing. If on Microsoft Windows, the slash
*	is mandatory too, since we are using a POSIX environment in the first place
*	(Interix / GNUWin / Cygwin / MinGW)
*/	
	curnode.path = path;
	if (path[path.length() - 1] != '/'){
		curnode.path.push_back('/');
	}
// Check valid dir
	if (DIR * dirp = opendir(path.c_str())){
		struct dirent *dp = NULL;
		while (dp = readdir(dirp)){
			try{
			// Load stats, name
				curnode.name = dp->d_name;
				curnode.load(curnode.path + curnode.name);
			// Ignore self, parent
				if (
					(curnode.getname() != ".") &&
					(curnode.getname() != "..") &&
					(curnode.getname() != "./") &&
					(curnode.getname() != "../")
				){
				// If node is a dir, load children
					if (curnode.getisDirectory()){
						localsize += curnode.size = this->load(curnode.fullname);
					}
				// Load node
			// Ordered insertion
					container::iterator inpoint = this->contents.begin();
					for(
						container::iterator end = this->contents.end();
						inpoint != end;
						inpoint++
					){
						if (curnode.fullname < inpoint->fullname){
							break;
						}
					}
					this->contents.insert(inpoint, curnode);
					localsize++;
				}
			}catch (std::runtime_error e){
				std::cerr << e.what() << std::endl;
			}
		}
		closedir(dirp);
	}else{
		throw std::runtime_error(std::string(path) + " not a valid dir");
	}
	this->path = path;
	return localsize;
}
Exemple #2
0
static FModel * FindModel(const char * path, const char * modelfile)
{
	FModel * model;
	FString fullname;

	fullname.Format("%s%s", path, modelfile);
	int lump = Wads.CheckNumForFullName(fullname);

	if (lump<0)
	{
		Printf("FindModel: '%s' not found\n", fullname.GetChars());
		return NULL;
	}

	for(int i = 0; i< (int)Models.Size(); i++)
	{
		if (!stricmp(fullname, Models[i]->filename)) return Models[i];
	}

	int len = Wads.LumpLength(lump);
	FMemLump lumpd = Wads.ReadLump(lump);
	char * buffer = (char*)lumpd.GetMem();

	if (!memcmp(buffer, "DMDM", 4))
	{
		model = new FDMDModel;
	}
	else if (!memcmp(buffer, "IDP2", 4))
	{
		model = new FMD2Model;
	}
	else if (!memcmp(buffer, "IDP3", 4))
	{
		model = new FMD3Model;
	}
	else
	{
		Printf("LoadModel: Unknown model format in '%s'\n", fullname.GetChars());
		delete buffer;
		return NULL;
	}

	if (!model->Load(path, buffer, len))
	{
		delete model;
		delete buffer;
		return NULL;
	}
	model->filename = copystring(fullname);
	Models.Push(model);
	return model;
}
void gl_RenderFrameModels( const FSpriteModelFrame *smf,
						   const FState *curState,
						   const int curTics,
						   const PClass *ti,
						   Matrix3x4 *normaltransform,
						   int translation)
{
	// [BB] Frame interpolation: Find the FSpriteModelFrame smfNext which follows after smf in the animation
	// and the scalar value inter ( element of [0,1) ), both necessary to determine the interpolated frame.
	FSpriteModelFrame * smfNext = nullptr;
	double inter = 0.;
	if( gl_interpolate_model_frames && !(smf->flags & MDL_NOINTERPOLATION) )
	{
		FState *nextState = curState->GetNextState( );
		if( curState != nextState && nextState )
		{
			// [BB] To interpolate at more than 35 fps we take tic fractions into account.
			float ticFraction = 0.;
			// [BB] In case the tic counter is frozen we have to leave ticFraction at zero.
			if ( ConsoleState == c_up && menuactive != MENU_On && !(level.flags2 & LEVEL2_FROZEN) )
			{
				float time = GetTimeFloat();
				ticFraction = (time - static_cast<int>(time));
			}
			inter = static_cast<double>(curState->Tics - curTics - ticFraction)/static_cast<double>(curState->Tics);

			// [BB] For some actors (e.g. ZPoisonShroom) spr->actor->tics can be bigger than curState->Tics.
			// In this case inter is negative and we need to set it to zero.
			if ( inter < 0. )
				inter = 0.;
			else
			{
				// [BB] Workaround for actors that use the same frame twice in a row.
				// Most of the standard Doom monsters do this in their see state.
				if ( (smf->flags & MDL_INTERPOLATEDOUBLEDFRAMES) )
				{
					const FState *prevState = curState - 1;
					if ( (curState->sprite == prevState->sprite) && ( curState->Frame == prevState->Frame) )
					{
						inter /= 2.;
						inter += 0.5;
					}
					if ( (curState->sprite == nextState->sprite) && ( curState->Frame == nextState->Frame) )
					{
						inter /= 2.;
						nextState = nextState->GetNextState( );
					}
				}
				if ( inter != 0.0 )
					smfNext = gl_FindModelFrame(ti, nextState->sprite, nextState->Frame, false);
			}
		}
	}

	for(int i=0; i<MAX_MODELS_PER_FRAME; i++)
	{
		if (smf->modelIDs[i] != -1)
		{
			FModel * mdl = Models[smf->modelIDs[i]];
			FTexture *tex = smf->skinIDs[i].isValid()? TexMan(smf->skinIDs[i]) : nullptr;
			mdl->BuildVertexBuffer();
			gl_RenderState.SetVertexBuffer(mdl->mVBuf);

			mdl->PushSpriteMDLFrame(smf, i);

			if ( smfNext && smf->modelframes[i] != smfNext->modelframes[i] )
				mdl->RenderFrame(tex, smf->modelframes[i], smfNext->modelframes[i], inter, translation);
			else
				mdl->RenderFrame(tex, smf->modelframes[i], smf->modelframes[i], 0.f, translation);

			gl_RenderState.SetVertexBuffer(GLRenderer->mVBO);
		}
	}
}
void gl_InitModels()
{
	int Lump, lastLump;
	FString path;
	int index, surface;
	int i;

	FSpriteModelFrame smf;

	lastLump = 0;

	for(unsigned i=0;i<Models.Size();i++)
	{
		delete Models[i];
	}
	Models.Clear();
	SpriteModelFrames.Clear();
	DeleteModelHash();

	// First, create models for each voxel
	for (unsigned i = 0; i < Voxels.Size(); i++)
	{
		FVoxelModel *md = new FVoxelModel(Voxels[i], false);
		Voxels[i]->VoxelIndex = Models.Push(md);
	}
	// now create GL model frames for the voxeldefs
	for (unsigned i = 0; i < VoxelDefs.Size(); i++)
	{
		FVoxelModel *md = (FVoxelModel*)Models[VoxelDefs[i]->Voxel->VoxelIndex];
		memset(&smf, 0, sizeof(smf));
		smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
		smf.modelIDs[0] = VoxelDefs[i]->Voxel->VoxelIndex;
		smf.skinIDs[0] = md->GetPaletteTexture();
		smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale;
		smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees;
		if (VoxelDefs[i]->PlacedSpin != 0)
		{
			smf.yrotate = 1.f;
			smf.rotationSpeed = VoxelDefs[i]->PlacedSpin / 55.55f;
			smf.flags |= MDL_ROTATING;
		}
		VoxelDefs[i]->VoxeldefIndex = SpriteModelFrames.Push(smf);
		if (VoxelDefs[i]->PlacedSpin != VoxelDefs[i]->DroppedSpin)
		{
			if (VoxelDefs[i]->DroppedSpin != 0)
			{
				smf.yrotate = 1.f;
				smf.rotationSpeed = VoxelDefs[i]->DroppedSpin / 55.55f;
				smf.flags |= MDL_ROTATING;
			}
			else
			{
				smf.yrotate = 0;
				smf.rotationSpeed = 0;
				smf.flags &= ~MDL_ROTATING;
			}
			SpriteModelFrames.Push(smf);
		}
	}

	memset(&smf, 0, sizeof(smf));
	smf.modelIDs[0] = smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
	while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1)
	{
		FScanner sc(Lump);
		while (sc.GetString())
		{
			if (sc.Compare("model"))
			{
				path = "";
				sc.MustGetString();
				memset(&smf, 0, sizeof(smf));
				smf.modelIDs[1] = smf.modelIDs[2] = smf.modelIDs[3] = -1;
				smf.xscale=smf.yscale=smf.zscale=1.f;

				smf.type = PClass::FindClass(sc.String);
				if (!smf.type || smf.type->Defaults == nullptr) 
				{
					sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String);
				}
				sc.MustGetStringName("{");
				while (!sc.CheckString("}"))
				{
					sc.MustGetString();
					if (sc.Compare("path"))
					{
						sc.MustGetString();
						FixPathSeperator(sc.String);
						path = sc.String;
						if (path[(int)path.Len()-1]!='/') path+='/';
					}
					else if (sc.Compare("model"))
					{
						sc.MustGetNumber();
						index = sc.Number;
						if (index < 0 || index >= MAX_MODELS_PER_FRAME)
						{
							sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
						}
						sc.MustGetString();
						FixPathSeperator(sc.String);
						smf.modelIDs[index] = FindModel(path.GetChars(), sc.String);
						if (smf.modelIDs[index] == -1)
						{
							Printf("%s: model not found in %s\n", sc.String, path.GetChars());
						}
					}
					else if (sc.Compare("scale"))
					{
						sc.MustGetFloat();
						smf.xscale = sc.Float;
						sc.MustGetFloat();
						smf.yscale = sc.Float;
						sc.MustGetFloat();
						smf.zscale = sc.Float;
					}
					// [BB] Added zoffset reading. 
					// Now it must be considered deprecated.
					else if (sc.Compare("zoffset"))
					{
						sc.MustGetFloat();
						smf.zoffset=sc.Float;
					}
					// Offset reading.
					else if (sc.Compare("offset"))
					{
						sc.MustGetFloat();
						smf.xoffset = sc.Float;
						sc.MustGetFloat();
						smf.yoffset = sc.Float;
						sc.MustGetFloat();
						smf.zoffset = sc.Float;
					}
					// angleoffset, pitchoffset and rolloffset reading.
					else if (sc.Compare("angleoffset"))
					{
						sc.MustGetFloat();
						smf.angleoffset = sc.Float;
					}
					else if (sc.Compare("pitchoffset"))
					{
						sc.MustGetFloat();
						smf.pitchoffset = sc.Float;
					}
					else if (sc.Compare("rolloffset"))
					{
						sc.MustGetFloat();
						smf.rolloffset = sc.Float;
					}
					// [BB] Added model flags reading.
					else if (sc.Compare("ignoretranslation"))
					{
						smf.flags |= MDL_IGNORETRANSLATION;
					}
					else if (sc.Compare("pitchfrommomentum"))
					{
						smf.flags |= MDL_PITCHFROMMOMENTUM;
					}
					else if (sc.Compare("inheritactorpitch"))
					{
						smf.flags |= MDL_USEACTORPITCH | MDL_BADROTATION;
					}
					else if (sc.Compare("inheritactorroll"))
					{
						smf.flags |= MDL_USEACTORROLL;
					}
					else if (sc.Compare("useactorpitch"))
					{
						smf.flags |= MDL_USEACTORPITCH;
					}
					else if (sc.Compare("useactorroll"))
					{
						smf.flags |= MDL_USEACTORROLL;
					}
					else if (sc.Compare("rotating"))
					{
						smf.flags |= MDL_ROTATING;
						smf.xrotate = 0.;
						smf.yrotate = 1.;
						smf.zrotate = 0.;
						smf.rotationCenterX = 0.;
						smf.rotationCenterY = 0.;
						smf.rotationCenterZ = 0.;
						smf.rotationSpeed = 1.;
					}
					else if (sc.Compare("rotation-speed"))
					{
						sc.MustGetFloat();
						smf.rotationSpeed = sc.Float;
					}
					else if (sc.Compare("rotation-vector"))
					{
						sc.MustGetFloat();
						smf.xrotate = sc.Float;
						sc.MustGetFloat();
						smf.yrotate = sc.Float;
						sc.MustGetFloat();
						smf.zrotate = sc.Float;
					}
					else if (sc.Compare("rotation-center"))
					{
						sc.MustGetFloat();
						smf.rotationCenterX = sc.Float;
						sc.MustGetFloat();
						smf.rotationCenterY = sc.Float;
						sc.MustGetFloat();
						smf.rotationCenterZ = sc.Float;
					}
					else if (sc.Compare("interpolatedoubledframes"))
					{
						smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES;
					}
					else if (sc.Compare("nointerpolation"))
					{
						smf.flags |= MDL_NOINTERPOLATION;
					}
					else if (sc.Compare("skin"))
					{
						sc.MustGetNumber();
						index=sc.Number;
						if (index<0 || index>=MAX_MODELS_PER_FRAME)
						{
							sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
						}
						sc.MustGetString();
						FixPathSeperator(sc.String);
						if (sc.Compare(""))
						{
							smf.skinIDs[index]=FNullTextureID();
						}
						else
						{
							smf.skinIDs[index] = LoadSkin(path.GetChars(), sc.String);
							if (!smf.skinIDs[index].isValid())
							{
								Printf("Skin '%s' not found in '%s'\n",
									sc.String, smf.type->TypeName.GetChars());
							}
						}
					}
					else if (sc.Compare("surfaceskin"))
					{
						sc.MustGetNumber();
						index = sc.Number;
						sc.MustGetNumber();
						surface = sc.Number;

						if (index<0 || index >= MAX_MODELS_PER_FRAME)
						{
							sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
						}

						if (surface<0 || surface >= MD3_MAX_SURFACES)
						{
							sc.ScriptError("Invalid MD3 Surface %d in %s", MD3_MAX_SURFACES, smf.type->TypeName.GetChars());
						}

						sc.MustGetString();
						FixPathSeperator(sc.String);
						if (sc.Compare(""))
						{
							smf.surfaceskinIDs[index][surface] = FNullTextureID();
						}
						else
						{
							smf.surfaceskinIDs[index][surface] = LoadSkin(path.GetChars(), sc.String);
							if (!smf.surfaceskinIDs[index][surface].isValid())
							{
								Printf("Surface Skin '%s' not found in '%s'\n",
									sc.String, smf.type->TypeName.GetChars());
							}
						}
					}
					else if (sc.Compare("frameindex") || sc.Compare("frame"))
					{
						bool isframe=!!sc.Compare("frame");

						sc.MustGetString();
						smf.sprite = -1;
						for (i = 0; i < (int)sprites.Size (); ++i)
						{
							if (strnicmp (sprites[i].name, sc.String, 4) == 0)
							{
								if (sprites[i].numframes==0)
								{
									//sc.ScriptError("Sprite %s has no frames", sc.String);
								}
								smf.sprite = i;
								break;
							}
						}
						if (smf.sprite==-1)
						{
							sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars());
						}

						sc.MustGetString();
						FString framechars = sc.String;

						sc.MustGetNumber();
						index=sc.Number;
						if (index<0 || index>=MAX_MODELS_PER_FRAME)
						{
							sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars());
						}
						if (isframe)
						{
							sc.MustGetString();
							if (smf.modelIDs[index] != -1)
							{
								FModel *model = Models[smf.modelIDs[index]];
								smf.modelframes[index] = model->FindFrame(sc.String);
								if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars());
							}
							else smf.modelframes[index] = -1;
						}
						else
						{
							sc.MustGetNumber();
							smf.modelframes[index] = sc.Number;
						}

						for(i=0; framechars[i]>0; i++)
						{
							char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
							int c = toupper(framechars[i])-'A';

							if (c<0 || c>=29)
							{
								sc.ScriptError("Invalid frame character %c found", c+'A');
							}
							if (map[c]) continue;
							smf.frame=c;
							SpriteModelFrames.Push(smf);
							GetDefaultByType(smf.type)->hasmodel = true;
							map[c]=1;
						}
					}
					else
					{
						sc.ScriptMessage("Unrecognized string \"%s\"", sc.String);
					}
				}
			}
		}
	}

	// create a hash table for quick access
	SpriteModelHash = new int[SpriteModelFrames.Size ()];
	atterm(DeleteModelHash);
	memset(SpriteModelHash, 0xff, SpriteModelFrames.Size () * sizeof(int));

	for (i = 0; i < (int)SpriteModelFrames.Size (); i++)
	{
		int j = ModelFrameHash(&SpriteModelFrames[i]) % SpriteModelFrames.Size ();

		SpriteModelFrames[i].hashnext = SpriteModelHash[j];
		SpriteModelHash[j]=i;
	}
}
static unsigned FindModel(const char * path, const char * modelfile)
{
	FModel * model = nullptr;
	FString fullname;

	fullname.Format("%s%s", path, modelfile);
	int lump = Wads.CheckNumForFullName(fullname);

	if (lump<0)
	{
		Printf("FindModel: '%s' not found\n", fullname.GetChars());
		return -1;
	}

	for(unsigned i = 0; i< Models.Size(); i++)
	{
		if (!Models[i]->mFileName.CompareNoCase(fullname)) return i;
	}

	int len = Wads.LumpLength(lump);
	FMemLump lumpd = Wads.ReadLump(lump);
	char * buffer = (char*)lumpd.GetMem();

	if (!memcmp(buffer, "DMDM", 4))
	{
		model = new FDMDModel;
	}
	else if (!memcmp(buffer, "IDP2", 4))
	{
		model = new FMD2Model;
	}
	else if (!memcmp(buffer, "IDP3", 4))
	{
		model = new FMD3Model;
	}

	if (model != nullptr)
	{
		if (!model->Load(path, lump, buffer, len))
		{
			delete model;
			return -1;
		}
	}
	else
	{
		// try loading as a voxel
		FVoxel *voxel = R_LoadKVX(lump);
		if (voxel != nullptr)
		{
			model = new FVoxelModel(voxel, true);
		}
		else
		{
			Printf("LoadModel: Unknown model format in '%s'\n", fullname.GetChars());
			return -1;
		}
	}
	// The vertex buffer cannot be initialized here because this gets called before OpenGL is initialized
	model->mFileName = fullname;
	return Models.Push(model);
}