Zurück   Flashforum > Software > 3D

Antwort
 
LinkBack Themen-Optionen Ansicht
Alt 20-07-2011, 16:58   #1 (permalink)
Neuer User
 
Registriert seit: Aug 2008
Beiträge: 205
frustrum clipping

Hi hallo,

ich will eine simple Sache in 3D machen und das ohne Einsatz einer engine.


Ich hab das Problem mal im Anhang aufgezeichnet. Ich denke das ist etwas anschaulicher.


Es geht darum, dass Ebenen am viewing-Frustrum (Sichtfeld) der kamera geclippt werden, aber dadurch leerflächen im projektions-screen entstehen, wo sie eigentlich nicht sein sollten.
Kleines Beispiel: die Kamera befindet sich knapp über eine Ebene, die parellel zur z-Achse liegt. In positiver z-Richtung verschwindet diese Ebene im Fluchtpunkt. Der Teil der Ebene, der sich außerhalb des Sichtfeldes der Kamera befindet ( z.B. hinter der Kamera oder direkt unter der Kamera) muss geclippt werden. Ich berechne also den Schnittpunkt dieser Ebene mit dem Frustrum, damit ich nur den sichtbaren Bereich rendere.
In dem Fall schneidet die Ebene die near-clipping-plane.
Wenn die Ebene nun an dieser Stelle abgeschnitten wird, entsteht im Sichtfeld eine Freifläche, die doch nach meinem optischen Empfinden auch durch die Ebene gefüllt sein müßte.
Hmmm..., ich denke durch den Anhang wird das Problem noch etwas deutlicher.

Ein frustrum:
Angehängte Grafiken
Dateityp: png frustrum-clipping.png (16,4 KB, 6x aufgerufen)
Dateityp: png result.png (10,2 KB, 7x aufgerufen)
Flashesjetzt ist offline   Mit Zitat antworten
Alt 20-07-2011, 21:45   #2 (permalink)
Neuer User
 
Registriert seit: Aug 2008
Beiträge: 205
Nochmal darüber nachgedacht. Es ist natürlich korrekt so. Wenn die Ebene auf mittlerer Höhe vor dem "Auge" liegt, kann man natürlich unter sie schauen. Man muss entsprechend dafür sorgen, dass man bestimmte Abstände einhält.
Flashesjetzt ist offline   Mit Zitat antworten
Alt 20-07-2011, 22:50   #3 (permalink)
Neuer User
 
Registriert seit: May 2008
Beiträge: 109
Je näher sich die near plane an der kamera befindet, umso geringer/kleiner ist diese freie Fläche. Mit welchem Wert hast du denn die Plane bisher definiert?
Wakka ist offline   Mit Zitat antworten
Alt 21-07-2011, 17:31   #4 (permalink)
Neuer User
 
Registriert seit: Aug 2008
Beiträge: 205
Hallo Wakka,

die plane hatte die Maße 800px X 600px und war 300px vor der kamera positioniert.
Mit diesen Werten spiele ich aber auch permanent rum.
Der Effekt mußte auftreten, da sich die Kamera in einem Gang befindet (der durch vier Ebenen begrenzt wird, rechts - links -oben - unten) der auch nur 800px hoch und 600px breit war.

Ich habe die Größe der plane sehr stark reduziert.
Nun tritt das Artefakt immer noch auf, aber es ist anderer Herkunft.
Wenn die berechnten clippingpoints auf unterschiedlichen Frustrumsbegrenzungsebenen sind, wird die Ecke, bzw. 2 Ecken einfach abgeschnitten. Ich habs nochmal aufgemalt (siehe Anhang).
Das muss man beim clippen oder später beim rendern irgendwie beachten. Zu dem Thema konnte ich bisher nichts finden im Internet.
Angehängte Grafiken
Dateityp: png Problem_abgeschnittene Ebene.png (10,8 KB, 5x aufgerufen)
Dateityp: png Resultat.png (13,3 KB, 4x aufgerufen)
Flashesjetzt ist offline   Mit Zitat antworten
Alt 21-07-2011, 22:25   #5 (permalink)
Neuer User
 
