trpage_material.cpp

来自「最新osg包」· C++ 代码 · 共 2,011 行 · 第 1/3 页

CPP
2,011
字号
/* ************************   Copyright Terrain Experts Inc.   Terrain Experts Inc (TERREX) reserves all rights to this source code   unless otherwise specified in writing by the President of TERREX.   This copyright may be updated in the future, in which case that version   supercedes this one.   -------------------   Terrex Experts Inc.   4400 East Broadway #314   Tucson, AZ  85711   info@terrex.com   Tel: (520) 323-7990   ************************   */#include <stdlib.h>#include <stdio.h>#include <string.h>/* trpage_material.cpp   This source file contains the methods for trpgMatTable, trpgTextureEnv,   trpgMaterial, and trpgTexTable.   You should only modify this code if you want to add data to these classes.*/#include <trpage_geom.h>#include <trpage_read.h>#ifdef _MSC_VER#define strcasecmp _stricmp#endif/* Write Material Table class   Keeps track of the materials that have been added.*/// ConstructortrpgMatTable::trpgMatTable(){    numTable = numMat = 0;}trpgMatTable::~trpgMatTable(){}// Reset functionvoid trpgMatTable::Reset(){    numTable = 0;    numMat = 0;    materialMap.clear();}// Validity checkbool trpgMatTable::isValid() const{    if(materialMap.size()==0)	return false;    // get an iterator for the materialMap    MaterialMapType::const_iterator itr = materialMap.begin();    for (  ; itr != materialMap.end( ); itr++) {	if(!(*itr).second.isValid()) {	    return false;	}    }    return true;}// Set functionsvoid trpgMatTable::SetNumTable(int no){    if ((no < 0) || (no==numTable))	return;    numTable = no;}void trpgMatTable::SetNumMaterial(int /*no*/){    // This method is obsolete since we're using the project handle    // and a map to store the materials, instead of a vector}void trpgMatTable::SetMaterial(int nm,const trpgMaterial &mat){	    materialMap[nm] = mat;    numMat = materialMap.size();}#define CEQ(ca,cb) (ca.red == cb.red && ca.green == cb.green && ca.blue == cb.blue)int trpgMatTable::AddMaterial(const trpgMaterial &mat,bool lookForExisting){    trpgMaterial cmat = mat; // necessary?	    // having a shadeModel of 999 indicates that the entry is free.  I thought this would    // work fine, until I realized that evidently most of the time the shademodel isn't set    // at all.  Now my kludge takes so much work it's almost worth doing it right.    if (cmat.shadeModel>100) cmat.shadeModel=trpgMaterial::Smooth;    int baseMat=0;    bool spaceInTable=false;	//int offset=baseMat;	    if (lookForExisting) {	// Look for a matching base material minus the textures	//for (baseMat = 0;baseMat < numMat;baseMat++) {	MaterialMapType::const_iterator itr = materialMap.begin();	for (  ; itr != materialMap.end( ); itr++) {	    baseMat = itr->first;	    const trpgMaterial &bm = itr->second;	    if (bm.shadeModel==999) {		// this is an 'empty' entry.  Means we won't find it, either.		spaceInTable=true;		break;	    }	    // Compare structures	    if (CEQ(cmat.color,bm.color) && CEQ(cmat.ambient,bm.ambient) &&		CEQ(cmat.diffuse,bm.diffuse) && CEQ(cmat.specular,bm.specular) &&		CEQ(cmat.emission,bm.emission) && cmat.shininess == bm.shininess &&		cmat.shadeModel == bm.shadeModel && cmat.pointSize == bm.pointSize &&		cmat.lineWidth == bm.lineWidth && cmat.cullMode == bm.cullMode &&		cmat.alphaFunc == bm.alphaFunc && cmat.alphaRef == bm.alphaRef &&		cmat.attrSet.fid == bm.attrSet.fid && cmat.attrSet.smc == bm.attrSet.smc &&		cmat.attrSet.stp == bm.attrSet.stp && cmat.attrSet.swc == bm.attrSet.swc &&		cmat.autoNormal == bm.autoNormal && cmat.texEnvs.size() == bm.texEnvs.size()) {		// Test the texture envs		bool isSame=true;                unsigned int i;		for (i=0;i<cmat.texEnvs.size();i++) {					const trpgTextureEnv &e1 = cmat.texEnvs[i];		    const trpgTextureEnv &e2 = bm.texEnvs[i];		    if (e1.envMode != e2.envMode ||			e1.minFilter != e2.minFilter ||			e1.magFilter != e2.magFilter ||			e1.wrapS != e2.wrapS || e1.wrapT != e2.wrapT ||			!CEQ(e1.borderCol,e2.borderCol))			isSame = false;		}		// Test the texture IDs		for (i=0;i<cmat.texids.size();i++) {		    if (cmat.texids[i] != bm.texids[i])			isSame = false;		}		if (isSame)		    return baseMat;	    }	}    }    // Didn't find it.  Add it    int idx;    if(cmat.writeHandle)	idx = cmat.GetHandle();    else	idx = numMat;    materialMap[idx] = cmat;    numMat = materialMap.size();    return idx;}// Write out material tablebool trpgMatTable::Write(trpgWriteBuffer &buf){	if (!isValid())		return false;	buf.Begin(TRPGMATTABLE);	// Total number of materials	buf.Add((int32)numTable);	buf.Add((int32)numMat);	// Write the materials	MaterialMapType::const_iterator itr = materialMap.begin();	for (  ; itr != materialMap.end( ); itr++) {		((trpgMaterial)(*itr).second).Write(buf);	}	buf.End();	return true;}/* ************	Material Table Read   ***********   */// Get functionsbool trpgMatTable::GetNumTable(int &no) const{	if (!isValid()) {		no = 0; // otherwise this causes errors because it is uninitialized.			return false;	}	no = numTable;	return true;}bool trpgMatTable::GetNumMaterial(int &no) const{	if (!isValid()) {		no = 0;			return false;	}		no = numMat;	return true;}bool trpgMatTable::GetMaterial(int nt,int nm,trpgMaterial &mat) const{    if (!isValid()) return false;	MaterialMapType::const_iterator itr = materialMap.find((nt*numMat)+nm);	if(itr == materialMap.end())		return false;    mat = (*itr).second;    return true;}const trpgMaterial *trpgMatTable::GetMaterialRef(int nt,int nm) const{	MaterialMapType::const_iterator itr = materialMap.find((nt*numMat)+nm);	if(itr == materialMap.end())		return false;	return const_cast<trpgMaterial *>(&(*itr).second);}bool trpgMatTable::Read(trpgReadBuffer &buf){	trpgMaterial mat;	trpgToken matTok;	int32 len;	bool status;	int i,j;	int nMat,nTable;	try {		buf.Get(nTable);		buf.Get(nMat);		if (nTable <= 0 || nMat < 0) throw 1;		// Read the materials		for (i=0;i<nTable;i++)			for (j=0;j<nMat;j++) {				buf.GetToken(matTok,len);				if (matTok != TRPGMATERIAL) throw 1;				buf.PushLimit(len);				mat.Reset();				status = mat.Read(buf);				buf.PopLimit();				if (!status) throw 1;				AddMaterial(mat,false);							}			numTable += nTable;			numMat = materialMap.size();	}	catch (...) {		return false;	}	return isValid();}/* Write Texture Environment class	Used to specify how a texture is applied.	Associated with materials.	*/// ConstructortrpgTextureEnv::trpgTextureEnv(){	Reset();}trpgTextureEnv::~trpgTextureEnv(){}// Reset functionvoid trpgTextureEnv::Reset(){	envMode = Decal;	minFilter = Linear;	magFilter = MipmapBilinear;	wrapS = wrapT = Repeat;	borderCol = trpgColor(0,0,0);}bool trpgTextureEnv::isValid() const{    return true;}// Set functionsvoid trpgTextureEnv::SetEnvMode(int mode){    envMode = mode;}void trpgTextureEnv::SetMinFilter(int fl){    minFilter = fl;}void trpgTextureEnv::SetMagFilter(int fl){    magFilter = fl;}void trpgTextureEnv::SetWrap(int s,int t){    wrapS = s;    wrapT = t;}void trpgTextureEnv::SetBorderColor(const trpgColor &col){    borderCol = col;}// Write functionbool trpgTextureEnv::Write(trpgWriteBuffer &buf){    if (!isValid())	return false;    buf.Begin(TRPGMAT_TEXENV);    buf.Begin(TRPGMAT_TXENV_MODE);    buf.Add(envMode);    buf.End();    buf.Begin(TRPGMAT_TXENV_FILTER);    buf.Add(minFilter);    buf.Add(magFilter);    buf.End();    buf.Begin(TRPGMAT_TXENV_WRAP);    buf.Add(wrapS);    buf.Add(wrapT);    buf.End();    buf.Begin(TRPGMAT_TXENV_BORDER);    buf.Add(borderCol);    buf.End();    buf.End();    return true;}/* **************   Texture Env Read support   **************   */// Get functionsbool trpgTextureEnv::GetEnvMode(int32 &ret) const{    if (!isValid()) return false;    ret = envMode;    return true;}bool trpgTextureEnv::GetMinFilter(int32 &ret) const{    if (!isValid()) return false;    ret = minFilter;    return true;}bool trpgTextureEnv::GetMagFilter(int32 &ret) const{    if (!isValid()) return false;    ret = magFilter;    return true;}bool trpgTextureEnv::GetWrap(int &S,int &T) const{    if (!isValid()) return false;    S = wrapS;    T = wrapT;    return true;}bool trpgTextureEnv::GetBorderColor(trpgColor &col) const{    if (!isValid()) return false;    col = borderCol;    return true;}/* Texture Env CB   Used to parse tokens for a texture Env.*/class textureEnvCB : public trpgr_Callback {public:    void *Parse(trpgToken,trpgReadBuffer &);    trpgTextureEnv *tenv;};void * textureEnvCB::Parse(trpgToken tok,trpgReadBuffer &buf){    int envMode;    int minFilter;    int magFilter;    int wrapS,wrapT;    trpgColor borderCol;    try {	switch (tok) {	case TRPGMAT_TXENV_MODE:	    buf.Get(envMode);	    tenv->SetEnvMode(envMode);	    break;	case TRPGMAT_TXENV_FILTER:	    buf.Get(minFilter);	    buf.Get(magFilter);	    tenv->SetMinFilter(minFilter);	    tenv->SetMagFilter(magFilter);	    break;	case TRPGMAT_TXENV_WRAP:	    buf.Get(wrapS);	    buf.Get(wrapT);	    tenv->SetWrap(wrapS,wrapT);	    break;	case TRPGMAT_TXENV_BORDER:	    buf.Get(borderCol);	    tenv->SetBorderColor(borderCol);	    break;	default:	    // Don't know this token.  Skip	    break;	}    }    catch (...) {	return NULL;    }    return tenv;}bool trpgTextureEnv::Read(trpgReadBuffer &buf){    trpgr_Parser parse;    textureEnvCB teCb;    // Texture environment is a bunch of tokens in random order    // Interface to it with a parser    teCb.tenv = this;    parse.AddCallback(TRPGMAT_TXENV_MODE,&teCb,false);    parse.AddCallback(TRPGMAT_TXENV_FILTER,&teCb,false);    parse.AddCallback(TRPGMAT_TXENV_WRAP,&teCb,false);    parse.AddCallback(TRPGMAT_TXENV_BORDER,&teCb,false);    parse.Parse(buf);    return isValid();}/* Write Material class   Material representation.*/// ConstructortrpgMaterial::trpgMaterial(){    Reset();}trpgMaterial::~trpgMaterial(){}// Reset functionvoid trpgMaterial::Reset(){    color = trpgColor(1,1,1);    ambient = trpgColor(0,0,0);    diffuse = trpgColor(1,1,1);    specular = trpgColor(0,0,0);    emission = trpgColor(0,0,0);    shininess = 0;    shadeModel = 999; // kludge to identify 'empty' material table entries    pointSize = 1;    lineWidth = 1;    cullMode = Back;    alphaFunc = GreaterThan;    alphaRef = 0;    alpha = 1.0;    autoNormal = false;    numTex = 0;    texids.resize(0);    texEnvs.resize(0);    numTile = 0;    isBump = false;    attrSet.fid = -1;    attrSet.smc = -1;    attrSet.stp = -1;    attrSet.swc = -1;    handle = -1;    writeHandle = false;}// Validity checkbool trpgMaterial::isValid() const{    // Only thing we really care about is texture    if (numTex < 0)	return false;    for (int i=0;i<numTex;i++)	if (!texEnvs[i].isValid())	    return false;    return true;}// Set functionsvoid trpgMaterial::SetColor(const trpgColor &col){    color = col;}void trpgMaterial::SetAmbient(const trpgColor &col){    ambient = col;}void trpgMaterial::SetDiffuse(const trpgColor &col){    diffuse = col;}void trpgMaterial::SetSpecular(const trpgColor &col){    specular = col;}void trpgMaterial::SetEmission(const trpgColor &col){    emission = col;}void trpgMaterial::SetShininess(float64 val){    shininess = val;}void trpgMaterial::SetShadeModel(int val){    shadeModel = val;}void trpgMaterial::SetPointSize(float64 val){    pointSize = val;}void trpgMaterial::SetLineWidth(float64 val){    lineWidth = val;}void trpgMaterial::SetCullMode(int val){    cullMode = val;}void trpgMaterial::SetAlphaFunc(int val){    alphaFunc = val;}void trpgMaterial::SetAlphaRef(float64 val){    alphaRef = val;}void trpgMaterial::SetAlpha(float64 val){    alpha = val;}void trpgMaterial::SetAutoNormal(bool val){    autoNormal = val;}void trpgMaterial::SetNumTexture(int no){    if (no < 0)	return;    numTex = no;    texids.resize(no);    texEnvs.resize(no);}void trpgMaterial::SetTexture(int no,int id,const trpgTextureEnv &env){    if (no < 0 || (unsigned int)no >= texids.size())	return;    texids[no] = id;    texEnvs[no] = env;}int trpgMaterial::AddTexture(int id,const trpgTextureEnv &env){    texids.push_back(id);    texEnvs.push_back(env);    numTex++;    return numTex-1;}void trpgMaterial::SetNumTiles(int no){    numTile = no;}int trpgMaterial::AddTile(){    return(++numTile);}void trpgMaterial::SetIsBumpMap(bool val){    isBump = val;}void trpgMaterial::SetAttr(int attrCode,int val){    switch (attrCode) {    case TR_FID:	attrSet.fid = val;	break;    case TR_SMC:	attrSet.smc = val;	break;    case TR_STP:	attrSet.stp = val;	break;    case TR_SWC:	attrSet.swc = val;	break;    }    return;}// Write to bufferbool trpgMaterial::Write(trpgWriteBuffer &buf){    if (!isValid())	return false;    buf.Begin(TRPGMATERIAL);    // Bundle the basic material parameters together    buf.Begin(TRPGMAT_BASIC);    buf.Add(color);    buf.Add(ambient);    buf.Add(diffuse);    buf.Add(specular);    buf.Add(emission);    buf.Add(shininess);    buf.Add(numTile);    buf.End();    // Most everything else is a single token.    // This is inefficient, but expandable    buf.Begin(TRPGMAT_SHADE);    buf.Add(shadeModel);    buf.End();    buf.Begin(TRPGMAT_SIZES);    buf.Add(pointSize);    buf.Add(lineWidth);    buf.End();    buf.Begin(TRPGMAT_CULL);    buf.Add(cullMode);    buf.End();    buf.Begin(TRPGMAT_ALPHA);    buf.Add(alphaFunc);    buf.Add(alphaRef);    buf.Add(alpha);    buf.End();    buf.Begin(TRPGMAT_NORMAL);    buf.Add((int32)autoNormal);    buf.End();    buf.Begin(TRPGMAT_TEXTURE);    buf.Add(numTex);    for (int i=0;i<numTex;i++) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?