00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef NL_PS_ATTRIB_MAKER_BIN_OP_H
00028 #error Do not include this file! include ps_attrib_maker_bin_op_inline instead!
00029 #endif
00030
00031 #ifndef NL_PS_ATTRIB_MAKER_BIN_OP_INLINE_H
00032 #define NL_PS_ATTRIB_MAKER_BIN_OP_INLINE_H
00033
00034
00035
00036 namespace NL3D {
00037
00038
00044 template <class T>
00045 inline T PSBinOpModulate(T arg1, T arg2) { return arg1 * arg2; }
00046 template <class T>
00047 inline T PSBinOpAdd(T arg1, T arg2) { return arg1 + arg2; }
00048 template <class T>
00049 inline T PSBinOpSubtract(T arg1, T arg2) { return arg1 - arg2; }
00050
00051 template <>
00052 inline CPlaneBasis PSBinOpModulate(CPlaneBasis p1, CPlaneBasis p2)
00053 {
00054
00055 NLMISC::CVector z = p1.X ^ p1.Y;
00056 CPlaneBasis r;
00057 r.X.x = p2.X.x * p1.X.x + p2.X.y * p1.Y.x + p2.X.z * z.x;
00058 r.X.y = p2.X.x * p1.X.y + p2.X.y * p1.Y.y + p2.X.z * z.y;
00059 r.X.z = p2.X.x * p1.X.z + p2.X.y * p1.Y.z + p2.X.z * z.z;
00060
00061 r.Y.x = p2.Y.x * p1.X.x + p2.Y.y * p1.Y.x + p2.Y.z * z.x;
00062 r.Y.y = p2.Y.x * p1.X.y + p2.Y.y * p1.Y.y + p2.Y.z * z.y;
00063 r.Y.z = p2.Y.x * p1.X.z + p2.Y.y * p1.Y.z + p2.Y.z * z.z;
00064
00065 return r;
00066
00067 }
00068 template <>
00069 inline CPlaneBasis PSBinOpAdd(CPlaneBasis p1, CPlaneBasis p2)
00070 {
00071 nlassert(0);
00072 return CPlaneBasis(NLMISC::CVector::Null);
00073 }
00074 template <>
00075 inline CPlaneBasis PSBinOpSubtract(CPlaneBasis p1, CPlaneBasis p2)
00076 {
00077 nlassert(0);
00078 return CPlaneBasis(NLMISC::CVector::Null);
00079 }
00080
00081
00082
00083
00084 template <>
00085 inline NLMISC::CRGBA PSBinOpModulate(NLMISC::CRGBA t1, NLMISC::CRGBA t2)
00086 {
00087 NLMISC::CRGBA result;
00088 result.modulateFromColor(t1, t2);
00089 return result;
00090 }
00091 template <>
00092 inline NLMISC::CRGBA PSBinOpAdd(NLMISC::CRGBA t1, NLMISC::CRGBA t2)
00093 {
00094 NLMISC::CRGBA r;
00095 uint S = t1.R + t2.R; if (S > 255) S = 255; r.R = (uint8) S;
00096 S = t1.G + t2.G; if (S > 255) S = 255; r.G = (uint8) S;
00097 S = t1.B + t2.B; if (S > 255) S = 255; r.B = (uint8) S;
00098 return r;
00099 }
00100 template <>
00101 inline NLMISC::CRGBA PSBinOpSubtract(NLMISC::CRGBA t1, NLMISC::CRGBA t2)
00102 {
00103 NLMISC::CRGBA r;
00104 sint S = t1.R - t2.R; if (S < 0) S = 0; r.R = (uint8) S;
00105 S = t1.G - t2.G; if (S < 0) S = 0; r.G = (uint8) S;
00106 S = t1.B - t2.B; if (S < 0) S = 0; r.B = (uint8) S;
00107 return r;
00108 }
00109
00110
00112
00114
00115
00116
00117
00119
00120 CPSAttribMakerBinOp<T>::CPSAttribMakerBinOp(const CPSAttribMakerBinOp &other) : CPSAttribMaker<T>(other)
00121 {
00122 std::auto_ptr<CPSAttribMaker<T> > a0(NLMISC::safe_cast<CPSAttribMaker<T> *>(other._Arg[0]->clone()))
00123 , a1(NLMISC::safe_cast<CPSAttribMaker<T> *>(other._Arg[1]->clone()));
00124 this->_Op = other._Op;
00125 this->_Size = other._Size;
00126 this->_MaxSize = other._MaxSize;
00127 this->_Arg[0] = a0.release();
00128 this->_Arg[1] = a1.release();
00129 }
00130
00131
00132 template <class T>
00133 CPSAttribMakerBinOp<T>::CPSAttribMakerBinOp() : _Op(CPSBinOp::selectArg1), _Size(0), _MaxSize(0)
00134 {
00135 _Arg[0] = _Arg[1] = NULL;
00136 _HasMemory = true;
00137 }
00138
00139
00140 template <class T>
00141 void CPSAttribMakerBinOp<T>::clean(void)
00142 {
00143 delete _Arg[0];
00144 delete _Arg[1];
00145 }
00146
00147
00148 template <class T>
00149 CPSAttribMakerBinOp<T>::~CPSAttribMakerBinOp()
00150 {
00151 clean();
00152 }
00153
00154
00156
00157 {
00158 return (op == CPSBinOp::selectArg1 || op == CPSBinOp::selectArg2 || op == CPSBinOp::modulate);
00159 }
00160
00161
00162
00163 template <class T>
00164 T CPSAttribMakerBinOp<T>::get (CPSLocated *loc, uint32 index)
00165 {
00166 switch (_Op)
00167 {
00168 case CPSBinOp::selectArg1:
00169 return _Arg[0]->get(loc, index);
00170 break;
00171 case CPSBinOp::selectArg2:
00172 return _Arg[1]->get(loc, index);
00173 break;
00174 case CPSBinOp::modulate:
00175 return PSBinOpModulate(_Arg[0]->get(loc, index), _Arg[1]->get(loc, index));
00176 break;
00177 case CPSBinOp::add:
00178 return PSBinOpAdd(_Arg[0]->get(loc, index), _Arg[1]->get(loc, index));
00179 break;
00180 case CPSBinOp::subtract:
00181 return PSBinOpSubtract(_Arg[0]->get(loc, index), _Arg[1]->get(loc, index));
00182 break;
00183 default: break;
00184 }
00185
00186 nlstop;
00187 return T();
00188 }
00189
00190
00191 void MakePrivate(uint8 * dest, const NLMISC::CRGBA *src1, const NLMISC::CRGBA *src2, uint32 stride, uint32 numAttrib, CPSBinOp::BinOp op);
00192
00193 template <class T>
00194 void MakePrivate(uint8 * dest, const T *src1, const T *src2, uint32 stride, uint32 numAttrib, CPSBinOp::BinOp op)
00195 {
00196 uint8 *destEnd = dest + (stride * numAttrib);
00197
00198 switch (op)
00199 {
00200 case CPSBinOp::modulate:
00201 {
00202 while (dest != destEnd)
00203 {
00204 * (T *) dest = PSBinOpModulate(*src1 ++, *src2 ++);
00205 dest += stride;
00206 }
00207 }
00208 break;
00209 case CPSBinOp::add:
00210 {
00211 while (dest != destEnd)
00212 {
00213 * (T *) dest = PSBinOpAdd(*src1 ++, *src2 ++);
00214 dest += stride;
00215 }
00216 }
00217 break;
00218 case CPSBinOp::subtract:
00219 while (dest != destEnd)
00220 {
00221 * (T *) dest = PSBinOpSubtract(*src1 ++, *src2 ++);
00222 dest += stride;
00223 }
00224 break;
00225 default: break;
00226 }
00227 }
00228
00229
00230
00231 template <class T>
00232 inline void *CPSAttribMakerBinOp<T>::makePrivate(T *buf1,
00233 T *buf2,
00234 CPSLocated *loc,
00235 uint32 startIndex,
00236 void *tab,
00237 uint32 stride,
00238 uint32 numAttrib,
00239 bool allowNoCopy ,
00240 uint32 srcStep
00241 ) const
00242 {
00243 uint8 *dest = (uint8 *) tab;
00244 uint leftToDo = numAttrib, toProcess;
00245 nlassert(_Arg[0] && _Arg[1]);
00246 switch (_Op)
00247 {
00248 case CPSBinOp::selectArg1:
00249 return _Arg[0]->make(loc, startIndex, tab, stride, numAttrib, allowNoCopy, srcStep);
00250 break;
00251 case CPSBinOp::selectArg2:
00252 return _Arg[1]->make(loc, startIndex, tab, stride, numAttrib, allowNoCopy, srcStep);
00253 break;
00254 default: break;
00255 }
00256
00257
00258
00259 while (leftToDo)
00260 {
00261 toProcess = leftToDo > PSBinOpBufSize ? PSBinOpBufSize : leftToDo;
00262 T *src1 = (T *) _Arg[0]->make(loc, startIndex + (numAttrib - leftToDo), &buf1[0], sizeof(T), toProcess, true, srcStep);
00263 T *src2 = (T *) _Arg[1]->make(loc, startIndex + (numAttrib - leftToDo), &buf2[0], sizeof(T), toProcess, true, srcStep);
00264 MakePrivate(dest, src1, src2, stride, toProcess, _Op);
00265 leftToDo -= toProcess;
00266 }
00267
00268 return tab;
00269 }
00270
00271
00272 template <class T>
00273 void *CPSAttribMakerBinOp<T>::make (CPSLocated *loc,
00274 uint32 startIndex,
00275 void *tab,
00276 uint32 stride,
00277 uint32 numAttrib,
00278 bool allowNoCopy ,
00279 uint32 srcStep
00280 ) const
00281 {
00286 uint8 tab1[PSBinOpBufSize * sizeof(T)];
00287 uint8 tab2[PSBinOpBufSize * sizeof(T)];
00288 return makePrivate((T *) &tab1[0], (T *) &tab2[0], loc, startIndex, tab, stride, numAttrib, allowNoCopy, srcStep);
00289 }
00290
00291
00292
00293 void Make4Private(uint8 * dest, const NLMISC::CRGBA *src1, const NLMISC::CRGBA *src2, uint32 stride, uint32 numAttrib, CPSBinOp::BinOp op);
00294
00295
00296 template <class T>
00297 void Make4Private(uint8 * dest, const T *src1, const T *src2, uint32 stride, uint32 numAttrib, CPSBinOp::BinOp op)
00298 {
00299 const uint stride2 = stride << 1, stride3 = stride + stride2, stride4 = stride2 << 1;
00300 uint8 *destEnd = dest + ((stride<<2) * numAttrib);
00301 switch (op)
00302 {
00303 case CPSBinOp::modulate:
00304 {
00305 while (dest != destEnd)
00306 {
00307
00308 * (T *) dest = PSBinOpModulate(*src1 ++, *src2 ++);
00309 * (T *) (dest + stride) = * (T *) dest;
00310 * (T *) (dest + stride2) = * (T *) dest;
00311 * (T *) (dest + stride3) = * (T *) dest;
00312 dest += stride4;
00313 }
00314 }
00315 break;
00316 case CPSBinOp::add:
00317 {
00318 while (dest != destEnd)
00319 {
00320
00321 * (T *) dest = PSBinOpAdd(*src1 ++, *src2 ++);
00322 * (T *) (dest + stride) = * (T *) dest;
00323 * (T *) (dest + stride2) = * (T *) dest;
00324 * (T *) (dest + stride3) = * (T *) dest;
00325 dest += stride4;
00326 }
00327 }
00328 break;
00329 case CPSBinOp::subtract:
00330 while (dest != destEnd)
00331 {
00332
00333 * (T *) dest = PSBinOpSubtract(*src1 ++, *src2 ++);
00334 * (T *) (dest + stride) = * (T *) dest;
00335 * (T *) (dest + stride2) = * (T *) dest;
00336 * (T *) (dest + stride3) = * (T *) dest;
00337 dest += stride4;
00338 }
00339 break;
00340 default: break;
00341 }
00342 }
00343
00344
00345 template <class T>
00346 inline void CPSAttribMakerBinOp<T>::make4Private(T *buf1,
00347 T *buf2,
00348 CPSLocated *loc,
00349 uint32 startIndex,
00350 void *tab,
00351 uint32 stride,
00352 uint32 numAttrib,
00353 uint32 srcStep
00354 ) const
00355 {
00356 uint8 *dest = (uint8 *) tab;
00357 uint leftToDo = numAttrib, toProcess;
00358 nlassert(_Arg[0] && _Arg[1]);
00359 switch (_Op)
00360 {
00361 case CPSBinOp::selectArg1:
00362 _Arg[0]->make4(loc, startIndex, tab, stride, numAttrib, srcStep);
00363 return;
00364 break;
00365 case CPSBinOp::selectArg2:
00366 _Arg[1]->make4(loc, startIndex, tab, stride, numAttrib, srcStep);
00367 return;
00368 break;
00369 default: break;
00370 }
00371
00372 while (leftToDo)
00373 {
00374 toProcess = leftToDo > PSBinOpBufSize ? PSBinOpBufSize : leftToDo;
00375 T *src1 = (T *) _Arg[0]->make(loc, startIndex + (numAttrib - leftToDo), &buf1[0], sizeof(T), toProcess, true, srcStep);
00376 T *src2 = (T *) _Arg[1]->make(loc, startIndex + (numAttrib - leftToDo), &buf2[0], sizeof(T), toProcess, true, srcStep);
00377
00378 Make4Private(dest, src1, src2, stride, toProcess, _Op);
00379 leftToDo -= toProcess;
00380 }
00381 }
00382
00383
00384
00385 template <class T>
00386 void CPSAttribMakerBinOp<T>::make4 (CPSLocated *loc,
00387 uint32 startIndex,
00388 void *tab,
00389 uint32 stride,
00390 uint32 numAttrib,
00391 uint32 srcStep
00392 ) const
00393
00394 {
00399 uint8 tab1[PSBinOpBufSize * sizeof(T)];
00400 uint8 tab2[PSBinOpBufSize * sizeof(T)];
00401 make4Private((T *) &tab1[0], (T *) &tab2[0], loc, startIndex, tab, stride, numAttrib, srcStep);
00402 }
00403
00404
00405
00406 void MakeNPrivate(uint8 * dest, const NLMISC::CRGBA *src1, const NLMISC::CRGBA *src2, uint32 stride, uint32 numAttrib, CPSBinOp::BinOp op, uint nbReplicate);
00407
00408
00409 template <class T>
00410 void MakeNPrivate(uint8 * dest,
00411 const T *src1,
00412 const T *src2,
00413 uint32 stride,
00414 uint32 numAttrib,
00415 CPSBinOp::BinOp op,
00416 uint nbReplicate,
00417 uint32 srcStep = (1 << 16)
00418 )
00419 {
00420 uint k;
00421 uint8 *destEnd = dest + ((stride * nbReplicate) * numAttrib);
00422 switch (op)
00423 {
00424 case CPSBinOp::modulate:
00425 {
00426 while (dest != destEnd)
00427 {
00428 * (T *) dest = PSBinOpModulate(*src1 ++, *src2 ++);
00429 k = (nbReplicate - 1);
00430 do
00431 {
00432 * (T *) (dest + stride) = *(T *) dest;
00433 dest += stride;
00434 }
00435 while (--k);
00436 dest += stride;
00437 }
00438 }
00439 break;
00440 case CPSBinOp::add:
00441 {
00442 while (dest != destEnd)
00443 {
00444 * (T *) dest = PSBinOpAdd(*src1 ++, *src2 ++);
00445 k = (nbReplicate - 1);
00446 do
00447 {
00448 * (T *) (dest + stride) = *(T *) dest;
00449 dest += stride;
00450 }
00451 while (--k);
00452 dest += stride;
00453 }
00454 }
00455 break;
00456 case CPSBinOp::subtract:
00457 while (dest != destEnd)
00458 {
00459 * (T *) dest = PSBinOpSubtract(*src1 ++, *src2 ++);
00460 k = (nbReplicate - 1);
00461 do
00462 {
00463 * (T *) (dest + stride) = *(T *) dest;
00464 dest += stride;
00465 }
00466 while (--k);
00467 dest += stride;
00468 }
00469 break;
00470 default: break;
00471 }
00472 }
00473
00474
00475 template <class T>
00476 inline void CPSAttribMakerBinOp<T>::makeNPrivate(T *buf1,
00477 T *buf2,
00478 CPSLocated *loc,
00479 uint32 startIndex,
00480 void *tab,
00481 uint32 stride,
00482 uint32 numAttrib,
00483 uint32 nbReplicate,
00484 uint32 srcStep
00485 ) const
00486 {
00487 uint8 *dest = (uint8 *) tab;
00488 uint leftToDo = numAttrib, toProcess;
00489 nlassert(_Arg[0] && _Arg[1]);
00490 switch (_Op)
00491 {
00492 case CPSBinOp::selectArg1:
00493 _Arg[0]->makeN(loc, startIndex, tab, stride, numAttrib, nbReplicate, srcStep);
00494 return;
00495 break;
00496 case CPSBinOp::selectArg2:
00497 _Arg[1]->makeN(loc, startIndex, tab, stride, numAttrib, nbReplicate, srcStep);
00498 return;
00499 break;
00500 default: break;
00501 }
00502
00503 while (leftToDo)
00504 {
00505 toProcess = leftToDo > PSBinOpBufSize ? PSBinOpBufSize : leftToDo;
00506 T *src1 = (T *) _Arg[0]->make(loc, startIndex + (numAttrib - leftToDo), &buf1[0], sizeof(T), toProcess, true, srcStep);
00507 T *src2 = (T *) _Arg[1]->make(loc, startIndex + (numAttrib - leftToDo), &buf2[0], sizeof(T), toProcess, true, srcStep);
00508
00509 MakeNPrivate(dest, src1, src2, stride, toProcess, _Op, nbReplicate);
00510 leftToDo -= toProcess;
00511 }
00512 }
00513
00514
00515 template <class T>
00516 void CPSAttribMakerBinOp<T>::makeN(CPSLocated *loc,
00517 uint32 startIndex,
00518 void *tab,
00519 uint32 stride,
00520 uint32 numAttrib,
00521 uint32 nbReplicate,
00522 uint32
00523 ) const
00524
00525 {
00530 uint8 tab1[PSBinOpBufSize * sizeof(T)];
00531 uint8 tab2[PSBinOpBufSize * sizeof(T)];
00532 makeNPrivate((T *) &tab1[0], (T *) &tab2[0], loc, startIndex, tab, stride, numAttrib, nbReplicate);
00533 }
00534
00535
00536 template <class T>
00537 void CPSAttribMakerBinOp<T>::serial (NLMISC::IStream &f) throw(NLMISC::EStream)
00538 {
00539 if (f.isReading())
00540 {
00541 clean();
00542 }
00543 f.serialVersion(1);
00544 f.serialEnum(_Op);
00545 f.serialPolyPtr(_Arg[0]);
00546 f.serialPolyPtr(_Arg[1]);
00547 f.serial(_Size, _MaxSize);
00548
00549 }
00550
00551
00552 template <class T>
00553 void CPSAttribMakerBinOp<T>::deleteElement (uint32 index)
00554 {
00555 if (_Arg[0]->hasMemory()) _Arg[0]->deleteElement(index);
00556 if (_Arg[1]->hasMemory()) _Arg[1]->deleteElement(index);
00557 nlassert(_Size != 0);
00558 --_Size;
00559 }
00560
00561
00562 template <class T>
00563 void CPSAttribMakerBinOp<T>::newElement (CPSLocated *emitterLocated, uint32 emitterIndex)
00564 {
00565 if (_Arg[0]->hasMemory()) _Arg[0]->newElement(emitterLocated, emitterIndex);
00566 if (_Arg[1]->hasMemory()) _Arg[1]->newElement(emitterLocated, emitterIndex);
00567 if (_Size != _MaxSize)
00568 {
00569 ++_Size;
00570 }
00571 }
00572
00573
00574 template <class T>
00575 void CPSAttribMakerBinOp<T>::resize (uint32 capacity, uint32 nbPresentElements)
00576 {
00577 nlassert(capacity < (1 << 16));
00578 _MaxSize = capacity;
00579 _Size = nbPresentElements;
00580 if (_Arg[0]->hasMemory()) _Arg[0]->resize(capacity, nbPresentElements);
00581 if (_Arg[1]->hasMemory()) _Arg[1]->resize(capacity, nbPresentElements);
00582 }
00583
00584
00585 }
00586
00587
00588 #endif // NL_PS_ATTRIB_MAKER_BIN_OP_INLINE_H
00589
00590