Registriert seit: May 2008
Beiträge: 109
Hallo Flashesjetzt,

nach welcher Methode clippst du denn die Plane im Frustum, Sutherland-Hodgman? Ich habe jetzt nicht die Ahnung von den Möglichkeiten des nativen 3D, können Polygone mit mehr als vier Punkten definiert werden?
Wakka ist offline   Mit Zitat antworten
Alt 21-07-2011, 23:46   #6 (permalink)
Neuer User
 
Registriert seit: Aug 2008
Beiträge: 205
Ja den Algorythmus benutze ich. Möglicherweise nicht ganz schulbuchmäßig, ich habe mir das aus 2-3 sourcecodes (Tutorial 4: Clipping , 3D Clipping to an arbitrary FOV - C++ Programming Tutorials, http://www.cubic.org/docs/3dclip.htm) zusammengeschustert.
Anschauliches applet: Cohen-Sutherland Clipping applet

Ich iteriere durch alle vertexe eines polygons und nehme zwei aufeinanderfolgende Eckpunkte: vertex 1 und vertex 2.
Ich berechne für beide vertexe alle Distanzen zu den Frustrumsebenen.

Liegen beide drinnen wird abgebrochen und der vertex 1 dem output-array hinzugefügt.

Liegen beide außerhalb wird geprüft, ob beide auf derselben Seite außerhalb liegen, wenn ja wird abgebrochen, wenn nein wird ähnlich verfahren wie im weiteren Fall.

Liegt vertex 1 im sichtbaren und vertex 2 im nicht sichtbaren Bereich, dann clippe ich nach und nach zur z-near eben zur linken und rechten Frustrumsebene und zuletzt zur Boden und Deckenebene des Frustrums. Falls geclippt wurde, berechne ich zwischendurch die Distanz zu den anderen Ebenen neu.

Ich habe in den oben verlinkten Beispielen, kein Hinweis gefunden, dass ein Polygon auf eine bestimme Anzahl von Ecken begrenzt ist. Ich weiss es nicht. Das Problem wird gar nicht angesprochen. Genauso wie das Problem, wenn die Kamera so nah an eine Ebene kommt, dass die Ebene zwar noch im Frustrum liegt, aber alle vertexe außerhalb des frustrums.

Das Problem tritt allerdings nur auf, wenn man sehr grosse Ebenen bzw. Polygone hat.
Flashesjetzt ist offline   Mit Zitat antworten
Alt 23-07-2011, 02:00   #7 (permalink)
Neuer User
 
Registriert seit: May 2008
Beiträge: 109
Generell ist die Anzahl eines Polygons nicht begrenzt, auch nicht beim clipping. Wenn die Ebene im Frustum, die Vertices aber ausserhalb sind stellt dies fürs clipping auch kein Problem dar.

Zitat:
Liegt vertex 1 im sichtbaren und vertex 2 im nicht sichtbaren Bereich, dann clippe ich nach und nach zur z-near eben zur linken und rechten Frustrumsebene und zuletzt zur Boden und Deckenebene des Frustrums. Falls geclippt wurde, berechne ich zwischendurch die Distanz zu den anderen Ebenen neu.
was meinst du mit nach und nach zur z-near clippen? könntest du den Ablauf nochmal genauer erklären? vielleicht auch mal ein wenig code, kann nicht schaden
Wakka ist offline   Mit Zitat antworten
Alt 23-07-2011, 21:02   #8 (permalink)
Neuer User
 
Registriert seit: Aug 2008
Beiträge: 205
Entschuldige, ich wollte damit sagen, dass ich nach und nach zu den frustrumsebenen clippe. Erst zur nearPlane, dann zu den Frustumsebenen links und rechts und dann zu Ebenen oben und unten.

Der code ist etwas redundant. Anstatt wie beim clipping-vorgang üblich, habe ich keine while-Schleife, die die flags überprüft.
Ich clippe erst zur nearplane (oder zplane, also die plane die alles abschneidet, was sich hinter ihr befindet.)
Falls geclippt wurde, berechne ich die Distanzen neu für den nächsten möglichen clipping-vorgang.


Hm naja, ist vermutlich nicht sonderlich gelungen.

PHP-Code:
private function clipPolygon(poly:IPolygon):void
        
{
            var 
k1:int
            var 
k2:int;
            var 
outSideLeft:int 1;
            var 
outSideRight:int 2;
            var 
outSideUp:int 4;
            var 
outSideDown:int 8;
            var 
outSideBehind:int 16;
            
            var 
vertices:Vector.<Vector3D> = poly.camVertices;
            var 
maxVertices:Number vertices.length;
            
            var 
ii:int;
            var 
distRatio:Number;

            var 
tempVec1:Vector3D;
            var 
tempVec2:Vector3D;
            var 
tempVecs:Vector.<Vector3D> = new Vector.<Vector3D>();
        
            
            for (var 
i:int 0maxVerticesi++) 
            {
                
k1 0;
                
k2 0;
                
                
ii = (1) % maxVertices;
                
tempVec1 vertices[i].clone();
                
tempVec2 vertices[ii].clone();

        
                
                
//alle Distanzen ausrechnen der Vektoren zu den FrustrumEbenen
                
                
var distRight:Number =  MathUtils.distancePlaneVector(rightFrustrum.normalVecrightFrustrum.distanceToOrigintempVec1);
                var 
distRight2:Number =  MathUtils.distancePlaneVector(rightFrustrum.normalVecrightFrustrum.distanceToOrigintempVec2);
                              
                                var 
distLeft:Number =  MathUtils.distancePlaneVector(leftFrustrum.normalVecleftFrustrum.distanceToOrigintempVec1);
                                var 
distLeft2:Number =  MathUtils.distancePlaneVector(leftFrustrum.normalVecleftFrustrum.distanceToOrigintempVec2);
                
                var 
distTop:Number =  MathUtils.distancePlaneVector(topFrustrum.normalVectopFrustrum.distanceToOrigintempVec1);
                var 
distTop2:Number =  MathUtils.distancePlaneVector(topFrustrum.normalVectopFrustrum.distanceToOrigintempVec2);
                
                                var 
distBottom:Number MathUtils.distancePlaneVector(bottomFrustrum.normalVecbottomFrustrum.distanceToOrigintempVec1);
                var 
distBottom2:Number MathUtils.distancePlaneVector(bottomFrustrum.normalVecbottomFrustrum.distanceToOrigintempVec2);
                
                var 
distZPlane2:Number MathUtils.distancePlaneVector(nearZPFrustrum.normalVecnearZPFrustrum.distanceToOrigintempVec2);
                var 
distZPlane:Number MathUtils.distancePlaneVector(nearZPFrustrum.normalVecnearZPFrustrum.distanceToOrigintempVec1);
                
                
                
// flags setzen falls Vektoren sich außerhalb der Ebene befinden
                
if (distLeft 0k1 outSideLeft;
                if (
distRight 0k1 outSideRight;
                if (
distTop 0k1 |= outSideUp;
                if (
distBottom 0k1 |= outSideDown;
                if (
distZPlane 0k1 |= outSideBehind;
                
                if (
distLeft2 0k2 outSideLeft;
                if (
distRight2 0k2 outSideRight;
                if (
distTop2 0k2 |= outSideUp;
                if (
distBottom2 0k2 |= outSideDown;
                if (
distZPlane2 0k2 |= outSideBehind;
                
                
                
                
        
                
                
// wenn beide Vektoren sich auf der gleichen Seite außerhalb des Frustrums befinden, kann abgebrochen werden, Linie muss nicht gerendert werden
                
if (k1 k2)
                {
                    
trace ("gecancelt weil beide vektoren außerhalb sind");
                    continue;
                }
                

                
//wenn beide Vektoren sich innerhalb des Frustrums befinden kann abgebrochen werden, vektoren müssen nicht neu berechnet werden
                
if (!(k1 k2))
                {
                    
trace ("gecancelt weil beide vektoren drinnen sind");
                    
tempVecs.push(tempVec1);
                    continue;
                }
                
                
                if (
k1)
                {
                    
                    
//checken ob sich vektor hinter der Kamera befindet    
                    
if (distZPlane 0)
                    {

                        
distRatio distZPlane2 / (distZPlane2 distZPlane);

                        
tempVec1.tempVec2.+ (tempVec1.tempVec2.x) * distRatio;
                        
tempVec1.tempVec2.+ (tempVec1.tempVec2.y) * distRatio;
                        
                        
tempVec1.tempVec2.+ (tempVec1.tempVec2.) * distRatio;
                        
translation true;
                        
                        
                        
                    }
                    
                    if (
translation)
                    {
                        
distLeft =  MathUtils.distancePlaneVector(leftFrustrum.normalVecleftFrustrum.distanceToOrigintempVec1);
                
                        
distRight =  MathUtils.distancePlaneVector(rightFrustrum.normalVecrightFrustrum.distanceToOrigintempVec1);

                    }
                    
                    
                    
//checken ob Vektor 1 sich links oder rechts außerhalb des Frustrums befindet und transalieren
                    
if (distLeft 0)
                    {
                    
                        
distRatio =  distLeft2 / (distLeft2distLeft);
    
                        
tempVec1.tempVec2.+(tempVec1.tempVec2.x) * distRatio;
                        
tempVec1.tempVec2.+ (tempVec1.tempVec2.y) * distRatio;
                        
tempVec1.tempVec2.+ (tempVec1.tempVec2.) * distRatio;
                        
                        
translation true;
                    }
                    
                    if (
distRight 0)
                    {
                        
distRatio distRight2 / (distRight2 distRight);

                        
tempVec1.tempVec2.+(tempVec1.tempVec2.x) * distRatio;
                        
tempVec1.tempVec2.+ (tempVec1.tempVec2.y) * distRatio;
                        
tempVec1.tempVec2.+ (tempVec1.tempVec2.) * distRatio;
                        
                        
translation true;
                    }
                    
                    
//wenn vektor transaliert wurde dann distanzen neu berechnen
                    
if (translation)
                    {
                         
distTop =  MathUtils.distancePlaneVector(topFrustrum.normalVectopFrustrum.distanceToOrigintempVec1);
                         
distBottom MathUtils.distancePlaneVector(bottomFrustrum.normalVecbottomFrustrum.distanceToOrigintempVec1);

                        
translation false;

                    }
                        
                    
                    
//checken ob sich vektor über - oder unterhalb des frustrums befindet 
                    
if (distTop 0)
                    {
                        
                        
distRatio distTop2 / (distTop2 distTop);
                        
                        
tempVec1.tempVec2.+(tempVec1.tempVec2.x) * distRatio;
                        
tempVec1.tempVec2.+ (tempVec1.tempVec2.y) * distRatio;
                        
tempVec1.tempVec2.+ (tempVec1.tempVec2.) * distRatio;
                        
translation true;
                        

                    }
                    
                    if (
distBottom 0)
                    {
                        
                        
distRatio distBottom2 / (distBottom2 distBottom);
                        
                        
tempVec1.tempVec2.+(tempVec1.tempVec2.x) * distRatio;
                        
tempVec1.tempVec2.+ (tempVec1.tempVec2.y) * distRatio;
                        
tempVec1.tempVec2.+ (tempVec1.tempVec2.) * distRatio;
                        
translation true;
                        

                    }
                                
                    
                }
            
                
                
                
//erster vektor wird immer gespeichert
                
tempVecs.push(tempVec1);

                
                
//Distanzen des neu berechneten Punktes berechnen
                
distLeft =  MathUtils.distancePlaneVector(leftFrustrum.normalVecleftFrustrum.distanceToOrigintempVec1);
                
distRight =  MathUtils.distancePlaneVector(rightFrustrum.normalVecrightFrustrum.distanceToOrigintempVec1);
                
distTop =  MathUtils.distancePlaneVector(topFrustrum.normalVectopFrustrum.distanceToOrigintempVec1);
                
distBottom MathUtils.distancePlaneVector(bottomFrustrum.normalVecbottomFrustrum.distanceToOrigintempVec1);
                
distZPlane MathUtils.distancePlaneVector(nearZPFrustrum.normalVecnearZPFrustrum.distanceToOrigintempVec1);
            
                
                if (
k2)
                {
                    
                    
//checken ob sich vektor hinter der Kamera befindet    
                    
if (distZPlane2 0)
                    {
                        
                        
distRatio distZPlane / (distZPlane distZPlane2);
                        
//trace ("distRatioZ : " + distRatio);
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.x) * distRatio;
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.y) * distRatio;
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.) * distRatio;
                        
                        
translation true;
                    }
                    
                    if (
translation)
                    {

                         
distLeft2 =  MathUtils.distancePlaneVector(leftFrustrum.normalVecleftFrustrum.distanceToOrigintempVec2);
                         
distRight2 =  MathUtils.distancePlaneVector(rightFrustrum.normalVecrightFrustrum.distanceToOrigintempVec2);
                        
                        
                    }
                    

                    
//checken ob Vektor 2 sich links oder rechts außerhalb des Frustrums befindet und transalieren
                    
if (distLeft2 0)
                    {

                        
distRatio =  distLeft / (distLeftdistLeft2);

                        
tempVec2.tempVec1.+(tempVec2.tempVec1.x) * distRatio;
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.y) * distRatio;
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.) * distRatio;
                        
                        
translation true;
                    }
                    
                    if (
distRight2 0)
                    {
                        
distRatio =  distRight / (distRight distRight2);

                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.x) * distRatio;
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.y) * distRatio;
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.) * distRatio;
                        
                        
translation true;
                    }


                    if (
translation)
                    {

                        
distTop2 =  MathUtils.distancePlaneVector(topFrustrum.normalVectopFrustrum.distanceToOrigintempVec2);
                        
distBottom2 MathUtils.distancePlaneVector(bottomFrustrum.normalVecbottomFrustrum.distanceToOrigintempVec2);    
                        
translation false;
                    }
                        
                    
                    
//checken ob sich vektor über - oder unterhalb des frustrums befindet 
                    
if (distTop2 0)
                    {
                        
                        
distRatio distTop / (distTop distTop2);
                        
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.x) * distRatio;
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.y) * distRatio;
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.) * distRatio;
                        
translation true;
                    }
                    
                    if (
distBottom2 0)
                    {
                        
                        
distRatio distBottom / (distBottom distBottom2);
                        
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.x) * distRatio;
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.y) * distRatio;
                        
tempVec2.tempVec1.+ (tempVec2.tempVec1.) * distRatio;
                        
translation true;
                    }
                    
                    
            
                    
                    
                    
tempVecs.push(tempVec2);


                }
                
                
