/src/AEmitter.cpp
C++ | 264 lines | 149 code | 54 blank | 61 comment | 12 complexity | 133426755533d3ff520a0241098c5253 MD5 | raw file
- //------------------------------------//
- //
- // AEmitter.cpp
- //
- // Author: ayufan (ayufan[at]o2.pl)
- // Project: ayuine2
- // Date: 2006-8-18
- //
- //------------------------------------//
-
- #include "StdAfx.hpp"
-
- namespace ayuine
- {
- //------------------------------------//
- // ParticleVertex: Static Fields
-
- VertexDeclElement ParticleVertex::Decl[] = {
- {0, OffsetOf(ParticleVertex, Origin), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
- {0, OffsetOf(ParticleVertex, Coords), D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
- {0, OffsetOf(ParticleVertex, Color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
- D3DDECL_END()
- };
-
- //------------------------------------//
- // AEmitter: Constructor
-
- AEmitter::AEmitter(u32 particles) {
- // Flags
- Flags = afUpdate | afZones | afArea | afPrepare | afTransform;
-
- // Ustaw domylne parametry
- _active = _free = nullptr;
- _time = _last = 0;
- Type = etPoint;
- Enabled = true;
- World = false;
- Mass = 1.0f;
- LifeTime = 1.0f;
- Radius = 1.0f;
- RadiusDerivative = 0.0f;
- StartColor = vec4(1, 1, 1, 1);
- EndColor = vec4(0, 0, 0, 0);
- Force = vec3(0, 0, 1);
- StartVelocity = 1.0f;
- MaxVelocity = 1.0f;
- MaxAngular = 1.0f;
-
- // Utwórz wszystkie czšsteczki
- _particles.resize(particles);
-
- // Dołšcz do listy pustych
- ArrayEach(Particle, i, _particles) {
- i->Next = _free;
- _free = &*i;
- }
-
- // Utwórz format wierzchołków
- _vertexType.reset(new VertexType(ParticleVertex::Decl));
- }
-
- //------------------------------------//
- // AEmitter: Destructor
-
- AEmitter::~AEmitter() {
- }
-
- //------------------------------------//
- // AEmitter: Methods
-
- void AEmitter::preupdate(f32 dt) {
- Particle *curr;
- Particle *next;
-
- // Wywołaj nadrzędnš metodę aktualizacji
- Actor::preupdate(dt);
-
- // Wyzeruj obszar emittera
- Box.clear();
-
- // Czy mamy dodawać nowe czšsteczki?
- if(Enabled) {
- // Dodaj róznicę czasowš
- _time += dt;
-
- // Oblicz co ile mamy robić czšsteczki
- f32 every = LifeTime / _particles.size();
-
- // Zrób nowe czšsteczki
- if(_free && _last + every < _time) {
- vec3 at;
-
- // Ustaw czas emitowania
- _last = _time;
-
- // Pobierz nowš czšsteczkę
- curr = _free;
- _free = _free->Next;
-
- // Zresetuj wszystkie parametry
- memset(curr, 0, sizeof(Particle));
-
- // Wylosuj wektor
- for(u32 i = 0; i < 3; i++)
- at[i] = ((rand() % 256) - 128) / 128.0f;
-
- // Ustaw parametry czšsteczek
- switch(Type) {
- case etPoint:
- curr->Origin = Origin;
- break;
-
- case etSphere:
- curr->Origin = Origin + Size.length() * at;
- break;
-
- case etBox:
- curr->Origin = Origin + Size * at;
- break;
- }
-
- // Ustaw siłę
- curr->Angular = angles(curr->Origin - Origin);
- curr->Velocity = Force + at.normalize() * StartVelocity;
-
- // Dodaj do aktywnych
- curr->Next = _active;
- _active = curr;
-
- // Oznacz czšsteczki jako zmienione
- Changed |= cfArea;
- }
- }
-
- // Zapisz listę
- curr = _active;
-
- // Zniszcz starš listę
- _active = nullptr;
-
- // Uaktualnij czšsteczki
- while(curr) {
- next = curr->Next;
-
- // Oznacz czšsteczki jako zmienione
- Changed |= cfArea;
-
- // Uaktualnij czšsteczkę
- curr->Origin += curr->Velocity * dt;
- curr->Rotation += curr->Angular * dt;
- curr->LifeTime += dt;
-
- // Czy jeszcze żyje?
- if(curr->LifeTime > LifeTime) {
- // Zabić jš
- curr->Next = _free;
- _free = curr;
- curr = next;
- continue;
- }
-
- f32 time = clamp(curr->LifeTime / LifeTime);
-
- // Uaktualnij parametry
- curr->Radius = Radius + Radius * powf(time, abs(RadiusDerivative)) * (RadiusDerivative > MathErr ? 1 : RadiusDerivative < -MathErr ? -1 : 0);
- curr->Color = StartColor * (1.0f - time) + EndColor * time;
-
- // Dodaj czšsteczki do obszaru
- Box = Box.merge(bbox(curr->Origin, curr->Radius));
- curr->Next = _active;
- _active = curr;
- curr = next;
- }
- }
-
- void AEmitter::postupdate(f32 dt) {
- // Uaktualnij bufory tylko jak zmienił się stan czšsteczek
- _needsToUpdate = Changed;
-
- // Wywołaj nadrzędnš metodę aktualizacji
- Actor::postupdate(dt);
- }
-
- void AEmitter::prepare(RenderFrame &frame) {
- // Sprawd typ wywietlania
- if(frame.Type == rmDepth)
- return;
-
- // Czy mamy materiał
- if(!Material)
- return;
-
- // Czšsteczki do wywietlenia
- if(!_active)
- return;
-
- // Musimy uaktualnić czšsteczki?
- if(_needsToUpdate) {
- Particle* curr;
- u32 i;
-
- // Oblicz iloć aktywnych czšsteczek
- for(curr = _active, i = 0; curr; curr = curr->Next)
- i++;
-
- // Zarezerwuj miejsce w buforach
- _vertices.resize(i * 4);
- _indices.resize(i * 6);
-
- // Wygeneruj każdš czšsteczkę
- for(curr = _active, i = 0; curr; curr = curr->Next, i++) {
- ParticleVertex *vertex = &_vertices.at(i * 4);
- u16 *index = &_indices.at(i * 6);
-
- // Zapisz pozycje
- vertex[0].Origin = curr->Origin;
- vertex[1].Origin = curr->Origin;
- vertex[2].Origin = curr->Origin;
- vertex[3].Origin = curr->Origin;
-
- // Zapisz koordynanty
- vertex[0].Coords = vec4(0, 0, -curr->Radius, -curr->Radius);
- vertex[1].Coords = vec4(0, 1, -curr->Radius, +curr->Radius);
- vertex[2].Coords = vec4(1, 1, +curr->Radius, +curr->Radius);
- vertex[3].Coords = vec4(1, 0, +curr->Radius, -curr->Radius);
-
- // Zapisz kolor
- vertex[0].Color =
- vertex[1].Color =
- vertex[2].Color =
- vertex[2].Color = D3DCOLOR_COLORVALUE(curr->Color.X, curr->Color.Y, curr->Color.Z, curr->Color.W);
-
- // Dodaj indeksy wierzchołków
- index[0] = i * 4 + 0;
- index[1] = i * 4 + 1;
- index[2] = i * 4 + 2;
- index[3] = i * 4 + 0;
- index[4] = i * 4 + 2;
- index[5] = i * 4 + 3;
- }
- _needsToUpdate = false;
- }
-
- RenderDynamic *object = new RenderDynamic();
-
- // Ustaw parametry ogólne
- object->Box = Box;
- object->Sphere = bsphere(Box.center(), Box.radius());
- object->Material = Material;
- object->Plane = vec4(-frame.CameraAt, Origin);
-
- // Ustaw parametry obiektu
- object->VertexType = _vertexType;
- object->Vertices = &_vertices.at(0);
- object->VertexStride = sizeof(ParticleVertex);
- object->VertexCount = _vertices.size();
- object->Indices = &_indices.at(0);
- object->IndexCount = _indices.size();
- object->Drawers.push(BatchIndexedDrawer(D3DPT_TRIANGLELIST, 0, _vertices.size(), 0, _indices.size() / 3));
-
- // Dodaj do renderingu
- frame.addFrag(object);
- }
- };