/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Ofstream.h" #include "mg/Ifstream.h" #include "mgGL/Material.h" #include "mgGL/RenderAttr.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // //Implements MGRenderAttr Class. //MGRenderAttr defines the attributes of rendering attributes. //These attrubutes are not used for drawing(line drawing mode). //copy constructor. MGRenderAttr::MGRenderAttr(const MGRenderAttr& attr) :MGGLAttrib(attr.m_flag),m_color(attr.m_color){ MGRenderAttr* attr2=const_cast(&attr); m_material=attr2->m_material; attr2->m_material=0; m_back_material=attr2->m_back_material; attr2->m_back_material=0; } //Destructor. MGRenderAttr::~MGRenderAttr(){ delete m_material; delete m_back_material; } //Assignment. MGRenderAttr& MGRenderAttr::operator=(const MGRenderAttr& attr){ if(this==&attr) return *this; MGGLAttrib::operator=(attr); MGRenderAttr* attr2=const_cast(&attr); m_color=attr.m_color; delete m_material; m_material=attr2->m_material; attr2->m_material=0; delete m_back_material; m_back_material=attr2->m_back_material; attr2->m_back_material=0; return *this; } MGRenderAttr& MGRenderAttr::operator=(const MGGel& gel2){ const MGRenderAttr* gel2_is_this=dynamic_cast(&gel2); if(gel2_is_this) operator=(*gel2_is_this); return *this; } bool MGRenderAttr::operator<(const MGRenderAttr& gel2)const{ return m_flag(&gel2); if(gel2_is_this) return operator<(*gel2_is_this); return false; } //////////Member Function////////// //Generate a newed clone object. MGRenderAttr* MGRenderAttr::clone()const{ return new MGRenderAttr(*this); } //Invoke appropriate OpenGL fucntion to this attribute. void MGRenderAttr::exec(mgVBO& vbo)const{ RENDERSIDE rs=render_side(); glPolygonMode(rs, GL_FILL); if(m_material){ if(rs==FRONT_AND_BACK) glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); else glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); if(rs==BACK) glFrontFace(GL_CW); else glFrontFace(GL_CCW); if(rs==FRONT || rs==BACK) m_material->exec(FRONT); else if(m_back_material){ m_material->exec(FRONT); m_back_material->exec(BACK); }else m_material->exec(FRONT_AND_BACK); } if(m_color.disabled()){ }else if(!m_color.undefined()){ m_color.exec(vbo); } } ///Set this attribute as color shading and set the color. ///When colr.disabled(), will be changed to undefined(). void MGRenderAttr::set_color_shading(const MGColor& colr){ m_color=colr; if(m_color.disabled()) m_color.set_undefined(); } //Set material. void set_material_data( MGMaterial*& material, const float ambient[3], const float diffuse[3], const float specular[3], const float emission[3], float shininess, float transparency ){ if(!material){ material=new MGMaterial(ambient,diffuse,specular,emission,shininess,transparency); }else{ material->setAmbientColor(ambient); material->setDiffuseColor(diffuse); material->setSpecularColor(specular); material->setEmissiveColor(emission); material->setShininess(shininess); material->setTransparency(transparency); } } bool MGRenderAttr::material_defined()const{ if(!m_material) return false; return true; } //Set the material. When rs=FRONT_AND_BACK and different material for the back side //is used, set_back_material must be invoked after invoking set_material. //Else the same material will be appllied for the both sides. void MGRenderAttr::set_material( RENDERSIDE rs, const float ambient[3], const float diffuse[3], const float specular[3], const float emission[3], float shininess, float transparency ){ set_render_side(rs); set_material_data(m_material, ambient,diffuse,specular,emission,shininess,transparency); delete m_back_material; m_back_material=0; } //Set the back side material. Invoking set_back_material means two sided material //and setting different material to the back side. //Before use of set_back_material, set_material must be invoked first. //set_back_material will set two sided material. //set_material must be invoked before invoking set_back_material. //Else the same material will be appllied for the both sides. void MGRenderAttr::set_back_material( const float ambient[3], const float diffuse[3], const float specular[3], const float emission[3], float shininess, float transparency ){ assert(m_material);//must be defined. set_render_side(FRONT_AND_BACK); set_material_data(m_back_material, ambient,diffuse,specular,emission,shininess,transparency); } //Return the material pointer of the back side when this has the two sided rendering //(FRONT_AND_BACK) and the different materials are applied to each side. //NULL will be returned when render_side()!=FRONT_AND_BACK. //Even when render_side()==FRONT_AND_BACK, if m_back_material==null(the same material //is applied to both side), null will be returned. const MGMaterial* MGRenderAttr::back_material()const{ if(render_side()!=FRONT_AND_BACK) return 0; return m_back_material; } //Debug Function. std::ostream& MGRenderAttr::out(std::ostream& ostrm)const{ ostrm<out(ostrm); if(back_material()) ostrm<<",Back Material=";m_back_material->out(ostrm); } return ostrm; } // Serialization. //Write all member data void MGRenderAttr::WriteMembers(MGOfstream& buf)const{ MGGLAttrib::WriteMembers(buf); if(undefined()) return; m_color.WriteMembers(buf); if(m_material){ buf<<0xffffffffL; //The header that indicates an MGMaterial object is followed. buf<<(*m_material); }else{ //When null pointer. buf<<0x00000000L; } if(m_back_material){ buf<<0xffffffffL; //The header that indicates an MGMaterial object is followed. buf<<(*m_back_material); }else{ //When null pointer. buf<<0x00000000L; } } void MGRenderAttr::ReadMembers(MGIfstream& buf){ MGGLAttrib::ReadMembers(buf); if(undefined()) return; m_color.ReadMembers(buf); long addr; buf>>addr; if(addr){ m_material=new MGMaterial(); buf>>(*m_material); }else{ //When null pointer. m_material=0; } buf>>addr; if(addr){ m_back_material=new MGMaterial(); buf>>(*m_back_material); }else{ //When null pointer. m_back_material=0; } } //Turn on the appropriate mask bit for this attribute. See glPushAttrib(). void MGRenderAttr::set_draw_attrib_mask(unsigned int& mask)const{ set_Amask(mask,LIGHTING_BIT); } //Turn on the appropriate mask bit for this attribute. See glPushAttrib(). void MGRenderAttr::set_render_attrib_mask(unsigned int& mask)const{ set_Amask(mask,LIGHTING_BIT); } //Turn off the appropriate mask bit for this attribute. See glPushAttrib(). void MGRenderAttr::reset_render_attrib_mask(unsigned int& mask)const{ reset_Amask(mask,LIGHTING_BIT); } ///Test if this defines color shading(returns true) or texture shading(returns false). bool MGRenderAttr::is_color_shading()const{ if(m_color.disabled()) return false; return true; } ///Test if this defines texture shading(returns true) or color shading(returns false). bool MGRenderAttr::is_texture_shading()const{ if(m_color.disabled()) return true; return false; }