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

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

1

18.06.2011, 19:35

Klappt immer noch nicht (nach langer Pause)

Hi Leute,

nachdem ich genug mit der Schule zu tun hatte, hab ich mich mal wieder an das berechnen der Normalen (kotz, brech) für MD2 Modelle gesetzt... Und ich verstehs einfach nicht, also ich denke ich weiß wie es geht, aber irgendwo hakts.
Könnt ihr euch das einmal ansehen?


(Link)


Rot = Normalen (vom Nullpunkt ausgehend, skaliert).
Licht sieht man ja.

Shader:

Quellcode

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// FÜR MODEL

uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
uniform mat3 normal_matrix; // Normalisierte Modelview Matrix

// Materialeigenschaften
uniform vec4 material_ambient; // Umgebungslicht
uniform vec4 material_diffuse; // Beleuchtung
uniform vec4 material_specular; // Highlight
uniform float material_shininess;

struct light{
    vec4 position;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    
    float constant_attenuation;
    float linear_attenuation;
    float quadratic_attenuation;
};

uniform light light0; // Lichtquelle

in vec3 a_Vertex;
in vec2 a_TexCoord0;
in vec3 a_Normal;

out vec2 texCoord0;
out vec3 normal;
out vec3 lightDir;
out vec3 halfVector;

out vec4 vertDiffuse;
out vec4 vertAmbient;
out float dist;

void main(void){        
    normal = normalize(normal_matrix*a_Normal);
    //normal = a_Normal;
    vec4 pos = modelview_matrix*vec4(a_Vertex, 1.0);

    //vec3 lightPos = (modelview_matrix*light0.position).xyz;
    vec3 lightPos = light0.position.xyz;
    lightDir = lightPos-pos.xyz;
    vec3 E = -(pos.xyz);
        
    dist = length(lightDir);
    lightDir = normalize(lightDir);
    
    halfVector = normalize(lightPos+E);
    
    vertDiffuse = material_diffuse*light0.diffuse;
    vertAmbient = material_ambient*light0.ambient;
    texCoord0 = a_TexCoord0;
    
    gl_Position = projection_matrix*pos;        
}

// FRAGMENT

precision highp float;

uniform sampler2D texture0;

uniform vec4 material_ambient;
uniform vec4 material_diffuse;
uniform vec4 material_specular;
uniform vec4 material_emissive;
uniform float material_shininess;

struct light{
    vec4 position;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    
    float constant_attenuation;
    float linear_attenuation;
    float quadratic_attenuation;
};

uniform light light0;

in vec2 texCoord0;
in vec3 normal;
in vec3 lightDir;
in vec3 halfVector;

in vec4 vertDiffuse;
in vec4 vertAmbient;
in float dist;

out vec4 outColor;

void main(void){
    vec3 N = normalize(normal);
    
    float NdotL = max(dot(N, normalize(lightDir)), 0.0);
    
    vec4 color = vec4(0.0);
    
    if(NdotL > 0.0){                
        color += vertDiffuse*NdotL;
        vec3 HV = normalize(halfVector);
        float NdotHV = max(dot(N, HV), 0.0);
        color += material_specular*light0.specular*pow(NdotHV, material_shininess); 
    }
        
    float attenuation = 1.0/(light0.constant_attenuation+ 
                             light0.linear_attenuation*dist+ 
                             light0.quadratic_attenuation*dist*dist);       
                        
    outColor = ((color*attenuation)+vertAmbient)*texture(texture0, texCoord0.st);
}

// FÜR NORMALE

uniform mat4 projection_matrix;
uniform mat4 modelview_matrix;
uniform mat3 normal_matrix; // Normalisierte Modelview Matrix

in vec3 a_Vertex;

void main(void){        
    vec4 pos = modelview_matrix*vec4(a_Vertex, 1.0);    
    gl_Position = projection_matrix*pos;    
}

// FRAGMENT

precision highp float;

out vec4 outColor;

void main(void){
    outColor = vec4(1.0, 0.0, 0.0, 1.0);
}


Modelloader (nur das wichtigste):

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// (auslesen usw.) ...