trace ("vorläufiges ergebnis : " tempVecs);
            
            }
            
            
            
poly.camVertices tempVecs;
            
trace ("endergebnis : " tempVecs);
            
            
        } 

Geändert von Flashesjetzt (23-07-2011 um 21:13 Uhr)
Flashesjetzt ist offline   Mit Zitat antworten
Alt 24-07-2011, 00:43   #9 (permalink)
Neuer User
 
Registriert seit: Aug 2008
Beiträge: 205
Zitat:
Zitat von Wakka Beitrag anzeigen
Hallo Flashesjetzt,

nach welcher Methode clippst du denn die Plane im Frustum, Sutherland-Hodgman? Ich habe jetzt nicht die Ahnung von den Möglichkeiten des nativen 3D, können Polygone mit mehr als vier Punkten definiert werden?


Ach, ich habe nach dem Cohen Sutherland Alogorithmus geclippt. Der Sutherland-Hodgman ist ja u.a. dazu gedacht um dieses Problem ein Polygon um die Ecke zu clippen, zu lösen. Na jetzt habe ich es, denke ich.
Flashesjetzt ist offline   Mit Zitat antworten
Alt 25-07-2011, 01:17   #10 (permalink)
Neuer User
 
Registriert seit: Aug 2008
Beiträge: 205
So klappts:

