Hello,
I’m trying to optimize the number of objects in my program to avoid performance problems. In the videos you see a box with black corners.
In the first video, the normals are ok. I made a new Geometry/Mesh for very planar face of the corner.
In the second video the normals are not ok. Here I put all planar faces into one Geometry/Mesh. In both cases, the normals should be correct. But it looks like they are not and I don’t know why. Does anyone have an Idea? Password for the videos is “JME-Forum”
Video one: https://howatherm.hartechcloud.de/index.php/s/eccJ2SoXRk4o7Sd
Video two: https://howatherm.hartechcloud.de/index.php/s/mkgDizgcxPbce5C
Source video one
public static void erzeugeGeometrieFlaechenkoerper (JMBauteil jmBauteil, LinkedList<JMFlaeche> flaechen){
Integer numberOfVertices = 0; // Summe der Eckpunkte
Integer numberOfIndexes = 0; // 3 Felder mit Punkten bilden ein Dreieck
// Die Anzahl der Normalen entspricht der Anzahl der Indexe
// Für jeden Punkt im Index gibt es eine Normale.
// Alle Normalen eines Dreiecks sind identisch (bei gekrümmten Flächen wäre das vermutlich anders)
Material mat;
Integer anzahlFlaechen = 0;
for (JMFlaeche flaeche : flaechen){ // Liste der Flächen durchlaufen
anzahlFlaechen++;
numberOfVertices = numberOfVertices + flaeche.getAnzahlPunkte(); // Anzahl der Punkte addieren
numberOfIndexes = numberOfIndexes + (flaeche.getAnzahlPunkte()-2)*3; // je 3 Punkte bilden ein Dreieck. Wenn die Fläche 5 Ecken hat
// dann werden dafür 3 Dreiecke benötigt (daher -2)
}
Vector3f[] vertices = new Vector3f[numberOfVertices]; // Feld für die Eckpunkte in der passenden Größe erzeugen
short indexes[] = new short[numberOfIndexes]; // Feld für die Indexe in der passenden Größe erzeugen
Vector3f nb[] = new Vector3f[numberOfIndexes]; // sFeld für die Normalen in der passenden Größe erzeugen
Vector2f [] texCoord = new Vector2f[4];
texCoord[0] = new Vector2f(0,0);
texCoord[1] = new Vector2f(1,0);
texCoord[2] = new Vector2f(0,1);
texCoord[3] = new Vector2f(1,1);
short points=0; // durchläuft alle Punkte
short index=0; // durchläuft die Liste aller Indizes und ihrer Normalen
anzahlFlaechen = 0;
for (JMFlaeche flaeche : flaechen){ // Liste der Flächen durchlaufen
anzahlFlaechen++;
short indexStart = points; // Der Index wird über die Punkte der aktuellen Fläche erstellt
short indexStop =(short) (indexStart + // Deshalb muss die Position des ersten Punktes des ersten Dreiecks und die
flaeche.getAnzahlPunkte()-3); // Position des ersten Punktes des letzten Dreiecks in der Liste
// aller Punkte (vertices[]) gespeichert werden.
for (Punkt3D p : flaeche.getPunkte()){ // Eckpunkte in der Liste der Eckpunkte speichern
vertices[points] = new Vector3f((float)p.x,(float)p.y,(float)p.z);
points++;
}
Vector3f normal = new Triangle(vertices[indexStart],vertices[indexStart+1],vertices[indexStart+2]).getNormal();
for (int i=indexStart; i <= indexStop; i++){ // Punkte durchlaufen (außer die letzten 2)
indexes[index] = (short)indexStart; // Punkt1 Alle Dreiecke gehen vom ersten Punkt der Fläche aus
nb[index] = normal;
index++;
indexes[index] =(short) (i+1); // Punkt 2
nb[index] = normal;
index++;
indexes[index] =(short) (i+2); // Punkt 3
nb[i+2] = normal;
nb[index] = normal;
index++;
}
} // Liste der Flächen durchlaufen
Mesh m = new Mesh(); // enthält die fertig konvertierte Mesh
// Setting buffers
m.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
m.setBuffer(VertexBuffer.Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));
m.setBuffer(VertexBuffer.Type.Index, 3, BufferUtils.createShortBuffer(indexes));
m.setBuffer(VertexBuffer.Type.Normal,3, BufferUtils.createFloatBuffer(nb));
m.updateBound();
m.setStatic();
String iD = jmBauteil.getID(); // Damit weiter unten auf die Daten der Geometrie zugegriffen werden kann
Geometry geom = new Geometry(iD, m); // wenn sie an der Node hängt
if (jmBauteil.isMarked()){ // Beuteil ist markiert
mat = MaterialListe.getMaterial(EnumMaterial.OBJEKT_MARKIERT);
} else { // Bauteil ist NICHT markiert
mat = MaterialListe.getMaterial(jmBauteil.getMaterial());
}
geom.setMaterial(mat);
geom.setShadowMode(RenderQueue.ShadowMode.Off);
jmBauteil.getNode().attachChild(geom); // Geometrie an die Node des Bauteils hängen
if (jmBauteil.isUnsichtbar()){ // Objekt unsichtbar
jmBauteil.getNode().setCullHint(Spatial.CullHint.Always); // Node nicht rendern
}
jmBauteil.getNode().setName(jmBauteil.getID()); // ID in der Node speichern
}
Source video two
public static void erzeugeGeometrieFlaechenkoerper (JMBauteil jmBauteil, LinkedList<JMFlaeche> flaechen){
Integer numberOfVertices = 0; // Summe der Eckpunkte
Integer numberOfIndexes = 0; // 3 Felder mit Punkten bilden ein Dreieck
// Die Anzahl der Normalen entspricht der Anzahl der Indexe
// Für jeden Punkt im Index gibt es eine Normale.
// Alle Normalen eines Dreiecks sind identisch (bei gekrümmten Flächen wäre das vermutlich anders)
Material mat;
Integer anzahlFlaechen = 0;
for (JMFlaeche flaeche : flaechen){ // Liste der Flächen durchlaufen
anzahlFlaechen++;
numberOfVertices = numberOfVertices + flaeche.getAnzahlPunkte(); // Anzahl der Punkte addieren
numberOfIndexes = numberOfIndexes + (flaeche.getAnzahlPunkte()-2)*3; // je 3 Punkte bilden ein Dreieck. Wenn die Fläche 5 Ecken hat
// dann werden dafür 3 Dreiecke benötigt (daher -2)
}
Vector3f[] vertices = new Vector3f[numberOfVertices]; // Feld für die Eckpunkte in der passenden Größe erzeugen
short indexes[] = new short[numberOfIndexes]; // Feld für die Indexe in der passenden Größe erzeugen
Vector3f nb[] = new Vector3f[numberOfIndexes]; // sFeld für die Normalen in der passenden Größe erzeugen
Vector2f [] texCoord = new Vector2f[4];
texCoord[0] = new Vector2f(0,0);
texCoord[1] = new Vector2f(1,0);
texCoord[2] = new Vector2f(0,1);
texCoord[3] = new Vector2f(1,1);
short points=0; // durchläuft alle Punkte
short index=0; // durchläuft die Liste aller Indizes und ihrer Normalen
anzahlFlaechen = 0;
for (JMFlaeche flaeche : flaechen){ // Liste der Flächen durchlaufen
anzahlFlaechen++;
short indexStart = points; // Der Index wird über die Punkte der aktuellen Fläche erstellt
short indexStop =(short) (indexStart + // Deshalb muss die Position des ersten Punktes des ersten Dreiecks und die
flaeche.getAnzahlPunkte()-3); // Position des ersten Punktes des letzten Dreiecks in der Liste
// aller Punkte (vertices[]) gespeichert werden.
for (Punkt3D p : flaeche.getPunkte()){ // Eckpunkte in der Liste der Eckpunkte speichern
vertices[points] = new Vector3f((float)p.x,(float)p.y,(float)p.z);
points++;
}
Vector3f normal = new Triangle(vertices[indexStart],vertices[indexStart+1],vertices[indexStart+2]).getNormal();
for (int i=indexStart; i <= indexStop; i++){ // Punkte durchlaufen (außer die letzten 2)
indexes[index] = (short)indexStart; // Punkt1 Alle Dreiecke gehen vom ersten Punkt der Fläche aus
nb[index] = normal;
index++;
indexes[index] =(short) (i+1); // Punkt 2
nb[index] = normal;
index++;
indexes[index] =(short) (i+2); // Punkt 3
nb[i+2] = normal;
nb[index] = normal;
index++;
}
} // Liste der Flächen durchlaufen
Mesh m = new Mesh(); // enthält die fertig konvertierte Mesh
// Setting buffers
m.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
m.setBuffer(VertexBuffer.Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));
m.setBuffer(VertexBuffer.Type.Index, 3, BufferUtils.createShortBuffer(indexes));
m.setBuffer(VertexBuffer.Type.Normal,3, BufferUtils.createFloatBuffer(nb));
m.updateBound();
m.setStatic();
String iD = jmBauteil.getID(); // Damit weiter unten auf die Daten der Geometrie zugegriffen werden kann
Geometry geom = new Geometry(iD, m); // wenn sie an der Node hängt
if (jmBauteil.isMarked()){ // Beuteil ist markiert
mat = MaterialListe.getMaterial(EnumMaterial.OBJEKT_MARKIERT);
} else { // Bauteil ist NICHT markiert
mat = MaterialListe.getMaterial(jmBauteil.getMaterial());
}
geom.setMaterial(mat);
geom.setShadowMode(RenderQueue.ShadowMode.Off);
jmBauteil.getNode().attachChild(geom); // Geometrie an die Node des Bauteils hängen
if (jmBauteil.isUnsichtbar()){ // Objekt unsichtbar
jmBauteil.getNode().setCullHint(Spatial.CullHint.Always); // Node nicht rendern
}
jmBauteil.getNode().setName(jmBauteil.getID()); // ID in der Node speichern
}