// Normalen erstellen   
    vector<bool> share;

    share.resize(m_header.numVertices);
        
    for(vector<KeyFrame>::iterator frame = m_keyFrames.begin(); frame != m_keyFrames.end(); frame++){       
        (*frame).normals.resize(m_header.numVertices);

        for(unsigned int i = 0; i < share.size(); i++){
            share[i] = false;
        }

        for(unsigned int i = 0; i < m_triangles.size(); i++){
            vec3 v1, v2, v3, vec1, vec2, normal;

            v1.x = (*frame).vertices[m_triangles[i].vertexIndex[0]].x;
            v1.y = (*frame).vertices[m_triangles[i].vertexIndex[0]].y;
            v1.z = (*frame).vertices[m_triangles[i].vertexIndex[0]].z;

            v2.x = (*frame).vertices[m_triangles[i].vertexIndex[1]].x;
            v2.y = (*frame).vertices[m_triangles[i].vertexIndex[1]].y;
            v2.z = (*frame).vertices[m_triangles[i].vertexIndex[1]].z;

            v3.x = (*frame).vertices[m_triangles[i].vertexIndex[2]].x;
            v3.y = (*frame).vertices[m_triangles[i].vertexIndex[2]].y;
            v3.z = (*frame).vertices[m_triangles[i].vertexIndex[2]].z;

            vec1 = v2-v1;
            vec2 = v3-v1;
            normal = vec1.cross(vec2);
            //normal.normalize();
                                    
            for(int v = 0; v < 3; v++){
                if(share[m_triangles[i].vertexIndex[v]]){
                    (*frame).normals[m_triangles[i].vertexIndex[v]].x += normal.x;
                    (*frame).normals[m_triangles[i].vertexIndex[v]].y += normal.y;
                    (*frame).normals[m_triangles[i].vertexIndex[v]].z += normal.z;
                }
                else{
                    (*frame).normals[m_triangles[i].vertexIndex[v]].x = normal.x;
                    (*frame).normals[m_triangles[i].vertexIndex[v]].y = normal.y;
                    (*frame).normals[m_triangles[i].vertexIndex[v]].z = normal.z;

                    share[m_triangles[i].vertexIndex[v]] = true; // teilt sich Vertex
                }               
            }
        }

        // normalisieren
        for(unsigned int i = 0; i < (*frame).normals.size(); i++){
            vec3 normal;

            normal.x = (*frame).normals[i].x;
            normal.y = (*frame).normals[i].y;
            normal.z = (*frame).normals[i].z;
            normal.normalize();

            (*frame).normals[i].x = normal.x;
            (*frame).normals[i].y = normal.y;
            (*frame).normals[i].z = normal.z;
        }
    }
        
    reorganizeVertices(); // Vertices anpassen  
    m_Frame.vertices = m_keyFrames[0].vertices; 
    m_Frame.normals = m_keyFrames[0].normals;
    generateBuffers();

    return true;
};

void md2File::generateBuffers(){
    // Vertices
    glGenBuffers(1, &m_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*m_Frame.vertices.size(), &m_Frame.vertices[0], GL_DYNAMIC_DRAW);
        
    // Texturkoordinaten
    glGenBuffers(1, &m_texCoordBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, m_texCoordBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*m_texCoords.size(), &m_texCoords[0], GL_STATIC_DRAW);

    // Normalen
    glGenBuffers(1, &m_normalBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, m_normalBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*m_Frame.normals.size(), &m_Frame.normals[0], GL_DYNAMIC_DRAW);

// TESTBUFFER = NORMALEN MIT 0|0|0 FÜR JEDE ZWEITEN

    // Testbuffer
    m_test.resize(m_keyFrames[0].normals.size()*2);
    int n = 0;

    for(unsigned int i = 0; i < m_keyFrames[0].normals.size()*2; i += 2){
        m_test[i] = Vertex();
        m_test[i+1] = m_keyFrames[0].normals[n];
        n++;
    }

    glGenBuffers(1, &m_testBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, m_testBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*m_test.size(), &m_test[0], GL_DYNAMIC_DRAW);
};

// HIER WERDEN DIE VERTICES SORTIERT (MIT HILFE DER INDICES)
// NORMALEN WERDEN MIT SORTIERT (IST DAS NÖTIG??? OHNE SIEHTS KOMISCH AUS)

