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

Black-Panther

Alter Hase

  • »Black-Panther« ist der Autor dieses Themas

Beiträge: 1 443

Wohnort: Innsbruck

  • Private Nachricht senden

1

16.12.2005, 22:00

Berechnung der Normalvektoren

Hallo allerseits!

Ich hab die Suche gerade verwendet, doch nichts passendes gefunden, denn eigentlich müsste alles gehn!

Zu meinem Problem:
Ich habe einen 3DS-Importer geschrieben, und berechne für jeden Vertex auch einen Normalvektor, doch ist selbiger nicht immer richtig! Oftmals bleiben ganze Flächen einfach schwarz, bis ich sie von der anderen Seite anschau (Vorzeichenfehler), andere stimmen dafür perfekt, wieder andere sind ungleichmäßig beleuchtet, und wieder andere überhaupt nicht...
Ich hab inzwischen zwei Funktionsversionen geschrieben:

Beide Versionen verwenden diese Funktion zur Berechnung des Normalvektors:

C-/C++-Quelltext

1
2
3
4
5
OMEGA_API og3DVector ogUtilsTriangleNormalVector(const og3DVector& v1, const og3DVector& v2, const og3DVector& v3)
{
    //Kreuzprodukt der Verbindungsvektoren zurückgeben

    return og3DVectorNormalizeEx(og3DVectorCross(v2 - v1, v3 - v1));
}


Version 1:
Bei dieser Version hats eigentlich im Großen und Ganzen recht gut ausgeschaut, nur eben Ungleichmäßigkeiten und manche schwarze Flächen.

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
ogResult og3dsFile::CalculateNormalVectors()
{
    //Variablen

    og3DVector  vNormal1;
    og3DVector  vNormal2;
    og3DVector  vNormalSum;

    //Alle Ebenen (eines jeden Modells) durchgehen und überprüfen ob ein Vertex auch bei anderen Ebenen vorhanden ist,

    //wenn ja, dann werden die Normalvektoren kombiniert

    for(int iIndex = 0; iIndex < m_iCountObjects; iIndex++)
    {
        for(int i = 0; i < m_aModel[iIndex].wCountFaces; i++)
        {
            //Nomalvektor der Ebene

            vNormal1    = ogUtilsTriangleNormalVector(m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].a].vPosition,
                                                      m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].b].vPosition,
                                                      m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].c].vPosition);
            //Jede Ecke durchgehen

            for(int ii = 0; ii < 3; ii++)
            {
                //Jede andere Ebene durchgehen

                ZeroMemory(&vNormalSum, sizeof(og3DVector));
                vNormalSum          = vNormal1;
                int iCountTriangles = 0;
                for(int iFace2 = 0; iFace2 < m_aModel[iIndex].wCountFaces; iFace2++)
                {
                    //Alle ebenen werden überprüft, außer die ursprungsebene

                    if(iFace2 != i)
                    {
                        //Jeden einzelnen Punkt dieser Ebene durchtesten

                        for(int iFace2Corner = 0; iFace2Corner < 3; iFace2Corner++)
                        {
                            //Verwendeter Eckpunkt der selbe, Smoothinggroup und Material auch?

                            if(m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].a].vPosition == m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[iFace2].wFace[iFace2Corner]].vPosition &&
                               //m_aModel[iIndex].pFace[i].wFace[ii] == m_aModel[iIndex].pFace[iFace2].wFace[iFace2Corner] &&

                               m_aModel[iIndex].pFace[i].dwSmoothingGroop == m_aModel[iIndex].pFace[iFace2].dwSmoothingGroop &&
                               m_aModel[iIndex].pFace[i].iMaterial == m_aModel[iIndex].pFace[iFace2].iMaterial)
                            {
                                //Ja, normalVektor dieser Ebene berechnen, und zur Summe hinzufügen

                                vNormal2  = ogUtilsTriangleNormalVector(m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[iFace2].wFace[iFace2Corner]].vPosition,
                                                                        m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[iFace2].wFace[(iFace2Corner + 1) % 3]].vPosition,
                                                                        m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[iFace2].wFace[(iFace2Corner + 2) % 3]].vPosition);
                                vNormalSum   += vNormal2;
                                iCountTriangles++;
                            }
                        }
                    }

                    if(iCountTriangles > 0)
                    {
                        //Teilen, normalisieren und speichern

                        vNormalSum /= (float)iCountTriangles;
                        m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].wFace[ii]].vNormal   = og3DVectorNormalizeEx(vNormalSum);
                    }
                    else m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].wFace[ii]].vNormal  = og3DVectorNormalizeEx(vNormalSum);
                }
            }
        }
    }

    return OG_OK;
}


