Blender V2.61 - r43446

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 bool COperator2Expr::IsLeftInside(float x, float y, float z,bool bBorderInclude)
00177 {
00178     return m_lhs->IsInside(x,y,z,bBorderInclude);
00179 }
00180 */
00181 bool COperator2Expr::NeedsRecalculated()
00182 {
00183     // added some lines, just for debugging purposes, it could be a one-liner :)
00184     //bool modleft
00185     //bool modright;
00186     assertd(m_lhs);
00187     assertd(m_rhs);
00188 
00189     //modright = m_rhs->NeedsRecalculated();
00190     if (m_rhs->NeedsRecalculated()) // early out
00191         return true;
00192     return m_lhs->NeedsRecalculated();
00193     //modleft = m_lhs->NeedsRecalculated();
00194     //return (modleft || modright);
00195     
00196 }
00197 
00198 
00199 
00200 CExpression* COperator2Expr::CheckLink(std::vector<CBrokenLinkInfo*>& brokenlinks) {
00201 // if both children are 'dead', return NULL
00202 // if only one child is alive, return that child
00203 // if both childresn are alive, return this
00204 
00205 
00206 //      bool leftalive = true,rightalive=true;
00207     /* Does this mean the function will always bomb? */
00208     assertd(false);
00209     assert(m_lhs);
00210     assert(m_rhs);
00211 /*
00212     if (m_cached_calculate)
00213         m_cached_calculate->Action(CValue::REFRESH_CACHE);
00214     
00215     CExpression* newlhs = m_lhs->CheckLink(brokenlinks);
00216     CExpression* newrhs = m_rhs->CheckLink(brokenlinks);
00217 
00218     if (m_lhs != newlhs)
00219     {
00220         brokenlinks.push_back(new CBrokenLinkInfo(&m_lhs,m_lhs));
00221     }
00222 
00223     if (m_rhs != newrhs)
00224     {
00225         brokenlinks.push_back(new CBrokenLinkInfo(&m_rhs,m_rhs));
00226     }
00227 
00228 
00229 
00230     m_lhs = newlhs;
00231     m_rhs = newrhs;
00232 
00233     if (m_lhs && m_rhs) {
00234         return this;
00235     }
00236     
00237     AddRef();
00238     if (m_lhs) 
00239         return Release(m_lhs->AddRef());
00240     
00241     if (m_rhs)
00242         return Release(m_rhs->AddRef());
00243 /       
00244 
00245   */
00246   return Release();
00247 
00248   
00249     
00250 }
00251 
00252 
00253 bool COperator2Expr::MergeExpression(CExpression *otherexpr)
00254 {
00255     if (m_lhs)
00256     {
00257         if (m_lhs->GetExpressionID() == CExpression::CCONSTEXPRESSIONID)
00258         {
00259             // cross fingers ;) replace constexpr by new tree...
00260             m_lhs->Release();
00261             m_lhs = otherexpr->AddRef();
00262             return true;
00263         }
00264     }
00265 
00266     assertd(false);
00267     return false;
00268 }
00269 
00270 
00271 void COperator2Expr::BroadcastOperators(VALUE_OPERATOR op)
00272 {
00273     if (m_lhs)
00274         m_lhs->BroadcastOperators(m_op);
00275     if (m_rhs)
00276         m_rhs->BroadcastOperators(m_op);
00277 }