[B3D] - Particle/Mesh in CameraView?

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

PSY

Betreff: [B3D] - Particle/Mesh in CameraView?

BeitragDo, Feb 26, 2009 17:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Hiho,

momentan bin ich dabei, ein Particle System zu coden. Infos dazu gibts im Worklog-Bereich.
Ein Problem bei solchen Systemen ist ja bekanntlich die Performance. Deshalb ist es ungemein wichtig, auch nur die Particle zu rendern, die innerhalb des Sichtbereichs der Kamera liegen.
Dabei wird oftmals die Funktion CameraProject(...) verwendet, die 3D Koordinaten in 2D Koordinaten umrechnet. Man braucht also nur die x,y,z Position seines Particles mit Hilfe von CameraProject() in 2D Koordinaten umzuwandeln, und dann überprüfen ob die Koordinaten innerhalb der eingestellten Auflösung liegen.
Beispiel:

Code: [AUSKLAPPEN]
If ProjectedX() >0 and ProjectedX()<800 then RENDERPARTICLE....


Diese Methode hat jedoch einen entscheidenden Nachteil: Je grösser der Particle skaliert wird, und je dichter sich die Kamera am Particle befindet, desto ungenauer wird die Berechnung. D.h. entweder wird der Particle gerendert, obwohl er sich schon ausserhalb des sichtbaren Bereiches befindet, oder (was meistens der Fall ist) Teile des Particles ragen noch in den sichtbaren Bereich, aber er wird dank der ungenauen Berechnung schon nicht mehr gerendert.

Deshalb hab ich mal ein wenig rumgespielt, und rausgekommen ist folgender Code: (bei grossen Particlemengen sogar schneller als die CameraProject()-Methode):
(edit) es geht hier eigentlich nur um die function visible_new(), der Rest des Codes dient nur der Veranschaulichung!

Code: [AUSKLAPPEN]
Graphics3D 800,600,0,2
SetBuffer BackBuffer()

Local v%,algo%=0,x#,y#,z#

Global Cam      = CreateCamera()
Global Mesh    = CreateMesh()
Global Surface   = CreateSurface(Mesh)
Global screenw    = GraphicsWidth()
Global screenh    = GraphicsHeight()

Global screen_ratio#     = Float(screenw)/screenh
Global xx#,yy#,zz#,size% =1

PositionEntity Cam,0,0,-20

;CREATE "PARTICLE"
v=AddVertex      (Surface, -1, 1, 0)
AddVertex       Surface,  1, 1, 0
AddVertex       Surface, -1,-1, 0
AddVertex         Surface,  1,-1, 0
AddTriangle     Surface, v,  v+1, v+2
AddTriangle     Surface, v+1,v+3, v+2


Repeat
   size=size+KeyHit(31)-KeyHit(45) : If size<1 Then size=1
   ScaleEntity Mesh,size,size,size,1
   xx=xx+KeyHit(205)*.5-KeyHit(203)*.5
   yy=yy+KeyHit(200)*.5-KeyHit(208)*.5
   zz=zz+KeyHit(44)-KeyHit(30)
   If KeyHit(28) Then algo=1-algo
   PositionEntity Mesh,xx,yy,zz
   RenderWorld()
   
   ;GET VERTEX COORDINATES OF PARTICLE
   TFormPoint VertexX(Surface,0),VertexY(Surface,0),VertexZ(Surface,0),Mesh,0
    x = TFormedX()
    y = TFormedY()
    z = TFormedZ()
   Text 10,10,"VERTICE 0:  " + x + "  " + y + "  " + z
   TFormPoint VertexX(Surface,1),VertexY(Surface,1),VertexZ(Surface,1),Mesh,0
    x = TFormedX()
    y = TFormedY()
    z = TFormedZ()
   Text 500,10,"VERTICE 1:  " + x + "  " + y + "  " +z
    TFormPoint VertexX(Surface,2),VertexY(Surface,2),VertexZ(Surface,2),Mesh,0
    x = TFormedX()
    y = TFormedY()
    z = TFormedZ()
    Text 10,100,"VERTICE 2:  " + x + "  " + y + "  " + z
    TFormPoint VertexX(Surface,3),VertexY(Surface,3),VertexZ(Surface,3),Mesh,0
    x = TFormedX()
    y = TFormedY()
    z = TFormedZ()
   Text 500,100,"VERTICE 3:  " + x + "  " + y + "  " + z
   
   If algo=1
      visible_new()
   Else
      visible_old()
   EndIf
   
   Color 255,255,255
   Text 0,300, "CURSOR KEYS : HORIZONTAL / VERTICAL MOVEMENT"
   Text 0,320, "A AND Y     : CAMERA ZOOM"
   Text 0,340, "S AND X     : SCALE PARTICLE"
   Text 0,360, "RETURN      : TOGGLE ALGORITHM"
   
   If algo=1 Then Text 0,400,"USING NEW ALGORITHM:  " Else Text 0,400,"USING CAMERAPROJECT:  "
   
   Flip 1
   