void md2File::reorganizeVertices(){
    vector<Vertex> tempVertices;
    vector<texCoord> tempTexCoords;
    vector<Vertex> tempNormals;
    bool texCoordsDone = false;

    for(vector<KeyFrame>::iterator frame = m_keyFrames.begin(); frame != m_keyFrames.end(); frame++){
        tempVertices.clear();
        tempNormals.clear();

        for(unsigned int i = 0; i < m_triangles.size(); i++){
            for(int j = 0; j < 3; j++){
                tempVertices.push_back((*frame).vertices[m_triangles[i].vertexIndex[j]]);
                tempNormals.push_back((*frame).normals[m_triangles[i].vertexIndex[j]]);
                
                if(!texCoordsDone){
                    tempTexCoords.push_back(m_texCoords[m_triangles[i].texCoordIndex[j]]);
                }
            }
        }

        texCoordsDone = true;
        (*frame).vertices = tempVertices;
        (*frame).normals = tempNormals;
    }

    m_texCoords = tempTexCoords;
};


Ausgabe:

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// VORBEREITUNG (LADEN USW.)

void setup(){
    // Shader
    sp = new GLSLProgram("data/shader/model.vert", "data/shader/model.frag");
    
    if(!sp->initialize()){
        cerr<<"Could not load shader!"<<endl;
    }

    sp->bindAttrib(0, "a_Vertex");
    sp->bindAttrib(1, "a_TexCoord0");
    sp->bindAttrib(2, "a_Normal");
    sp->linkProgram();

    sp2 = new GLSLProgram("data/shader/normals.vert", "data/shader/normals.frag");
    
    if(!sp2->initialize()){
        cerr<<"Could not load shader!"<<endl;
    }

    sp2->bindAttrib(0, "a_Vertex");
    sp2->linkProgram();

    // Model
    model = new md2File();
    
    if(!model->load("data/models/earth/model.md2")){
        cerr<<"Model could not be loaded!"<<endl;
    }
    
    // Textur
    texture = new tgaFile();

    if(!texture->load("data/models/earth/model.tga")){
        cerr<<"Texture could not be loaded!"<<endl;    
        return;
    }
     
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexImage2D(GL_TEXTURE_2D,
                 0,                      
                 GL_RGB8,          
                 texture->getWidth(),          
                 texture->getHeight(), 
                 0,       
                 GL_RGB,           
                 GL_UNSIGNED_BYTE,  
                 texture->getImageData());
}

// RENDERN

void render(){      
    float modelviewMatrix[16];
    float projectionMatrix[16];
    vector<float> normalMatrix;
    
    glRotatef(-90-23.44, 1, 0, 0);
    //glRotatef(rotation, 0, 0, 1);
    glScalef(30, 30, 30);
    //rotation += 50/fps;
        
    glGetFloatv(GL_MODELVIEW_MATRIX, modelviewMatrix);
    glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
            
        sp->bindShader();

        // Matrizen
        sp->sendUniform4x4("modelview_matrix", modelviewMatrix);
        sp->sendUniform4x4("projection_matrix", projectionMatrix);
        normalMatrix = sp->normalizeMatrix(modelviewMatrix);
        sp->sendUniform3x3("normal_matrix", &normalMatrix[0]);
        sp->sendUniform("texture0", 0);

        // Materialeigenschaften
        sp->sendUniform("material_ambient", 0.2, 0.2, 0.2, 0);
        sp->sendUniform("material_diffuse", 0.4, 0.4, 0.4, 0);
        sp->sendUniform("material_specular", 1, 1, 1, 0);
        sp->sendUniform("material_shininess", 0);

        // Lichtquelle
        sp->sendUniform("light0.ambient", 1, 1, 1, 0);
        sp->sendUniform("light0.diffuse", 1, 1, 1, 0);
        sp->sendUniform("light0.specular", 1, 1, 1, 0);
        sp->sendUniform("light0.constant_attenuation", 0.1f);
        sp->sendUniform("light0.linear_attenuation", 0.3f);
        sp->sendUniform("light0.quadratic_attenuation", 0.01f);
        sp->sendUniform("light0.position", 1, 0, -1, 0);

    glBindTexture(GL_TEXTURE_2D, textureID);
            
    glEnableVertexAttribArray(0); // Vertex
    glEnableVertexAttribArray(1); // Textur
    glEnableVertexAttribArray(2); // Normalen
            
    glBindBuffer(GL_ARRAY_BUFFER, model->getVertexBuffer());    
    glVertexAttribPointer(GLint(0), 3, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, model->getTexCoordBuffer());
    glVertexAttribPointer(GLint(1), 2, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, model->getNormalBuffer());
    glVertexAttribPointer(GLint(2), 3, GL_FLOAT, GL_FALSE, 0, 0);
        
    glDrawArrays(GL_TRIANGLES, 0, model->getVerticesNumber());

    glDisableVertexAttribArray(0); 
    glDisableVertexAttribArray(1); 
    glDisableVertexAttribArray(2);
    
    // NORMALEN 
    glScalef(0.02, 0.02, 0.02);
        
    glGetFloatv(GL_MODELVIEW_MATRIX, modelviewMatrix);
    glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
            
        sp2->bindShader();

        // Matrizen
        sp2->sendUniform4x4("modelview_matrix", modelviewMatrix);
        sp2->sendUniform4x4("projection_matrix", projectionMatrix);
        normalMatrix = sp2->normalizeMatrix(modelviewMatrix);
        sp2->sendUniform3x3("normal_matrix", &normalMatrix[0]);

    glBindTexture(GL_TEXTURE_2D, textureID);
            
    glEnableVertexAttribArray(0); // Normale
            
    glBindBuffer(GL_ARRAY_BUFFER, model->getTestBuffer());  
    glVertexAttribPointer(GLint(0), 3, GL_FLOAT, GL_FALSE, 0, 0);
        
    glDrawArrays(GL_LINES, 0, model->getVerticesNumber()*2);

    glDisableVertexAttribArray(0);
}