PHP-Code:
private function clipPolygon(poly:IPolygon):void
        
{
            
            var 
inPut:Vector.<Vector3D> = new Vector.<Vector3D>();
            var 
outPut:Vector.<Vector3D> = new Vector.<Vector3D>();
            
            
            
            
inPut inPut.concat(poly.camVertices);
            
            var 
vec1:Vector3D;
            var 
vec2:Vector3D;
            var 
clippedVec:Vector3D;
            var 
distRatio:Number;
            var 
ii:int;
            for 
each (var plane:Plane in frustrumPlanes
            {
                var 
numVecs:int inPut.length;
                
outPut = new Vector.<Vector3D>();
                for (var 
i:int 0numVecsi++ ) 
                {
                    
ii = (1) % numVecs;
                    
vec1 inPut[i];
                    
vec2 inPut[ii];
                    
                    
//trace ("vec1  ist : " + vec1);
                    //trace ("vec2  ist : " + vec2);
                    
                    
var dist1:Number MathUtils.distancePlaneVector(plane.normalVecplane.distanceToOriginvec1);
                    var 
dist2:Number MathUtils.distancePlaneVector(plane.normalVecplane.distanceToOriginvec2);
                    
                    if (
dist1 && dist2 0)
                    {
                        
//falls beide innerhalb, vec2 ins array stecken und nächsten Schleifendurchgang starten
                        //trace ("beide drin");
                        
outPut.push(vec2);
                        continue;
                    }
                    if (
dist1 && dist2 0)
                    {
                        
//falls beide außerhalb, nächsten Schleifendurchgang starten
                        //trace ("beide draussen");
                        
continue;
                    }
                    
                    if (
dist1 0)
                    {
                        
distRatio dist2 / (dist1 dist2);
                        
clippedVec = new Vector3D();
                        
clippedVec.vec2.x  - (vec1.vec2.) * distRatio;
                        
clippedVec.vec2.- (vec1.vec2.y) * distRatio;
                        
clippedVec.vec2.- (vec1.vec2.z) * distRatio;
                        
outPut.push(clippedVec);
                        
outPut.push(vec2);
                        
//trace (" vec2 liegt drinnen");
                        
                    
}
                    else if (
dist2 0)
                    {
                        
distRatio dist1 / (dist2 dist1);
                        
clippedVec = new Vector3D();
                        
clippedVec.vec1.- (vec2.vec1.) * distRatio;
                        
clippedVec.vec1.- (vec2.vec1.) * distRatio;
                        
clippedVec.vec1.- (vec2.vec1.) * distRatio;
                        
outPut.push(clippedVec);
                        
//trace ("vec 1 liegt drinnen");
                        
                    
}
                    

                }
                

                
                
inPut outPut;
            
                
                
            }
            

            
poly.camVertices outPut;

Flashesjetzt ist offline   Mit Zitat antworten
Antwort

Lesezeichen

Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind an
Pingbacks sind an
Refbacks sind an


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
[Flash CS3] MovieClip: Clipping Firemice Flash Einsteiger 1 04-05-2010 00:18
Clipping Probleme e-anima 3D 4 14-10-2009 08:10
png-Clipping? thomas_as Flash 8 2 03-01-2006 10:38
Clipping rmasterb Spielkonzepte und Spieleprogrammierung 4 16-06-2005 06:03
div clipping per js? #exec HTML und CSS 2 03-12-2003 17:52


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:59 Uhr.

Domains, Webhosting & Vserver von Host Europe
Unterstützt das Flashforum!
Adobe User Group


Copyright ©1999 – 2012 Marc Thiele