Version 2:
Hier sieht es katastrophal aus! Bei Quads kann man auf Grund der Beleuchtung die einzelnen Dreiecke sehen (Diagonale sichbar!). Eigentlich müsste die Funktion aber richtig sein!?

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
ogResult og3dsFile::CalculateNormalVectors()
{
    //Variablen

    og3DVector  vNormal;

    //Alle Ebenen (eines jeden Modells) durchgehen und überprüfen ob ein Vertex auch bei anderen Ebenen vorhanden ist,

    //wenn ja, dann werden die Normalvektoren kombiniert

    for(int iIndex = 0; iIndex < m_iCountObjects; iIndex++)
    {
        //Startwert setzten (für Normalvektoren = og3DVector(0.0f, 0.0f, 0.0f));

        for(int i = 0; i < m_aModel[iIndex].wCountVertizes; i++) m_aModel[iIndex].pVertex[i].vNormal = og3DVector(0.0f, 0.0f, 0.0f);

        //Alle Ebenen diese Objekts durchlaufen, und Normalvektor berechnen

        for(int i = 0; i < m_aModel[iIndex].wCountFaces; i++)
        {
            //Nomalvektor der Ebene

            vNormal     = ogUtilsTriangleNormalVector(  m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].a].vPosition,
                                                        m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].b].vPosition,
                                                        m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].c].vPosition);

            //Alle Eckpunkte der Ebene haben den selben Normalvektor

            m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].a].vNormal   += vNormal;
            m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].a].vNormal   += vNormal;
            m_aModel[iIndex].pVertex[m_aModel[iIndex].pFace[i].a].vNormal   += vNormal;
        }

        //Alle Normalvektoren normalisieren

        for(int i = 0; i < m_aModel[iIndex].wCountVertizes; i++) og3DVectorNormalizeEx(m_aModel[iIndex].pVertex[i].vNormal);
    }

    return OG_OK;
}


Schwarze Flächen entstehen nur, wenn ich zB einen Würfel von innen anschau, aber das komische daran ist, dass das nicht bei allen Wänden so ist (dann wär nämlich Culling verantwortlich). Nur bei 2 von 6 Quads ist das so...
Wäre dankbar für jede Hilfe...
stillalive studios
Drone Swarm (32.000 Dronen gleichzeitig steuern!)
facebook, twitter

Black-Panther

Alter Hase

  • »Black-Panther« ist der Autor dieses Themas

Beiträge: 1 443

Wohnort: Innsbruck

  • Private Nachricht senden

2

19.12.2005, 16:42

Kann mir wirklich niemand sagen, was an diesen Funktionen falsch sein sollte?!
stillalive studios
Drone Swarm (32.000 Dronen gleichzeitig steuern!)
facebook, twitter

baba_melone

Frischling

Beiträge: 62

Wohnort: 66879 Obermohr

Beruf: Schüler

  • Private Nachricht senden

3

23.12.2005, 17:47

Könnte es sein, dass das Problem daran liegt, dass du die Vertexnormalvektoren transformierst, und sie deswegen eben keine Normalvektoren mehr sind? Das könnte durchaus zu solchen Problemen führen

Black-Panther

Alter Hase

  • »Black-Panther« ist der Autor dieses Themas

Beiträge: 1 443

Wohnort: Innsbruck

  • Private Nachricht senden

4

23.12.2005, 19:17

Wo transformier ich denn hier die Normalvektoren!?
stillalive studios
Drone Swarm (32.000 Dronen gleichzeitig steuern!)
facebook, twitter

Werbeanzeige