I have attached a simple demo project containing a teapot and a freeform. Both objects have default properties. The buffer shade model works for the teapot but not the freeform?
The buffer shade model has no effect on TGLFreeform. Instead, the normals have to be calculated manually.
Up till now I have used the method TMeshObject.BuildNormals to calculate the normals but that method produces only flat shading. All vertices used in each triangle are assigned the same normal (the code comment says it generates smoothed normals but that is not true).
To make it work I manually calculate a normal for each vertex. The calculated vertex is an average of the normals for all triangles using the vertex. For each added vertex I also add the averaged normal. This is fairly easy when adding the vertexes.
It could be great if the smoothed normals could be calculated inside the mesh object. I am not sure that is possible to do though. It requires that you know what triangles are using the vertex and I guess that that information is lost after the vertexes has been added?
I will try to explain how I created the above images
A TMeshObject (added to a TGLFreeform) is used to visualize a regular 2D grid. The grid consists of evenly spaced points in X and Y directions each representing a Z value. To create a surface, triangles are generated using the points as vertexes (same as in TGLTerrainRenderer). Now, if you draw that geometry on a piece of paper, you will se that each point (vertex) in the grid is part of up to six triangles. The normal for each vertex is calculated as an average of the normals in these triangles. For each triangle added to the TMeshObject a normal must be calculated for each of the three vertexes.
To calculate the normal for ONE vertex, the code logic goes something like this (outline only).
var
P11 : TAffineVector; //Triangle vertex
P21 : TAffineVector;
P31 : TAffineVector;
.
.
Normal : TAffineVector; //Resulting averaged normal
Normal1 : TAffineVector; //Triangle normal
Normal2 : TAffineVector;
.
.
begin
//First, calculate a normal for each of the triangles using the vertex:
Hi all, I try to use Marching Cube algorithm developed by Pavel (in GLIsoSurface.pas) to build an isosurface in a MeshObject;
It seem to work well, but now I'm using BuildNormals so I obtain a not-smoothed surface.
Now I'm tryng to calculate the smoothed normals from triangles, but I' m not an expert about these things, so I'm asking if anybody solved the problem, or has any suggestion to do it as an extension of Marching Cube algorithm. That is, is there a "simple way" to get the various triangles involved with every vertex?
thank you, in advance.
this is my code:
IsoSurf:= TIsoSurfaceExtractor.Create;
..
.. add data to IsoData field variable
..
IsoSurf.AssignData(nx, ny, nz, IsoData);
IsoSurf.MarchingCubes(1000, Vert, Trg);
with GLMesh1 do begin
Mode:=mmTriangles;
Vertices.Clear;
for i:= 0 to High(Vert) do
Vertices.AddVertex(AffineVectorMake(DX+Vert[i].X*xStep, DY-Vert[i].Y*yStep, DZ+Vert[i].Z*zStep), NullVector, AColor);
CalcNormals(fwCounterClockWise);
end;
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
TGLSceneViewer.Buffer.ShadeModel has no effect on TGLFreeform. Am I missing something?
Lars,
Give an example from official demos, please, how there was earlier and now.
PW
Hi Pavel
I have attached a simple demo project containing a teapot and a freeform. Both objects have default properties. The buffer shade model works for the teapot but not the freeform?
Lars
Thanks to the information added in another thread: https://sourceforge.net/p/glscene/discussion/93606/thread/c1ec5396/ dealing with the same problem I have now solved this problem.
The buffer shade model has no effect on TGLFreeform. Instead, the normals have to be calculated manually.
Up till now I have used the method TMeshObject.BuildNormals to calculate the normals but that method produces only flat shading. All vertices used in each triangle are assigned the same normal (the code comment says it generates smoothed normals but that is not true).
To make it work I manually calculate a normal for each vertex. The calculated vertex is an average of the normals for all triangles using the vertex. For each added vertex I also add the averaged normal. This is fairly easy when adding the vertexes.
It could be great if the smoothed normals could be calculated inside the mesh object. I am not sure that is possible to do though. It requires that you know what triangles are using the vertex and I guess that that information is lost after the vertexes has been added?
I will try to explain how I created the above images
A TMeshObject (added to a TGLFreeform) is used to visualize a regular 2D grid. The grid consists of evenly spaced points in X and Y directions each representing a Z value. To create a surface, triangles are generated using the points as vertexes (same as in TGLTerrainRenderer). Now, if you draw that geometry on a piece of paper, you will se that each point (vertex) in the grid is part of up to six triangles. The normal for each vertex is calculated as an average of the normals in these triangles. For each triangle added to the TMeshObject a normal must be calculated for each of the three vertexes.
To calculate the normal for ONE vertex, the code logic goes something like this (outline only).
var
P11 : TAffineVector; //Triangle vertex
P21 : TAffineVector;
P31 : TAffineVector;
.
.
Normal : TAffineVector; //Resulting averaged normal
Normal1 : TAffineVector; //Triangle normal
Normal2 : TAffineVector;
.
.
begin
//First, calculate a normal for each of the triangles using the vertex:
Normal1 := CalcPlaneNormal(P11, P21, P31);
Normal2 := CalcPlaneNormal(P12, P22, P32);
.
.
.
//Then, sum all calculated normals:
Normal := VectorAdd(Normal, Normal1);
Normal := VectorAdd(Normal, Normal2);
.
.
.
//Then, normalize the normal
Normal := VectorNormalize(Normal);
//Finally, when three vertexes and three normals have been prepared, they can be added to the TMeshObject as a triangle and three normals
MeshObject.Vertices.Add(Vertex1, Vertex2, Vertex3);
MeshObject.Normals.Add(VertexNormal1, VertexNormal2, VertexNormal3);
In case of other types of geometry, e.g., an isosurface, the procedure will be different.
Hi all, I try to use Marching Cube algorithm developed by Pavel (in GLIsoSurface.pas) to build an isosurface in a MeshObject;
It seem to work well, but now I'm using BuildNormals so I obtain a not-smoothed surface.
Now I'm tryng to calculate the smoothed normals from triangles, but I' m not an expert about these things, so I'm asking if anybody solved the problem, or has any suggestion to do it as an extension of Marching Cube algorithm. That is, is there a "simple way" to get the various triangles involved with every vertex?
thank you, in advance.
this is my code:
IsoSurf:= TIsoSurfaceExtractor.Create;
..
.. add data to IsoData field variable
..
IsoSurf.AssignData(nx, ny, nz, IsoData);
IsoSurf.MarchingCubes(1000, Vert, Trg);
with GLMesh1 do begin
Mode:=mmTriangles;
Vertices.Clear;
end;
Roberto,
I'm only adapted the well-known algorithms to use with GLScene v.1.2 and later
You have to looke at the example in the attachment
PW
Hi Pavel,
thank you for your answer! Now I take a look to your code;
thx again,
r.