Until KeyHit(1)


Function visible_new()
   Local zdist#
   zdist = zz-EntityZ(Cam)
   If zdist > 0
      If zdist > Abs(xx) - size
         If zdist > (Abs(yy)-size) * screen_ratio
            Color 0,255,0
            Text 200,400,"PARTICLE VISIBLE" : Return
         End If
      End If
   End If
   Color 255,0,0
   Text 200,400,"PARTICLE NOT VISIBLE"
End Function


Function visible_old()
   CameraProject Cam,xx,yy,zz
   If ProjectedZ()>0
      If ProjectedX() > -size And ProjectedX() < screenw + size
            If ProjectedY() > -size And ProjectedY() < screenh + size
            Color 0,255,0
            Text 200,400,"PARTICLE VISIBLE" : Return
            End If
        End If
    End If
    Color 255,0,0
   Text 200,400,"PARTICLE NOT VISIBLE"
         
End Function


Steuerung:
Mit den Cursortasten Particle in x und y Richtung bewegen
Mit A und Y die Cam bewegen
Mit S und X den Particle skalieren
Mit RETURN zwischen der alten Methode (CameraProject) und der neuen Methode umschalten.

Einfach mal den Partikel grösser skalieren und/oder mit der Cam ranfahren, dann sieht man das Problem.


Wie man sehen kann, hat die neue Methode gegenüber der oftmals benutzen Cameraproject()-Methode einen entscheidenden Vorteil.


L8er,
PSY
  • Zuletzt bearbeitet von PSY am Fr, Feb 27, 2009 0:04, insgesamt einmal bearbeitet

FireballFlame

BeitragDo, Feb 26, 2009 17:39
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich versteh das noch nicht ganz. Rendert Blitz nicht automatisch nur das, was im Sichtfeld ist? Und kann man im Zweifelsfall nicht EntityInView benutzen?
PC: Intel Core i7 @ 4x2.93GHz | 6 GB RAM | Nvidia GeForce GT 440 | Desktop 2x1280x1024px | Windows 7 Professional 64bit
Laptop: Intel Core i7 @ 4x2.00GHz | 8 GB RAM | Nvidia GeForce GT 540M | Desktop 1366x768px | Windows 7 Home Premium 64bit

the FR3AK

BeitragDo, Feb 26, 2009 17:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Zu EntityInView:
Blitz geht aber immer nur vom MittelPunkt des Objektes aus und dann treten eben mal solche Fehler auf wie oben beschrieben.

Zu Blitz rendert nur alles was im Sichbereich ist:
Ich glaube Blitz rendert alles was im CameraRange Bereich ist oder?

aMul

Sieger des Minimalist Compo 01/13

BeitragDo, Feb 26, 2009 17:53
Antworten mit Zitat
Benutzer-Profile anzeigen
BB rendert ein Mesh komplett, sobald auch nur ein Polygon im Sichtbereich ist.
Da bei Partikelengines aber die Polygone oft jeden Frame neu erstellt werden lohnt es sich die die außerhalb des Bildschirms gerendert würden auszulassen.