Ich kanns nachvollziehen das nicht alles lesen zu wollen, aber vielleicht fällt euch ja beim überfliegen was auf.

MfG DK

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

2

18.06.2011, 22:25

Im Bild sind viel zu wenig Normalen zu sehen. Gib mal alle aus, dann siehst du ja ob die Berechnung generell gut aussieht.
@D13_Dreinig

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

3

18.06.2011, 23:15

5766 Vertices
5766 Normale
passt

die Werte liegen meistens zwischen 0 und 1, manchmal auch 1.#INF (?)

Mir kommt das komisch vor das die alle so als "Ring" angeordnet sind... kann doch nicht richtig sein oder? Aber ich wüsste jetzt auch nicht was an der Berechnung falsch sein sollte.

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

4

19.06.2011, 10:05

Da du die normierst sollten alle die Länge 1 haben. Ausserdem, wenn du wirklich alle Normalen zeichnest, sind diese z.T. definitiv falsch, die Kugel sollte nämlich eher "Stachelbeerenmäßig" aussehen.
@D13_Dreinig

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

5

19.06.2011, 12:02

Ich könnte dir die Füße küssen :P also es war ein kleiner Fehler in meiner Vector.h so das das normalisieren falsch war *öhhhhhhhhhhhhhhhhhhhhhhhhh*
Manchmal könnt ich mir echt selber auf die Fresse hauen.


(Link)


MfG und danke für die Hilfe
DeKugelschieber

PS: Falls noch was in der Richtung von mir kommt dann hier (Thread).

Mastermind

unregistriert

6

19.06.2011, 12:06

Das lustige ist dass man das in dem Code den du gepostet hast nicht erkennen konnte da man natürlich davon ausgeht dass "normalize" tut was dransteht.

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

7

19.06.2011, 12:11

Da hast du natürlich absolut recht, aber daran sieht man mal wieder das es oft nur an kleinigkeiten hakt :)

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

19.06.2011, 12:22

Und man sieht daran auch wieder, dass es besser ist eine bereits bestehende, optimierte und getestete Mathematik-Bibliothek zu nehmen statt selber eine neu zu schreiben.
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]

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

9

19.06.2011, 12:28

hmpf

BurningWave

Alter Hase

Beiträge: 1 106

Wohnort: Filderstadt/Konstanz

Beruf: Student

  • Private Nachricht senden

10

19.06.2011, 15:08

Und man sieht daran auch wieder, dass es besser ist eine bereits bestehende, optimierte und getestete Mathematik-Bibliothek zu nehmen statt selber eine neu zu schreiben.

Wobei man beim selbst Schreiben mehr lernt.

Werbeanzeige