Blender  V2.59
Operator2Expr.cpp
Go to the documentation of this file.
00001 
00004 // Operator2Expr.cpp: implementation of the COperator2Expr class.
00005 /*
00006  * Copyright (c) 1996-2000 Erwin Coumans <coockie@acm.org>
00007  *
00008  * Permission to use, copy, modify, distribute and sell this software
00009  * and its documentation for any purpose is hereby granted without fee,
00010  * provided that the above copyright notice appear in all copies and
00011  * that both that copyright notice and this permission notice appear
00012  * in supporting documentation.  Erwin Coumans makes no
00013  * representations about the suitability of this software for any
00014  * purpose.  It is provided "as is" without express or implied warranty.
00015  *
00016  */
00017 // 31 dec 1998 - big update: try to use the cached data for updating, instead of
00018 // rebuilding completely it from left and right node. Modified flags and bounding boxes
00019 // have to do the trick
00020 // when expression is cached, there will be a call to UpdateCalc() instead of Calc()
00021 
00022 #include "Operator2Expr.h"
00023 #include "StringValue.h"
00024 #include "VoidValue.h"
00025 
00027 // Construction/Destruction
00029 
00030 COperator2Expr::COperator2Expr(VALUE_OPERATOR op, CExpression *lhs, CExpression *rhs)
00031 :       
00032 m_rhs(rhs),
00033 m_lhs(lhs),
00034 m_cached_calculate(NULL),
00035 m_op(op)
00036 /*
00037 pre:
00038 effect: constucts a COperator2Expr with op, lhs and rhs in it
00039 */
00040 {
00041 
00042 }
00043 
00044 COperator2Expr::COperator2Expr():
00045 m_rhs(NULL),
00046 m_lhs(NULL),
00047 m_cached_calculate(NULL)
00048 
00049 /*
00050 pre:
00051 effect: constucts an empty COperator2Expr
00052 */
00053 {
00054         
00055 }
00056 
00057 COperator2Expr::~COperator2Expr()
00058 /*
00059 pre:
00060 effect: deletes the object
00061 */
00062 {
00063         if (m_lhs)
00064                 m_lhs->Release();
00065         if (m_rhs)
00066                 m_rhs->Release();
00067         if (m_cached_calculate)
00068                 m_cached_calculate->Release();
00069         
00070 }
00071 CValue* COperator2Expr::Calculate()
00072 /*
00073 pre:
00074 ret: a new object containing the result of applying operator m_op to m_lhs
00075 and m_rhs
00076 */
00077 {
00078         
00079         bool leftmodified,rightmodified;
00080         leftmodified = m_lhs->NeedsRecalculated();
00081         rightmodified = m_rhs->NeedsRecalculated();
00082         
00083         // if no modifications on both left and right subtree, and result is already calculated
00084         // then just return cached result...
00085         if (!leftmodified && !rightmodified && (m_cached_calculate))
00086         {
00087                 // not modified, just return m_cached_calculate
00088         } else {
00089                 // if not yet calculated, or modified...
00090                 
00091                 
00092                 if (m_cached_calculate) {
00093                         m_cached_calculate->Release();
00094                         m_cached_calculate=NULL;
00095                 }
00096                 
00097                 CValue* ffleft = m_lhs->Calculate();
00098                 CValue* ffright = m_rhs->Calculate();
00099                 
00100                 ffleft->SetOwnerExpression(this);//->m_pOwnerExpression=this;
00101                 ffright->SetOwnerExpression(this);//->m_pOwnerExpression=this;
00102                 
00103                 m_cached_calculate = ffleft->Calc(m_op,ffright);
00104                 
00105                 //if (m_cached_calculate)                               
00106                 //      m_cached_calculate->Action(CValue::SETOWNEREXPR,&CVoidValue(this,false,CValue::STACKVALUE));
00107 
00108                 ffleft->Release();
00109                 ffright->Release();
00110         }
00111         
00112         return m_cached_calculate->AddRef();
00113         
00114 }
00115 
00116 /*
00117 bool COperator2Expr::IsInside(float x, float y, float z,bool bBorderInclude)
00118 {
00119         bool inside;
00120         inside = false;
00121         
00122         switch (m_op) 
00123         {
00124         case VALUE_ADD_OPERATOR: {
00125         //      inside = first || second; // optimized with early out if first is inside
00126                 // todo: calculate smallest leaf first ! is much faster...
00127                         
00128                 bool second;//first ;//,second;
00129                 
00130                 //first = m_lhs->IsInside(x,y,z) ;
00131                 second = m_rhs->IsInside(x,y,z,bBorderInclude) ;
00132                 if (second)
00133                         return true; //early out
00134         
00135         //      second = m_rhs->IsInside(x,y,z) ;
00136 
00137                 return m_lhs->IsInside(x,y,z,bBorderInclude) ;
00138                         
00139                 break;
00140                                                          }
00141                 
00142         case VALUE_SUB_OPERATOR: {
00143                 //inside = first && !second; // optimized with early out
00144                 // todo: same as with add_operator: calc smallest leaf first
00145 
00146                 bool second;//first ;//,second;
00147                 //first = m_lhs->IsInside(x,y,z) ;
00148                 second = m_rhs->IsInside(x,y,z,bBorderInclude);
00149                 if (second)
00150                         return false;
00151 
00152                 // second space get subtracted -> negate!
00153                 //second = m_rhs->IsInside(x,y,z);
00154 
00155                 return (m_lhs->IsInside(x,y,z,bBorderInclude));
00156 
00157                 
00158                 break;
00159                                                          }
00160         default:{
00161                 assert(false);
00162                 // not yet implemented, only add or sub csg operations
00163                         }
00164         }
00165         
00166         return inside;  
00167 }
00168 
00169 
00170 
00171 bool COperator2Expr::IsRightInside(float x, float y, float z,bool bBorderInclude) {
00172         
00173         return m_rhs->IsInside(x,y,z,bBorderInclude) ;
00174         
00175 }
00176 
00177 bool COperator2Expr::IsLeftInside(float x, float y, float z,bool bBorderInclude) {
00178         return m_lhs->IsInside(x,y,z,bBorderInclude);
00179 }
00180 */
00181 bool COperator2Expr::NeedsRecalculated() {
00182         // added some lines, just for debugging purposes, it could be a one-liner :)
00183         //bool modleft
00184         //bool modright;
00185         assertd(m_lhs);
00186         assertd(m_rhs);
00187 
00188         //modright = m_rhs->NeedsRecalculated();
00189         if (m_rhs->NeedsRecalculated()) // early out
00190                 return true;
00191         return m_lhs->NeedsRecalculated();
00192         //modleft = m_lhs->NeedsRecalculated();
00193         //return (modleft || modright);
00194         
00195 }
00196 
00197 
00198 
00199 CExpression* COperator2Expr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) {
00200 // if both children are 'dead', return NULL
00201 // if only one child is alive, return that child
00202 // if both childresn are alive, return this
00203 
00204 
00205 //      bool leftalive = true,rightalive=true;
00206         /* Does this mean the function will always bomb? */
00207         assertd(false);
00208         assert(m_lhs);
00209         assert(m_rhs);
00210 /*
00211         if (m_cached_calculate)
00212                 m_cached_calculate->Action(CValue::REFRESH_CACHE);
00213         
00214         CExpression* newlhs = m_lhs->CheckLink(brokenlinks);
00215         CExpression* newrhs = m_rhs->CheckLink(brokenlinks);
00216 
00217         if (m_lhs != newlhs)
00218         {
00219                 brokenlinks.push_back(new CBrokenLinkInfo(&m_lhs,m_lhs));
00220         }
00221 
00222         if (m_rhs != newrhs)
00223         {
00224                 brokenlinks.push_back(new CBrokenLinkInfo(&m_rhs,m_rhs));
00225         }
00226 
00227 
00228 
00229         m_lhs = newlhs;
00230         m_rhs = newrhs;
00231 
00232         if (m_lhs && m_rhs) {
00233                 return this;
00234         }
00235         
00236         AddRef();
00237         if (m_lhs) 
00238                 return Release(m_lhs->AddRef());
00239         
00240         if (m_rhs)
00241                 return Release(m_rhs->AddRef());
00242 /               
00243 
00244   */
00245   return Release();
00246 
00247   
00248         
00249 }
00250 
00251 
00252 bool COperator2Expr::MergeExpression(CExpression *otherexpr)
00253 {
00254         if (m_lhs)
00255         {
00256                 if (m_lhs->GetExpressionID() == CExpression::CCONSTEXPRESSIONID)
00257                 {
00258                         // cross fingers ;) replace constexpr by new tree...
00259                         m_lhs->Release();
00260                         m_lhs = otherexpr->AddRef();
00261                         return true;
00262                 }
00263         }
00264 
00265         assertd(false);
00266         return false;
00267 }
00268 
00269 
00270 void COperator2Expr::BroadcastOperators(VALUE_OPERATOR op)
00271 {
00272         if (m_lhs)
00273                 m_lhs->BroadcastOperators(m_op);
00274         if (m_rhs)
00275                 m_rhs->BroadcastOperators(m_op);
00276 }