Jump to content
  • Advertisement
Sign in to follow this  
bilsa

bad design for Materials ?

This topic is 5472 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey everyone! I'm currently designing a material system. But I'm a little worried that maybe my material class is badly designed :/ I'm very fond of OOP and when I program I strive for "modularity" and make a system easy to update and maintain. So this is how I have thought:
class ITechniqueProperties {
public:
};

class IMaterialTechnique {
public:
	//Sets different states for a renderer... like glColor3f ... glBindTexture...
	virtual void PrepareRenderer(IRenderer* pRenderer) = 0;
	//Gets the propertys for a technique, like the texture data if Texture diffuse material 
	//or color data for ColorDiffuse. This Data can be used for sorting...
	//so materials with same properties are called only once...
	virtual ITechniqueProperties* GetProperties() = 0;
};

class IMaterial {
public:
	//Sets different states for a renderer... like glColor3f ... glBindTexture...
	virtual void PrepareRenderer(IRenderer* pRenderer) = 0;
	//Different techniques for this material, eg. use Texture as diffuse or a single color
	virtual void SetTechnique(IMaterialTechnique* pTechnique) = 0;
	//Gets the technique...
	virtual IMaterialTechnique* GetTechnique() = 0;
};

//Example of a material
class DiffuseMaterial : public IMaterial {
public:
	virtual void PrepareRenderer(IRenderer* pRenderer) {
		m_pTechnique->PrepareRenderer(pRenderer);
	}
	virtual void SetTechnique(IMaterialTechnique* pTechnique) {
		m_pTechnique = pTechnique;
	}
	virtual IMaterialTechnique* GetTechnique() {
		return m_pTechnique;
	}
protected:
	IMaterialTechnique* m_pTechnique;
};

//Example of a DiffuseMaterial technique
class DiffuseColorTechnique : public IMaterialTechnique {
public:
	//The propertys of a diffuse color material = simply the colors
	class DiffuseColorTechniqueProperties : public ITechniqueProperties {
	public:
		DiffuseColorTechniqueProperties(float red, float green, float blue, float alpha) : r(red), g(green), b(blue), a(alpha) {}
		float r, g, b, a;
	};

	DiffuseColorTechnique(DiffuseColorTechniqueProperties* pDiffueseProperties) : m_pDiffueseProperties(pDiffueseProperties) {}
	//Prepare the renderer => Set the colors to use for rendering
	virtual void PrepareRenderer(IRenderer* pRenderer) {
		//pRenderer->SetColorRGBA(m_pDiffueseProperties->r, m_pDiffueseProperties->g, m_pDiffueseProperties->b, m_pDiffueseProperties->a);
	}

	//Return the properties, could be used for sorting
	virtual ITechniqueProperties* GetProperties() {
		return m_pDiffueseProperties;
	}
private:
	DiffuseColorTechniqueProperties* m_pDiffueseProperties;
};

so this could be used like this: //Choose a technique... in this case a solid color for Diffuse material IMaterialTechnique* pDiffuseMaterialTechnique = new DiffuseColorTechnique(1.0f, 0.0f, 0.0f, 0.5f); //Set the technique in the Diffuse material IMaterial* pMaterial = new DiffuseMaterial( pDiffuseMaterialTechnique ); The problem I'm strugling with is when I want to find out what properties a Material has. For eg maybe I want to check what texture the material uses: ITechniqueProperties* pMaterialProperties = pMaterial->GetTechnique()->GetProperties(); But this ITechniqueProperties is just a base class containing no useful data, even though it points to relevant data. Would it be considered bad design to have some kind of RTTI system here to identify what type of material it is and thus identify the Data that we need for sorting? like: DiffuseColorTechnique* pDiffuseColorTechnique = dynamic_cast<DiffuseColorTechnique*>(pMaterial->GetTechnique()); if(pDiffuseColorTechnique != 0) { pDiffuseColorTechnique->GetColorProperties(); //... } Do you guys get the point? Would this be concidered bad design or would it be acceptable? How would you guys do this? Thx!

Share this post


Link to post
Share on other sites
Advertisement
maybe rather than using "real" RTTI, use a custom simpler
version by haveing a "type" identifier in the base class


enum eMType {
M_UNDEFINED,
M_DIFFUSE,
M_SPECULAR,
M_ANISOTRIPIC,
// etc. etc.
};
class BaseType {
private:
eMType type;
public:
const eMType getType() const { return type; }
BaseType(eMType ty) : type(ty) {}
};




then when you derive a class:

class DiffuseMaterial : public BaseType {
public:
DiffuseMaterial() : BaseType(eMType::M_DIFFUSE) {}
}




one thing you might notice is that basetype dosn't have a
default constructor with no arguments, this may help your system by:
A. preventing creation of non-pointer vars of BaseType (protects against interface abuse)
B. forces you to set a type whenever you derive a new material

this can be modified pretty easily and saves you having to use
RTTI to determin the type of a material, dynamic_cast can be
expensive if used excessivly.

Hope that helps.

Cheers,
Danu

Share this post


Link to post
Share on other sites
Yeh, thx. I was also thinking about something like that. But currently I have a custom rtti system which actually is only twice as slow as returning an int like you did there. So
I'll be using that if an rtti system is acceptable in this
situation. :)

Share this post


Link to post
Share on other sites
If using that enum eMType I would have to recompile when adding a new type right?

If using classes, there is no need for recompile.

Anyway, would appreciate some more tips!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!