Ich render Isoflächen mit marschierenden Cubes, (oder vielleicht marschierende Quadrate, da dies 2D ist) und ich möchte Set-Operationen wie Set-Differenz, Schnittpunkt und Union. Ich dachte, das wäre einfach zu implementieren, indem man einfach zwischen zwei Vertex-Skalaren von zwei verschiedenen impliziten Oberflächen wählt, aber das ist es nicht.CSG-Operationen auf impliziten Oberflächen mit Marching-Cubes
Für meine ersten Tests habe ich mit zwei
Kugeln
Kreise versucht, und die eingestellte Operation Unterschied. a. B. Ein Kreis bewegt sich und der andere ist stationär. Hier ist der Ansatz, den ich bei der Auswahl von Eckpunktskalaren und bei der Klassifizierung von Eckpunkten wie innen oder außen ausprobiert habe. Der Code ist in C++ geschrieben. OpenGL wird für das Rendern verwendet, aber das ist nicht wichtig. Normales Rendern ohne CSG-Operationen liefert das erwartete Ergebnis.
void march(const vec2& cmin, //min x and y for the grid cell
const vec2& cmax, //max x and y for the grid cell
std::vector<vec2>& tri,
float iso,
float (*cmp1)(const vec2&), //distance from stationary circle
float (*cmp2)(const vec2&) //distance from moving circle
)
{
unsigned int squareindex = 0;
float scalar[4];
vec2 verts[8];
/* initial setup of the grid cell */
verts[0] = vec2(cmax.x, cmax.y);
verts[2] = vec2(cmin.x, cmax.y);
verts[4] = vec2(cmin.x, cmin.y);
verts[6] = vec2(cmax.x, cmin.y);
float s1,s2;
/**********************************
********For-loop of interest******
*******Set difference between ****
*******two implicit surfaces******
**********************************/
for(int i=0,j=0; i<4; ++i, j+=2){
s1 = cmp1(verts[j]);
s2 = cmp2(verts[j]);
if((s1 < iso)){ //if inside circle1
if((s2 < iso)){ //if inside circle2
scalar[i] = s2; //then set the scalar to the moving circle
} else {
scalar[i] = s1; //only inside circle1
squareindex |= (1<<i); //mark as inside
}
}
else {
scalar[i] = s1; //inside neither circle
}
}
if(squareindex == 0)
return;
/* Usual interpolation between edge points to compute
the new intersection points */
verts[1] = mix(iso, verts[0], verts[2], scalar[0], scalar[1]);
verts[3] = mix(iso, verts[2], verts[4], scalar[1], scalar[2]);
verts[5] = mix(iso, verts[4], verts[6], scalar[2], scalar[3]);
verts[7] = mix(iso, verts[6], verts[0], scalar[3], scalar[0]);
for(int i=0; i<10; ++i){ //10 = maxmimum 3 triangles, + one end token
int index = triTable[squareindex][i]; //look up our indices for triangulation
if(index == -1)
break;
tri.push_back(verts[index]);
}
}
Das gibt mir seltsam jaggies: here http://www.mechcore.net/images/gfx/csgbug2.png
Es sieht aus wie die CSG Operation wird ohne Interpolation. Es "verwirft" einfach das ganze Dreieck. Muss ich auf andere Weise interpolieren oder die Vertex-Skalarwerte kombinieren? Ich würde gerne etwas Hilfe dabei haben. Grundsätzlich meine Implementierung von Marsch Quadraten gut funktioniert: Ein vollständiger Testfall kann HERE
EDIT heruntergeladen werden. Es ist mein skalares Feld welches gebrochen ist, und ich frage mich, wie der richtige Weg aussehen würde. Ich suche vorzugsweise für eine allgemeine Ausrichtung der drei Set-Operationen I oben,
EDIT 2 für die üblichen Primitiven (Kreis, Rechteck/Quadrat, Flugzeug) diskutiert umzusetzen: Hier sind die einige neue Bilder nach der Umsetzung der Antworter White Paper:
1.Difference
2.Intersection
3.Union
EDIT 3: Ich implementiert diese in 3D auch mit der richtigen Beschattung/Beleuchtung:
1.Difference between a greater sphere and a smaller sphere
2.Difference between a greater sphere and a smaller sphere in the center, clipped by two planes on both sides, and then union with a sphere in the center.
3.Union between two cylinders.
Hm, komisch. Das funktioniert tatsächlich, aber die Kante wird irgendwie komisch. Ich werde untersuchen, ob das ein Präzisionsproblem ist. Es erscheint jedoch nicht für normale Kreise. Hier ist ein Screenshot eines 100x100 Grids: http://www.mechcore.net/images/gfx/csgbug3.png –
Richtig, es ist ein Genauigkeitsproblem. Größere Kreise funktionieren gut, aber die Gitter-Tesselation erhöht nicht (ich verwende Floats). Große Antwort und tolles Papier. Mein tiefster Dank an Sie, mein Herr. –
Gern geschehen! Viel Glück mit Ihrem Projekt, implizite Oberflächen machen Spaß! –