src/thirdparty/particles/ParticleDLL/other_api.cpp

Go to the documentation of this file.
00001 // other_api.cpp
00002 //
00003 // Copyright 1998-2005 by David K. McAllister.
00004 //
00005 // This file implements the API calls that are not particle actions.
00006 
00007 #include "papi.h"
00008 #include "ParticleState.h"
00009 
00010 #include <iostream>
00011 
00012 // For Windows DLL.
00013 #ifdef WIN32
00014 #ifdef PARTICLE_MAKE_DLL
00015 BOOL APIENTRY DllMain( HANDLE hModule,
00016                        DWORD  ul_reason_for_call,
00017                        LPVOID lpReserved
00018                      )
00019 {
00020     switch (ul_reason_for_call)
00021     {
00022     case DLL_PROCESS_ATTACH:
00023     case DLL_THREAD_ATTACH:
00024     case DLL_THREAD_DETACH:
00025     case DLL_PROCESS_DETACH:
00026         break;
00027     }
00028     return TRUE;
00029 }
00030 #endif
00031 #endif
00032 
00034 // State setting calls
00035 
00036 PARTICLEDLL_API void pColor(float red, float green, float blue, float alpha)
00037 {
00038     ParticleState &PS = _GetPState();
00039 
00040     delete PS.Color;
00041     delete PS.Alpha;
00042     PS.Color = new PDPoint(pVec(red, green, blue));
00043     PS.Alpha = new PDPoint(pVec(alpha));
00044 }
00045 
00046 PARTICLEDLL_API void pColorD(const pDomain &cdom)
00047 {
00048     ParticleState &PS = _GetPState();
00049     delete PS.Color;
00050     delete PS.Alpha;
00051     PS.Color = cdom.copy();
00052     PS.Alpha = new PDPoint(pVec(1));
00053 }
00054 
00055 PARTICLEDLL_API void pColorD(const pDomain &cdom, const pDomain &adom)
00056 {
00057     ParticleState &PS = _GetPState();
00058 
00059     delete PS.Color;
00060     delete PS.Alpha;
00061     PS.Color = cdom.copy();
00062     PS.Alpha = adom.copy();
00063 }
00064 
00065 PARTICLEDLL_API void pUpVec(const pVec &up)
00066 {
00067     ParticleState &PS = _GetPState();
00068 
00069     delete PS.Up;
00070     PS.Up = new PDPoint(up);
00071 }
00072 
00073 PARTICLEDLL_API void pUpVecD(const pDomain &dom)
00074 {
00075     ParticleState &PS = _GetPState();
00076 
00077     delete PS.Up;
00078     PS.Up = dom.copy();
00079 }
00080 
00081 PARTICLEDLL_API void pVelocity(const pVec &v)
00082 {
00083     ParticleState &PS = _GetPState();
00084 
00085     delete PS.Vel;
00086     PS.Vel = new PDPoint(v);
00087 }
00088 
00089 PARTICLEDLL_API void pVelocityD(const pDomain &dom)
00090 {
00091     ParticleState &PS = _GetPState();
00092 
00093     delete PS.Vel;
00094     PS.Vel = dom.copy();
00095 }
00096 
00097 PARTICLEDLL_API void pRotVelocity(const pVec &v)
00098 {
00099     ParticleState &PS = _GetPState();
00100 
00101     delete PS.RotVel;
00102     PS.RotVel = new PDPoint(v);
00103 }
00104 
00105 PARTICLEDLL_API void pRotVelocityD(const pDomain &dom)
00106 {
00107     ParticleState &PS = _GetPState();
00108 
00109     delete PS.RotVel;
00110     PS.RotVel = dom.copy();
00111 }
00112 
00113 PARTICLEDLL_API void pVertexB(const pVec &v)
00114 {
00115     ParticleState &PS = _GetPState();
00116 
00117     delete PS.VertexB;
00118     PS.VertexB = new PDPoint(v);
00119 }
00120 
00121 PARTICLEDLL_API void pVertexBD(const pDomain &dom)
00122 {
00123     ParticleState &PS = _GetPState();
00124 
00125     delete PS.VertexB;
00126     PS.VertexB = dom.copy();
00127 }
00128 
00129 
00130 PARTICLEDLL_API void pVertexBTracks(bool trackVertex)
00131 {
00132     ParticleState &PS = _GetPState();
00133 
00134     PS.vertexB_tracks = trackVertex;
00135 }
00136 
00137 PARTICLEDLL_API void pSize(const pVec &size)
00138 {
00139     ParticleState &PS = _GetPState();
00140 
00141     delete PS.Size;
00142     PS.Size = new PDPoint(size);
00143 }
00144 
00145 PARTICLEDLL_API void pSizeD(const pDomain &dom)
00146 {
00147     ParticleState &PS = _GetPState();
00148 
00149     delete PS.Size;
00150     PS.Size = dom.copy();
00151 }
00152 
00153 PARTICLEDLL_API void pMass(float mass)
00154 {
00155     ParticleState &PS = _GetPState();
00156 
00157     PS.Mass = mass;
00158 }
00159 
00160 PARTICLEDLL_API void pStartingAge(float age, float sigma)
00161 {
00162     ParticleState &PS = _GetPState();
00163 
00164     PS.Age = age;
00165     PS.AgeSigma = sigma;
00166 }
00167 
00168 PARTICLEDLL_API void pTimeStep(float newDT)
00169 {
00170     ParticleState &PS = _GetPState();
00171 
00172     PS.dt = newDT;
00173 }
00174 
00176 // Action List Calls
00177 
00178 PARTICLEDLL_API int pGenActionLists(int action_list_count)
00179 {
00180     ParticleState &PS = _GetPState();
00181 
00182     if(PS.in_new_list)
00183         return -1; // ERROR
00184 
00185     _PLock();
00186 
00187     int ind = PS.GenerateALists(action_list_count);
00188 
00189     _PUnLock();
00190 
00191     return ind;
00192 }
00193 
00194 PARTICLEDLL_API void pNewActionList(int action_list_num)
00195 {
00196     ParticleState &PS = _GetPState();
00197 
00198     if(PS.in_new_list)
00199         return; // ERROR
00200 
00201     _PLock();
00202 
00203     PS.alist_id = action_list_num;
00204     if(PS.alist_id < 0 || PS.alist_id >= (int)PS.ALists.size())
00205         return; // ERROR
00206 
00207     PS.in_new_list = true;
00208     PS.ALists[PS.alist_id].resize(0); // Remove any old actions
00209     // XXX Does that delete the actions?
00210 
00211     _PUnLock();
00212 }
00213 
00214 PARTICLEDLL_API void pEndActionList()
00215 {
00216     ParticleState &PS = _GetPState();
00217 
00218     if(!PS.in_new_list)
00219         return; // ERROR
00220 
00221     PS.in_new_list = false;
00222 
00223     PS.alist_id = -1;
00224 }
00225 
00226 PARTICLEDLL_API void pDeleteActionLists(int action_list_num, int action_list_count)
00227 {
00228     ParticleState &PS = _GetPState();
00229 
00230     if(PS.in_new_list)
00231         return; // ERROR
00232 
00233     if(action_list_num < 0)
00234         return; // ERROR
00235 
00236     _PLock();
00237 
00238     if(action_list_num + action_list_count > (int)PS.ALists.size())
00239         return; // ERROR
00240 
00241     for(int i = action_list_num; i < action_list_num + action_list_count; i++) {
00242         PS.ALists[i].resize(0);
00243         // XXX Does that delete the actions?
00244     }
00245 
00246     _PUnLock();
00247 }
00248 
00249 PARTICLEDLL_API void pCallActionList(int action_list_num)
00250 {
00251     ParticleState &PS = _GetPState();
00252 
00253     if(PS.in_new_list) {
00254         // Add this call as an action to the current list.
00255         PACallActionList *S = new PACallActionList;
00256         S->action_list_num = action_list_num;
00257 
00258         PS.SendAction(S);
00259     } else {
00260         // Execute the specified action list.
00261         _PLock();
00262 
00263         if(action_list_num < 0 || action_list_num >= (int)PS.ALists.size())
00264             return; // ERROR
00265 
00266         ActionList &AList = PS.ALists[action_list_num];
00267 
00268         // Not sure it's safe to unlock here since AList can be accessed by another thread while
00269         // we're executing it, but we can't stay locked while doing all the actions or it's not parallel.
00270         _PUnLock();
00271 
00272         PS.ExecuteActionList(AList);
00273     }
00274 }
00275 
00277 // Particle Group Calls
00278 
00279 // Create particle groups, each with max_particles allocated.
00280 PARTICLEDLL_API int pGenParticleGroups(int p_group_count, size_t max_particles)
00281 {
00282     ParticleState &PS = _GetPState();
00283 
00284     if(PS.in_new_list)
00285         return -1; // ERROR
00286 
00287     _PLock();
00288 
00289     int ind = PS.GeneratePGroups(p_group_count);
00290 
00291     for(int i = ind; i < ind + p_group_count; i++) {
00292         PS.PGroups[i].SetMaxParticles(max_particles);
00293     }
00294 
00295     _PUnLock();
00296 
00297     return ind;
00298 }
00299 
00300 PARTICLEDLL_API void pDeleteParticleGroups(int p_group_num, int p_group_count)
00301 {
00302     ParticleState &PS = _GetPState();
00303 
00304     if(p_group_num < 0)
00305         return; // ERROR
00306 
00307     _PLock();
00308 
00309     if(p_group_num + p_group_count > (int)PS.ALists.size())
00310         return; // ERROR
00311 
00312     for(int i = p_group_num; i < p_group_num + p_group_count; i++) {
00313         PS.PGroups[i].SetMaxParticles(0);
00314         PS.PGroups[i].GetList().resize(0);
00315     }
00316 
00317     _PUnLock();
00318 }
00319 
00320 // Change which group is current.
00321 PARTICLEDLL_API void pCurrentGroup(int p_group_num)
00322 {
00323     ParticleState &PS = _GetPState();
00324 
00325     if(PS.in_new_list)
00326         return; // ERROR
00327 
00328     _PLock();
00329 
00330     if(p_group_num < 0 || p_group_num >= (int)PS.PGroups.size())
00331         return; // ERROR
00332 
00333     _PUnLock();
00334 
00335     PS.pgroup_id = p_group_num;
00336 }
00337 
00338 // Change the maximum number of particles in the current group.
00339 PARTICLEDLL_API size_t pSetMaxParticles(size_t max_count)
00340 {
00341     ParticleState &PS = _GetPState();
00342 
00343     if(PS.in_new_list)
00344         return 0; // ERROR
00345 
00346     // useless test, can never be negative
00347     // if(max_count < 0)
00348     //    return 0; // ERROR
00349 
00350     // This can kill them and call their death callback.
00351     PS.GetPGroup(PS.pgroup_id).SetMaxParticles(max_count);
00352 
00353     return max_count;
00354 }
00355 
00356 // Copy from the specified group to the current group.
00357 PARTICLEDLL_API void pCopyGroup(int p_src_group_num, size_t index, size_t copy_count)
00358 {
00359     ParticleState &PS = _GetPState();
00360 
00361     if(PS.in_new_list)
00362         return; // ERROR
00363 
00364     _PLock();
00365 
00366     if(p_src_group_num < 0 || p_src_group_num >= (int)PS.PGroups.size())
00367         return; // ERROR
00368 
00369     ParticleGroup &srcgrp = PS.GetPGroup(p_src_group_num);
00370 
00371     ParticleGroup &destgrp = PS.GetPGroup(PS.pgroup_id);
00372 
00373     // Find out exactly how many to copy.
00374     size_t ccount = copy_count;
00375     if(ccount > srcgrp.size() - index)
00376         ccount = srcgrp.size() - index;
00377     if(ccount > destgrp.GetMaxParticles() - destgrp.size())
00378         ccount = destgrp.GetMaxParticles() - destgrp.size();
00379 
00380     // useless test, can never be negative
00381     // if(ccount<0)
00382     //     ccount = 0;
00383 
00384     // Directly copy the particles to the current list.
00385     for(size_t i=0; i<ccount; i++) {
00386         // Is it bad to call a birth callback while locked?
00387         destgrp.Add(srcgrp.GetList()[index+i]);
00388     }
00389 
00390     _PUnLock();
00391 }
00392 
00393 // Copy from the current group to application memory.
00394 PARTICLEDLL_API size_t pGetParticles(size_t index, size_t count, float *verts,
00395                                      float *color, float *vel, float *size, float *age)
00396 {
00397     ParticleState &PS = _GetPState();
00398 
00399     // XXX I should think about whether color means color3, color4, or what.
00400     // For now, it means color4.
00401 
00402     if(PS.in_new_list)
00403         return static_cast< size_t >( -1 ); // ERROR
00404 
00405     _PLock();
00406 
00407     if(PS.pgroup_id < 0 || PS.pgroup_id >= (int)PS.PGroups.size())
00408         return static_cast< size_t >( -2 ); // ERROR
00409 
00410     // useless test, both are never negative
00411     // if(index < 0 || count < 0)
00412     //    return static_cast< size_t >( -3 ); // ERROR
00413 
00414     ParticleGroup &pg = PS.PGroups[PS.pgroup_id];
00415 
00416     _PUnLock();
00417 
00418     if(index + count > pg.size()) {
00419         count = pg.size() - index;
00420         if(count <= 0)
00421             return static_cast< size_t >( -4 ); // ERROR index out of bounds.
00422     }
00423 
00424     int vi = 0, ci = 0, li = 0, si = 0, ai = 0;
00425 
00426     // This should be optimized.
00427     for(size_t i=index; i<index+count; i++) {
00428         const Particle &m = pg.GetList()[i];
00429 
00430         if(verts) {
00431             verts[vi++] = m.pos.x();
00432             verts[vi++] = m.pos.y();
00433             verts[vi++] = m.pos.z();
00434         }
00435 
00436         if(color) {
00437             color[ci++] = m.color.x();
00438             color[ci++] = m.color.y();
00439             color[ci++] = m.color.z();
00440             color[ci++] = m.alpha;
00441         }
00442 
00443         if(vel) {
00444             vel[li++] = m.vel.x();
00445             vel[li++] = m.vel.y();
00446             vel[li++] = m.vel.z();
00447         }
00448 
00449         if(size) {
00450             size[si++] = m.size.x();
00451             size[si++] = m.size.y();
00452             size[si++] = m.size.z();
00453         }
00454 
00455         if(age) {
00456             age[ai++] = m.age;
00457         }
00458     }
00459 
00460     return count;
00461 }
00462 
00463 // Return a pointer to the particle data, together with the stride IN FLOATS
00464 // from one particle to the next and the offset IN FLOATS from the start of the particle
00465 // for each attribute's data. The number in the arg name is how many floats the attribute
00466 // consists of.
00467 //
00468 // WARNING: This function gives the application access to memory allocated and controlled
00469 // by the Particle API. Don't do anything stupid with this power or you will regret it.
00470 PARTICLEDLL_API size_t pGetParticlePointer(float *&ptr, size_t &stride, size_t &pos3Ofs, size_t &posB3Ofs,
00471         size_t &size3Ofs, size_t &vel3Ofs, size_t &velB3Ofs,
00472         size_t &color3Ofs, size_t &alpha1Ofs, size_t &age1Ofs)
00473 {
00474     ParticleState &PS = _GetPState();
00475 
00476     if(PS.in_new_list)
00477         return static_cast< size_t >( -1 ); // ERROR
00478 
00479     ParticleGroup &pg = PS.PGroups[PS.pgroup_id];
00480 
00481     if(pg.size() < 1) {
00482         return static_cast< size_t >( -4 ); // ERROR index out of bounds.
00483     }
00484 
00485     ParticleList::iterator it = pg.begin();
00486     Particle *p0 = &(*it);
00487     ++it;
00488     Particle *p1 = &(*it);
00489     float *fp0 = (float *)p0;
00490     float *fp1 = (float *)p1;
00491 
00492     ptr = (float *)p0;
00493     stride = fp1 - fp0;
00494     pos3Ofs = (float *)&(p0->pos.x()) - fp0;
00495     posB3Ofs = (float *)&(p0->posB.x()) - fp0;
00496     size3Ofs = (float *)&(p0->size.x()) - fp0;
00497     vel3Ofs = (float *)&(p0->vel.x()) - fp0;
00498     velB3Ofs = (float *)&(p0->velB.x()) - fp0;
00499     color3Ofs = (float *)&(p0->color.x()) - fp0;
00500     alpha1Ofs = (float *)&(p0->alpha) - fp0;
00501     age1Ofs = (float *)&(p0->age) - fp0;
00502 
00503     return pg.size();
00504 }
00505 
00506 // Returns the number of particles currently in the group.
00507 PARTICLEDLL_API size_t pGetGroupCount()
00508 {
00509     ParticleState &PS = _GetPState();
00510 
00511     if(PS.in_new_list)
00512         return 0; // ERROR
00513 
00514     PS.GetPGroup(PS.pgroup_id);
00515     _PLock();
00516 
00517     if(PS.pgroup_id < 0 || PS.pgroup_id >= (int)PS.PGroups.size())
00518         return static_cast< size_t >( -2 ); // ERROR
00519 
00520     _PUnLock();
00521 
00522     return PS.PGroups[PS.pgroup_id].size();
00523 }
00524 
00525 // Returns the maximum number of allowed particles
00526 PARTICLEDLL_API size_t pGetMaxParticles()
00527 {
00528     ParticleState &PS = _GetPState();
00529 
00530     if(PS.in_new_list)
00531         return 0; // ERROR
00532 
00533     _PLock();
00534 
00535     if(PS.pgroup_id < 0 || PS.pgroup_id >= (int)PS.PGroups.size())
00536         return static_cast< size_t >( -2 ); // ERROR
00537 
00538     _PUnLock();
00539 
00540     return PS.PGroups[PS.pgroup_id].GetMaxParticles();
00541 }
00542 
00544 // Other API Calls
00545 
00546 PARTICLEDLL_API void pBirthCallback(P_PARTICLE_CALLBACK callback, void *data)
00547 {
00548     ParticleState &PS = _GetPState();
00549     if(PS.in_new_list)
00550         return; // ERROR
00551 
00552     PS.GetPGroup(PS.pgroup_id).SetBirthCallback(callback, data);
00553 }
00554 
00555 PARTICLEDLL_API void pDeathCallback(P_PARTICLE_CALLBACK callback, void *data)
00556 {
00557     ParticleState &PS = _GetPState();
00558     if(PS.in_new_list)
00559         return; // ERROR
00560 
00561     PS.GetPGroup(PS.pgroup_id).SetDeathCallback(callback, data);
00562 }
00563 
00564 PARTICLEDLL_API void pReset()
00565 {
00566     ParticleState &PS = _GetPState();
00567     if(PS.in_new_list)
00568         return; // ERROR
00569 
00570     PS.GetPGroup(PS.pgroup_id).GetList().clear();
00571 }
00572 
00573 PARTICLEDLL_API void pSeed(unsigned int seed)
00574 {
00575     pSRandf(seed);
00576 }

Generated on Sat Mar 15 22:55:58 2008 for Armagetron Advanced by  doxygen 1.5.4