Blender V2.61 - r43446
|
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 }