/********************************************************************/ /* 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/Color.h" #include "mgGL/Appearance.h" #include "mgGL/Light.h" #include "mgGL/LineStipple.h" #include "mgGL/LineWidth.h" #include "mgGL/Lights.h" // //Define MGAppearance Class. //MGAppearance is a class to contain MGGLAttrib objects. //MGAppearance acts just like as std::auto_ptr. //That is, MGAppearance holds newed object pointers of MGGLAttrib, //and when copy constructor or assignment operator is invoked, //the pointer ownership is transfered to the new MGAppearance object. MGAppearance& MGAppearance::operator=(const MGAppearance& gel2){ if(this==&gel2) return *this; m_glattribs=gel2.m_glattribs; m_no_display=gel2.m_no_display; return *this; } MGAppearance& MGAppearance::operator=(const MGGel& gel2){ const MGAppearance* gel2_is_this=dynamic_cast(&gel2); if(gel2_is_this) operator=(*gel2_is_this); return *this; } bool MGAppearance::operator<(const MGAppearance& gel2)const{ int n1=size(), n2=gel2.size(); if(n1==n2){ return int(this)(&gel2); if(gel2_is_this) return operator<(*gel2_is_this); return false; } //Add a light. light must be a newed object, and the ownership will be //transfered to this object. //Function's return value is the number of lights after added. int MGAppearance::add_light(MGLight* light){ iterator i=search_by_id(MGLIGHTS_TID); MGLights* lights; if(i==end()){ lights=new MGLights; push_back(lights); }else lights=static_cast(*i); lights->push_back(light); return lights->size(); } //Test if this MGAppearance can be removed or not. bool MGAppearance::can_be_removed()const{ return (size()==0 && !no_display()); } //Generate copied gel of this gel. //Returned is a newed object. User must delete the object. MGAppearance* MGAppearance::clone()const{ MGAppearance* appr2=new MGAppearance; const_iterator i=begin(), ie=end(); for(; i!=ie; i++){ MGAttrib* attri=static_cast((**i).clone()); appr2->push_back(attri); } appr2->m_no_display=m_no_display; return appr2; } std::ostream& MGAppearance::out( std::ostream& ostrm )const{ ostrm<<"MGAppearance="<(*i); if(gla){ if(no_color && gla->is_highlight_attrib()) continue; gla->drawAttrib(vbo); } } } //Release the specified attribute. //Function's return value is the MGGLAttrib* that is released. MGGLAttrib* MGAppearance::release_attrib(long tid){ iterator i=begin(), ie=end(); for(;i!=ie; i++){ if((*i)->identify_type()==tid){ MGGLAttrib* gla=static_cast(*i); m_glattribs.release(i); return gla; } } return 0; } //render GLAttributes process. void MGAppearance::render(mgVBO& vbo)const{ if(no_display()) return; const_iterator i=begin(), ie=end(); for(;i!=ie; i++){ const MGGLAttrib* gla=dynamic_cast(*i); if(gla) gla->render(vbo); } } //Set the attribute in this list. attr must be a newed object, and the //ownership will be transfered to this MGAppearance. void MGAppearance::set_attrib(MGGLAttrib* attr){ MGGLAttrib* olda=set_attrib_with_old(attr); if(olda) delete olda; } void MGAppearance::set_attrib(MGGLAttribs& attrs){ int n=(int)attrs.size(); for(int i=0; i(*i); iterator j=m_glattribs.release(i); insert(j,attr); return gla; }else{//If not found. push_back(attr); return 0; } } //Functional object for find_if. class MGAppearanceSearch{ public: MGAppearanceSearch(const MGGLAttrib* atr):m_attr(atr){;}; bool operator()(const MGGel* atr2){ return m_attr->same_type(*(static_cast(atr2))); }; const MGGLAttrib* m_attr; }; //Search the same MGGLAttrib leaf class object in this list. //If not found, end() will be returned. MGAppearance::iterator MGAppearance::search(const MGGLAttrib* atr){ return std::find_if(begin(), end(), MGAppearanceSearch(atr)); } MGAppearance::const_iterator MGAppearance::search(const MGGLAttrib* atr)const{ return std::find_if(begin(), end(), MGAppearanceSearch(atr)); } MGAppearance::iterator MGAppearance::search_by_id(MGGEL_TID tid){ MGAppearance::iterator i=begin(), ie=end(); for(;i!=ie; i++){ const MGGLAttrib* gla=static_cast(*i); if(gla->identify_type()==tid) return i; } return ie; } MGAppearance::const_iterator MGAppearance::search_by_id(MGGEL_TID tid)const{ MGAppearance::const_iterator i=begin(), ie=end(); for(;i!=ie; i++){ const MGGLAttrib* gla=static_cast(*i); if(gla->identify_type()==tid) return i; } return ie; } //Turn on the appropriate mask bit for this attribute. See glPushAttrib(). int MGAppearance::get_draw_attrib_mask()const{ unsigned int mask=0; MGAppearance::const_iterator i=begin(), ie=end(); for(;i!=ie; i++){ const MGGLAttrib* gla=static_cast(*i); gla->set_draw_attrib_mask(mask); } return mask; } //Turn on the appropriate mask bit for this attribute. See glPushAttrib(). int MGAppearance::get_render_attrib_mask()const{ unsigned int mask=0; MGAppearance::const_iterator i=begin(), ie=end(); for(;i!=ie; i++){ const MGGLAttrib* gla=static_cast(*i); gla->set_render_attrib_mask(mask); } return mask; } //メンバデータを書き込む関数 void MGAppearance::WriteMembers(MGOfstream& buf)const{ buf<>m_glattribs; int no_disp; buf>>no_disp; m_no_display=false; if(no_disp) m_no_display=true; } void MGAppearance::set_color(const MGColor& color){ MGColor* colr=new MGColor(color); set_attrib(colr); } void MGAppearance::set_color(const float color[4]){ MGColor* colr=new MGColor(color[0],color[1],color[2],color[3]); set_attrib(colr); } void MGAppearance::set_color(float red, float green, float blue, float alpha){ MGColor* colr=new MGColor(red,green,blue,alpha); set_attrib(colr); } //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 MGAppearance::set_material( MGRenderAttr::RENDERSIDE rs, const float ambient[3], const float diffuse[3], const float specular[3], const float emission[3], float shininess, float transparency ){ MGRenderAttr* ra; iterator i=search_by_id(MGRENDER_ATTR_TID); if(i==end()){ ra=new MGRenderAttr(); push_back(ra); }else ra=static_cast(*i); ra->set_material(rs,ambient,diffuse,specular,emission,shininess,transparency); } //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. void MGAppearance::set_back_material( const float ambient[3], const float diffuse[3], const float specular[3], const float emission[3], float shininess, float transparency ){ MGRenderAttr* ra; iterator i=search_by_id(MGRENDER_ATTR_TID); if(i==end()){ ra=new MGRenderAttr(); push_back(ra); }else ra=static_cast(*i); ra->set_back_material( ambient,diffuse,specular,emission,shininess,transparency); } ///Line stipple属性をセットする。 ///When factor=0 is input, line pattern is disabled. This means the line is solid. ///When factor<0, the stipple attribute is undefined. This means the attribute ///is defined by the environment. ///When factor<=0, pattern is unnecessary. void MGAppearance::setLineStipple(short int factor,unsigned short pattern){ MGLineStipple* ls=new MGLineStipple(factor,pattern); set_attrib(ls); } void MGAppearance::setLineWidth(float width){ MGLineWidth* lw=new MGLineWidth(width); set_attrib(lw); }