EntityInView bezieht sich auf das ganze Objekt, aber eine vernünftige Partikelengine ist Singlesurface und somit gibt es nur ein Objekt in dem alle Partikel(eines Types) enthalten sind.


EDIT:
Auf den Code bezogen:
Vier mal TFormPoint für nur einen Partikel ist dreimal zu viel.
Wenn man das Partikel-Mesh an die Kamera hängt(EntityParent), braucht man den Befehl nur noch einmal(zuzüglich einem Sinus und einem Kosinus bei gedrehten Partikeln).

Wenn dann das Mesh eh an der Kamera hängt kann man übrigens auch ganz leicht und ohne großartige Rechnungen überprüfen ob die Partikel gesehen werden oder nicht, indem man einfach auf Überschneidung mit der pyramidenartige Form des Sichtfeldes prüft(oder noch simpler, aber dafür nicht so genau alle Partikel mit z<0 ausblendet)
Panic Pong - ultimate action mashup of Pong and Breakout <= aktives Spiele-Projekt, Downloads mit vielen bunten Farben!
advASCIIdraw - the advanced ASCII art program <= aktives nicht-Spiele-Projekt, must-have für ASCII/roguelike/dungeon-crawler fans!
Alter BB-Kram: ThroughTheAsteroidBelt - mit Quelltext! | RGB-Palette in 32²-Textur / Farbige Beleuchtung mit Dot3 | Stereoskopie in Blitz3D | Teleport-Animation Screensaver

PSY

BeitragDo, Feb 26, 2009 19:35
Antworten mit Zitat
Benutzer-Profile anzeigen
aMul hat Folgendes geschrieben:

EDIT:
Auf den Code bezogen:
Vier mal TFormPoint für nur einen Partikel ist dreimal zu viel.
Wenn man das Partikel-Mesh an die Kamera hängt(EntityParent), braucht man den Befehl nur noch einmal(zuzüglich einem Sinus und einem Kosinus bei gedrehten Partikeln).

Wenn dann das Mesh eh an der Kamera hängt kann man übrigens auch ganz leicht und ohne großartige Rechnungen überprüfen ob die Partikel gesehen werden oder nicht, indem man einfach auf Überschneidung mit der pyramidenartige Form des Sichtfeldes prüft(oder noch simpler, aber dafür nicht so
genau alle Partikel mit z<0 ausblendet)


Da muss ich widersprechen!
Viel zu kompliziert. Ich will ja die Particel nicht nur drehen.
Erstmal müssen sie rotieren können. Dann gibts die Option, alle Partikel auf die Kamera auszurichten. Dann brauch ich Partikel, die nach "oben" schaun, z.b. Wasserringe, Blätter, Zeitungen auf dem Boden usw.
Partikel, die sich in Kreiselbewegungen fortbewegen (Helix)
Partikel, die wachsen, schrumpfen, sich um alle Achsen drehn
uswusw...

Das soll ich alles von Hand berechnen? Wozu? Viel zu umständlich...
So erstell ich ein Ghostmesh, skalier es auf die Grösse des Partikels, und platzier den Partikel ins Ghostmesh an x,y,z. Dann richt ich das Ghostmesh aus (je nachdem mit pointcamera, aligntovector, nen pivot rotieren lassen für helix uswusw.) Dann schnapp ich mir einfach die 4 Vertexcoordinaten von dem Particle aus dem Ghostmesh und übertrag sie auf mein Hauptmesh...das ist zig-mal einfacher und nur ein Bruchteil des Aufwandes gegenüber anderen Berechnungen. Und von der Geschwindigkeit ändert das überhaupt nix, eher im Gegenteil...
ich brauch nicht einen sin oder cos befehl im ganzen system...


Zitat:
Wenn dann das Mesh eh an der Kamera hängt kann man übrigens auch ganz leicht und ohne großartige Rechnungen überprüfen ob die Partikel gesehen werden oder nicht, indem man einfach auf Überschneidung mit der pyramidenartige Form des Sichtfeldes prüft

genau das mach ich ja ....

L8er,
PSY
PSY LABS Games
Coders don't die, they just gosub without return

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group