Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

03.07.2014, 07:33

OscFluid

Fluid-Simulation auf Basis von Oscilation.

Also ich habe in der letzten Zeit für ein kleines Projekt eine Fluid-Simulation gesucht.
Es geht immer nur mit Advection und ist sehr kompliziert.

Warum?

Heute früh habe ich eine andere Lösung geschrieben. Ein komplett anderer Ansatz.
Die Wellen sind Oscillationen, der Druck das ist mittlere das Oscillationsniveau.

Die Meine Methode kommt ohne Richtungsvectoren aus, ohne Advection, ohne Blur.
Alles ist extrem einfach, nur par Zeilen Code.

Und das Ergebnis:



Hier der Code:
OscFluid.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#pragma once
#define DEFAULT_SIZE (100)
#define DEFAULT_VISC (0.02f)
#define DEFAULT_EQUI (0.1f)

#define SQRT2 (0.70710678118654752440084436210485)

class OscFluid
{
public:
    OscFluid(const int NewSize = DEFAULT_SIZE, const float NewVisc = DEFAULT_VISC, const float NewEqui = DEFAULT_EQUI);
    ~OscFluid();
        
    int PosIdx(int x, int y); //convert position to index

    void Update();  

    const int Size;
    const int Area;
    const float Visc; //viscosity
    const float Equi; //equilibrium

    float* Press; //pressure
    float* Vel; //velocity

    float* Perm; //permeability 

private:
    inline void Solve(const int ThisIdx, const int OtherIdx, const float Amount);
    inline void Apply(const int ThisIdx);
};

OscFluid.cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include "OscFluid.h"

OscFluid::OscFluid(const int NewSize, const float NewVisc, const float NewEqui) :
    Press(nullptr),
    Vel(nullptr),
    Perm(nullptr),
    Size(NewSize),
    Area(NewSize * NewSize),
    Visc(NewVisc),
    Equi(NewEqui)
{
    Press = new float[Area];
    Vel = new float[Area];
    Perm = new float[Area];

    for (int i = 0; i < Area; ++i)//default values
    {
        Press[i] = 0.5f;
        Vel[i] = 0.0;

        Perm[i] = 1.f;
    }
    for (int i = 0; i < Size; ++i)//walls, not permeable
    {
        Perm[PosIdx(i, 0)] = 0.f;
        Perm[PosIdx(i, Size - 1)] = 0.f;
        Perm[PosIdx(0, i)] = 0.f;
        Perm[PosIdx(Size - 1, i)] = 0.f;
    }
} 
OscFluid::~OscFluid()
{
    delete[] Press;
    delete[] Vel;
    delete[] Perm;
}
int OscFluid::PosIdx(const int X, const int Y)
{
    return X + Y * Size;
}
void OscFluid::Update()
{
    for (int ThisIdx = 0; ThisIdx < Area; ++ThisIdx)
    {
        if (Perm[ThisIdx] > 0.f)
        {
            Solve(ThisIdx, ThisIdx + 1, Equi);
            Solve(ThisIdx, ThisIdx - 1, Equi);
            Solve(ThisIdx, ThisIdx + Size, Equi);
            Solve(ThisIdx, ThisIdx - Size, Equi);

            Solve(ThisIdx, ThisIdx + 1 + Size, Equi * SQRT2 );
            Solve(ThisIdx, ThisIdx + 1 - Size, Equi * SQRT2 );
            Solve(ThisIdx, ThisIdx - 1 + Size, Equi * SQRT2 );
            Solve(ThisIdx, ThisIdx - 1 - Size, Equi * SQRT2 );
        }
    }
    for (int ThisIdx = 0; ThisIdx < Area; ++ThisIdx)
    {
        if (Perm[ThisIdx] > 0.f)
        {
            Apply(ThisIdx);
        }
    }
}
void OscFluid::Solve(const int ThisIdx, const int OtherIdx, const float Amount)
{
    const float Acc = (Press[ThisIdx] - Press[OtherIdx]) * Perm[OtherIdx] * Amount;
    Vel[OtherIdx] += Acc;
}
void OscFluid::Apply(const int ThisIdx)
{
    Press[ThisIdx] += Vel[ThisIdx];
    Vel[ThisIdx] *= (1.f - Visc);
}


Würde mich mal interessieren was ihr davon haltet, oder obs die Methode vorher schon gab.
So ein ganz richtiges Fluid ist es ja prinzipbedingt nicht.

MFG
Bilder zu meinem Projekt: ParSim

Dieser Beitrag wurde bereits 9 mal editiert, zuletzt von »Horus« (05.07.2014, 23:37)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

03.07.2014, 08:10

Joar, sowas hat man schon auf dem C64 in der Demo-Szene gemacht. Vor 25 Jahren ;)
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

3

04.07.2014, 10:24

Dann ist ja gut.

Komisch nur, dass ich eine derartige Methode nirgendwo gefunden habe als ich nach Fluid gesucht hab.
Wie heißt diese Methode denn?

Neben den schicken Wellen lässt sich daraus vor allem was ganz anderes machen.

Ich denke an sowas wie eine Wirtschaftssimulation. Man kann Warenströme mit der Methode extrem schnell leiten.
Da ließen sich sehr nette Straßennetze usw simulieren.
Auch Verkehr der im Tageszyklus pulsiert ist bestimmt cool.


Aber hier erstmal nochmal die Wellen mit neuer Grafik.


MFG
Bilder zu meinem Projekt: ParSim

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

4

04.07.2014, 10:26

Du könntest auch Schall simulieren.
Nimm eine WAV-Datei als Eingabe und spiele sie an einer Stelle im 2D-Raum ab (Schwingungen anhand der Amplituden in der Datei erzeugen).
An einer anderen Stelle platzierst du dann ein virtuelles Mikrofon, das die ankommenden Schwingungen wieder als Sound ausgibt.
Würde mich sehr interessieren, wie sich das anhört, denn sowas wollte ich immer mal machen.

Werbeanzeige