Meshes zerschneiden
Übersicht

![]() |
NoobodyBetreff: Meshes zerschneiden |
![]() Antworten mit Zitat ![]() |
---|---|---|
Dank einer Anregung von Steven04 habe ich mich daran gemacht, einen Algorithmus zu schreiben, der Meshes an einer Ebene in zwei Teile spaltet.
Die Funktion kann beliebig viele Surfaces verarbeiten und berechnet auch die Texturkoordinaten der neu gesetzten Vertices. Leider mag sie es nicht, wenn die Trennebene perfekt durch einen Vertex hindurchgeht - das quittiert sie mit der Meldung 'Something wrong here'. Die Funktion funktioniert mit allen Primitiven von Blitz, andere Meshes standen mir leider nicht zum Testen zur Verfügung. Daher wäre ich um Rückmeldung froh, wenn gewisse Meshes gehen oder auch nicht gehen. Zum Trennen des Meshs muss "SplitMesh" aufgerufen werden. Sie verlangt als ersten Parameter das Mesh, das zerschnitten werden soll, dann die Ebene in Form eines Punktes und einer Richtung. Die Ebene geht dann durch diesen Punkt und steht senkrecht auf der angegebenen Richtung. Zurückgegeben wird das Mesh, das abgespalten wurde. Der Code: Code: [AUSKLAPPEN] Graphics3D 800, 600, 0, 2
SetBuffer BackBuffer() Local Mesh = CreateCylinder() ; Hier kann man verschiedene Primitiven ausprobieren ;Local Mesh = CreateCube() ;Local Mesh = CreateCone() ;Local Mesh = CreateSphere() Local Cam = CreateCamera() PositionEntity Cam, 0, 0, -5 Local Pivot = CreatePivot() EntityParent Cam, Pivot Local MeshPivot = CreatePivot() Local Light = CreateLight( 2 ) LightRange Light, 10 PositionEntity Light, 0, 5, -2 Local X# = 0 ; Mit diesen Werten rumspielen, um andere Schnittebenen zu erzeugen Local Y# = 0 Local Z# = 0 Local NX# = 0.99 ; Würde hier 1 stehen, geht die Ebene beim Zylinder genau durch zwei Vertices, daher wird hier ein geringfügig kleinerer Wert genommen Local NY# = 1 Local NZ# = 0 Timer = CreateTimer( 60 ) While Not KeyHit( 1 ) Cls If KeyHit( 57 ) Then If NewMesh Then Y# = Y# + 0.3 Counter = MilliSecs() NewMesh = SplitMesh( Mesh, X#, Y#, Z#, NX#, NY#, NZ# ) TimeSpan = MilliSecs() - Counter EntityParent NewMesh, MeshPivot MoveEntity MeshPivot, 0, -0.3, 0 EndIf TurnEntity Pivot, 0, KeyDown( 205 ) - KeyDown( 203 ), 0 Wireframe MouseDown( 1 ) RenderWorld RenderVertices( Mesh, Cam ) If NewMesh Then For i = 1 To CountChildren( MeshPivot ) RenderVertices( GetChild( MeshPivot, i ), Cam ) Next Text 0, 0, "Verbrauchte Zeit: " + TimeSpan + "ms" EndIf Flip 0 WaitTimer Timer Wend End Function RenderVertices( Mesh, Cam ) For SurfIndex = 1 To CountSurfaces( Mesh ) Surface = GetSurface( Mesh, SurfIndex ) For VertIndex = 0 To CountVertices( Surface ) - 1 TFormPoint VertexX( Surface, VertIndex ), VertexY( Surface, VertIndex ), VertexZ( Surface, VertIndex ), Mesh, 0 CameraProject Cam, TFormedX(), TFormedY(), TFormedZ() WritePixel ProjectedX(), ProjectedY(), $FFFFFF Next Next End Function ;-----------------------------------------------------------Include------------------------------------------------------------------- Type TSplitTriangle Field Surface Field V1 Field V2 Field V3 Field D1# Field D2# Field D3# End Type Type TTriangle Field SurfIndex Field Surface Field V1 Field V2 Field V3 Field Vertex1.TVertex Field Vertex2.TVertex Field Vertex3.TVertex End Type Type TVertex Field X# Field Y# Field Z# Field U# Field V# Field ID Field Used End Type Global IntersectionX#, IntersectionY#, IntersectionZ#, IntersectionT# Function SplitMesh( Mesh, X#, Y#, Z#, NX#, NY#, NZ# ) TFormNormal NX#, NY#, NZ#, 0, Mesh NX# = TFormedX() NY# = TFormedY() NZ# = TFormedZ() TFormPoint X#, Y#, Z#, 0, Mesh X# = TFormedX() Y# = TFormedY() Z# = TFormedZ() C# = -( X#*NX# + Y#*NY# + Z#*NZ# ) For SurfIndex = 1 To CountSurfaces( Mesh ) Surface = GetSurface( Mesh, SurfIndex ) For TriIndex = 0 To CountTriangles( Surface ) - 1 V1 = TriangleVertex( Surface, TriIndex, 0 ) V2 = TriangleVertex( Surface, TriIndex, 1 ) V3 = TriangleVertex( Surface, TriIndex, 2 ) D1# = VertexX( Surface, V1 )*NX# + VertexY( Surface, V1 )*NY# + VertexZ( Surface, V1 )*NZ# + C# D2# = VertexX( Surface, V2 )*NX# + VertexY( Surface, V2 )*NY# + VertexZ( Surface, V2 )*NZ# + C# D3# = VertexX( Surface, V3 )*NX# + VertexY( Surface, V3 )*NY# + VertexZ( Surface, V3 )*NZ# + C# If Sgn( D1# ) <> Sgn( D2# ) Or Sgn( D1# ) <> Sgn( D3# ) Or Sgn( D2# ) <> Sgn( D3# ) Then SplitTriangle.TSplitTriangle = New TSplitTriangle SplitTriangle\Surface = Surface SplitTriangle\V1 = V1 SplitTriangle\V2 = V2 SplitTriangle\V3 = V3 SplitTriangle\D1# = D1# SplitTriangle\D2# = D2# SplitTriangle\D3# = D3# Else Triangle.TTriangle = New TTriangle Triangle\Surface = Surface Triangle\V1 = V1 Triangle\V2 = V2 Triangle\V3 = V3 EndIf Next ClearSurface Surface, False, True Next For SplitTriangle = Each TSplitTriangle SplitTriangle( SplitTriangle, X#, Y#, Z#, NX#, NY#, NZ# ) Next For Triangle.TTriangle = Each TTriangle AddTriangle Triangle\Surface, Triangle\V1, Triangle\V2, Triangle\V3 Next Delete Each TTriangle For SurfIndex = 1 To CountSurfaces( Mesh ) Surface = GetSurface( Mesh, SurfIndex ) For TriIndex = 0 To CountTriangles( Surface ) - 1 Triangle.TTriangle = New TTriangle Triangle\SurfIndex = SurfIndex Triangle\Surface = Surface Triangle\V1 = TriangleVertex( Surface, TriIndex, 0 ) Triangle\V2 = TriangleVertex( Surface, TriIndex, 1 ) Triangle\V3 = TriangleVertex( Surface, TriIndex, 2 ) Next ClearSurface Surface, False, True Next NewMesh = CopyMeshEx( Mesh ) For Triangle.TTriangle = Each TTriangle D1# = VertexX( Triangle\Surface, Triangle\V1 )*NX# + VertexY( Triangle\Surface, Triangle\V1 )*NY# + VertexZ( Triangle\Surface, Triangle\V1 )*NZ# + C# D2# = VertexX( Triangle\Surface, Triangle\V2 )*NX# + VertexY( Triangle\Surface, Triangle\V2 )*NY# + VertexZ( Triangle\Surface, Triangle\V2 )*NZ# + C# D3# = VertexX( Triangle\Surface, Triangle\V3 )*NX# + VertexY( Triangle\Surface, Triangle\V3 )*NY# + VertexZ( Triangle\Surface, Triangle\V3 )*NZ# + C# D1# = Floor( D1#*50 ) D2# = Floor( D2#*50 ) D3# = Floor( D3#*50 ) If Sgn( D1# ) = 1 Or Sgn( D2# ) = 1 Or Sgn( D3# ) = 1 Then AddTriangle Triangle\Surface, Triangle\V1, Triangle\V2, Triangle\V3 Else NewSurface = GetSurface( NewMesh, Triangle\SurfIndex ) AddTriangle NewSurface, Triangle\V1, Triangle\V2, Triangle\V3 EndIf Next Delete Each TTriangle Delete Each TSplitTriangle CleanMesh( Mesh ) CleanMesh( NewMesh ) UpdateNormals Mesh UpdateNormals NewMesh Return NewMesh End Function Function CopyMeshEx( Mesh ) NewMesh = CreateMesh() Brush = GetEntityBrush( Mesh ) For SurfIndex = 1 To CountSurfaces( Mesh ) Surface = GetSurface( Mesh, SurfIndex ) NewSurface = CreateSurface( NewMesh ) PaintSurface NewSurface, GetSurfaceBrush( Surface ) For VertIndex = 0 To CountVertices( Surface ) - 1 V = AddVertex( NewSurface, VertexX( Surface, VertIndex ), VertexY( Surface, VertIndex ), VertexZ( Surface, VertIndex ) ) VertexTexCoords NewSurface, V, VertexU( Surface, VertIndex ), VertexV( Surface, VertIndex ) Next For TriIndex = 0 To CountTriangles( Surface ) - 1 AddTriangle NewSurface, TriangleVertex( Surface, TriIndex, 0 ), TriangleVertex( Surface, TriIndex, 1 ), TriangleVertex( Surface, TriIndex, 2 ) Next Next PaintEntity NewMesh, Brush Return NewMesh End Function Function CleanMesh( Mesh ) For SurfIndex = 1 To CountSurfaces( Mesh ) Surface = GetSurface( Mesh, SurfIndex ) For VertIndex = 0 To CountVertices( Surface ) - 1 Vertex.TVertex = New TVertex Vertex\X# = VertexX( Surface, VertIndex ) Vertex\Y# = VertexY( Surface, VertIndex ) Vertex\Z# = VertexZ( Surface, VertIndex ) Vertex\U# = VertexU( Surface, VertIndex ) Vertex\V# = VertexV( Surface, VertIndex ) Vertex\ID = VertIndex Next For TriIndex = 0 To CountTriangles( Surface ) - 1 Triangle.TTriangle = New TTriangle For i = 0 To 2 VertIndex = TriangleVertex( Surface, TriIndex, i ) For Vertex.TVertex = Each TVertex If Vertex\ID = VertIndex Then Vertex\Used = True If i = 0 Then Triangle\Vertex1 = Vertex ElseIf i = 1 Then Triangle\Vertex2 = Vertex Else Triangle\Vertex3 = Vertex Exit EndIf Next Next Next ClearSurface Surface For Vertex.TVertex = Each TVertex If Not Vertex\Used Then Delete Vertex Else Vertex\ID = AddVertex( Surface, Vertex\X#, Vertex\Y#, Vertex\Z#, Vertex\U#, Vertex\V# ) EndIf Next For Triangle.TTriangle = Each TTriangle AddTriangle Surface, Triangle\Vertex1\ID, Triangle\Vertex2\ID, Triangle\Vertex3\ID Next Delete Each TVertex Delete Each TTriangle Next End Function Function SplitTriangle( Triangle.TSplitTriangle, X#, Y#, Z#, NX#, NY#, NZ# ) Surface = Triangle\Surface C# = -( X#*NX# + Y#*NY# + Z#*NZ# ) V1 = Triangle\V1 V2 = Triangle\V2 V3 = Triangle\V3 D1# = VertexX( Surface, V1 )*NX# + VertexY( Surface, V1 )*NY# + VertexZ( Surface, V1 )*NZ# + C# D2# = VertexX( Surface, V2 )*NX# + VertexY( Surface, V2 )*NY# + VertexZ( Surface, V2 )*NZ# + C# D3# = VertexX( Surface, V3 )*NX# + VertexY( Surface, V3 )*NY# + VertexZ( Surface, V3 )*NZ# + C# If Sgn( D1# ) <> Sgn( D2# ) Then NewV1 = SplitEdge( Surface, V1, V2, X#, Y#, Z#, NX#, NY#, NZ# ) NewV2 = NewV1 + 1 If Sgn( D1# ) <> Sgn( D3# ) Then NewV3 = SplitEdge( Surface, V1, V3, X#, Y#, Z#, NX#, NY#, NZ# ) NewV4 = NewV3 + 1 AddTriangle Surface, V1, NewV1, NewV3 AddTriangle Surface, V2, V3, NewV2 AddTriangle Surface, NewV2, V3, NewV4 ElseIf Sgn( D2# ) <> Sgn( D3# ) Then NewV3 = SplitEdge( Surface, V2, V3, X#, Y#, Z#, NX#, NY#, NZ# ) NewV4 = NewV3 + 1 AddTriangle Surface, V2, NewV3, NewV2 AddTriangle Surface, V1, NewV4, V3 AddTriangle Surface, V1, NewV1, NewV4 EndIf ElseIf Sgn( D1# ) <> Sgn( D3# ) Then NewV1 = SplitEdge( Surface, V1, V3, X#, Y#, Z#, NX#, NY#, NZ# ) NewV2 = NewV1 + 1 NewV3 = SplitEdge( Surface, V2, V3, X#, Y#, Z#, NX#, NY#, NZ# ) NewV4 = NewV3 + 1 AddTriangle Surface, V3, NewV1, NewV3 AddTriangle Surface, V1, V2, NewV2 AddTriangle Surface, V2, NewV4, NewV2 EndIf End Function Function SplitEdge( Surface, V1, V2, X#, Y#, Z#, NX#, NY#, NZ# ) V1X# = VertexX( Surface, V1 ) V1Y# = VertexY( Surface, V1 ) V1Z# = VertexZ( Surface, V1 ) V1U# = VertexU( Surface, V1 ) V1V# = VertexV( Surface, V1 ) V2X# = VertexX( Surface, V2 ) V2Y# = VertexY( Surface, V2 ) V2Z# = VertexZ( Surface, V2 ) V2U# = VertexU( Surface, V2 ) V2V# = VertexV( Surface, V2 ) If LinePlaneIntersection( V1X#, V1Y#, V1Z#, V2X# - V1X#, V2Y# - V1Y#, V2Z# - V1Z#, X#, Y#, Z#, NX#, NY#, NZ# ) Then U# = IntersectionT#*V2U# + ( 1 - IntersectionT# )*V1U# V# = IntersectionT#*V2V# + ( 1 - IntersectionT# )*V1V# V1 = AddVertex( Surface, IntersectionX#, IntersectionY#, IntersectionZ#, U#, V# ) V2 = AddVertex( Surface, IntersectionX#, IntersectionY#, IntersectionZ#, U#, V# ) Return V1 Else RuntimeError "Something wrong here." EndIf End Function Function LinePlaneIntersection( X#, Y#, Z#, VX#, VY#, VZ#, PX#, PY#, PZ#, NX#, NY#, NZ# ) T# = -( NX#*X# + NY#*Y# + NZ#*Z# - NX#*PX# - NY#*PY# - NZ#*PZ# )/( NX#*VX# + NY#*VY# + NZ#*VZ# ) T# = Floor( T#*100 )/100. If T# >= 0 And T# <= 1 Then IntersectionX# = X# + VX#*T# IntersectionY# = Y# + VY#*T# IntersectionZ# = Z# + VZ#*T# IntersectionT# = T# Return True Else Return False EndIf End Function Mit Pfeiltasten links/rechts kann man die Kamera drehen und mit Leertaste zerschneiden. Wenn man mehrmals Leertaste drückt, wird das Mesh regelrecht in Scheiben geschnitten, sieht lustig aus ![]() Die Funktion kann leider die entstandenen Schnittflächen nicht selbstständig mit Dreiecken füllen. Es entstehen also 'Löcher', durch die man ins Mesh hineinsehen kann. Daran arbeite ich aber noch - falls es funktioniert, kann man Crysis - like Bäume zerschneiden gehn ![]() Bei Bugs und Anregungen kann man sich jederzeit per PN oder hier im Thread melden. |
||
- Zuletzt bearbeitet von Noobody am Di, Apr 21, 2009 14:53, insgesamt 6-mal bearbeitet
![]() |
Xaymarehemals "Cgamer" |
![]() Antworten mit Zitat ![]() |
---|---|---|
kannst du auch sowas wie eine substract und add funktion bauen? die letzten beiden codes waren ja schon nice:)
zb sowas: https://www.blitzforum.de/upload/file.php?id=5328 mesh in mesh funktion add beide meshes endmesh(addiert und ohne unnütze vertexe/triangles) |
||
Warbseite |
![]() |
FireballFlame |
![]() Antworten mit Zitat ![]() |
---|---|---|
Beeindruckend!
Ich habe mal einige Meshes getestet; das Zerteilen an sich funktioniert wunderbar, die Texturen gehen dabei allerdings verloren. |
||
PC: Intel Core i7 @ 4x2.93GHz | 6 GB RAM | Nvidia GeForce GT 440 | Desktop 2x1280x1024px | Windows 7 Professional 64bit
Laptop: Intel Core i7 @ 4x2.00GHz | 8 GB RAM | Nvidia GeForce GT 540M | Desktop 1366x768px | Windows 7 Home Premium 64bit |
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Naja, das wäre dann Contructive Solid Geometry und geht leider über mein Wissen hinaus ![]() Es existiert aber ein Code im englischen Codearchiv dazu. Ist zwar ein wenig buggy, aber funktioniert trotzdem nicht schlecht. Die Sache mit den Texturen ist mir jetzt peinlich ![]() Da hatte ich gleich vergessen, in CleanMesh die UV - Koordinaten mit zu übertragen. Ist jetzt gefixt. |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
![]() |
Chrise |
![]() Antworten mit Zitat ![]() |
---|---|---|
rein theoretisch könnte man doch das Vertex das direkt durch die Eben verläuft verdopllen? Oder ist der "Fehler" so gewollt?
Sonst ist das ein wirklich schönes Ergebnis! |
||
Llama 1 Llama 2 Llama 3
Vielen Dank an Pummelie, der mir auf seinem Server einen Platz für LlamaNet bietet. |
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das würde die Funktion jetzt schon erledigen, nur besteht das Problem, dass der Vertex, wenn er direkt auf der Ebene liegt, von der Hesseschen Normalform zu der 'Zerschneiden' - Liste hinzugefügt wird, die LinePlaneCollision aber aufgrund kleinster Rundungsfehler den Schnittpunkt des Dreiecks nicht bestimmen kann. Ich versuche, das noch zu beheben, aber da muss ich noch eine Weile rumgrübeln.
Aber danke für das Lob ![]() |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
![]() |
FireballFlame |
![]() Antworten mit Zitat ![]() |
---|---|---|
Irgendwie scheinen 2 Schnitte hintereinander generell nicht zu gehen... aber die Texturen funktionieren jetzt ![]() |
||
PC: Intel Core i7 @ 4x2.93GHz | 6 GB RAM | Nvidia GeForce GT 440 | Desktop 2x1280x1024px | Windows 7 Professional 64bit
Laptop: Intel Core i7 @ 4x2.00GHz | 8 GB RAM | Nvidia GeForce GT 540M | Desktop 1366x768px | Windows 7 Home Premium 64bit |
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich habe die Funktion nochmal verbessert und einen Bug behoben, der die Funktion nach einmaliger Benutzung unbrauchbar machte - ich habe vergessen, nach der Funktion wieder aufzuräumen ![]() Ausserdem hatte ich gar nicht darauf geachtet, dass VertexX etc. ja unverändert sind, egal, wie das Objekt positioniert, gedreht und skaliert ist, daher wurde dann die Schnittebene falsch angesetzt. Ein einfaches TFormPoint und TFormNormal schufen da Abhilfe. Der Code ist im ersten Post nacheditiert. Wenn man nun mehrmals Leertaste drückt, wird das Mesh in Scheiben geschnitten. |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
![]() |
Chrise |
![]() Antworten mit Zitat ![]() |
---|---|---|
Bei mir kommt da etwas von wegen illegal Type conversation ![]() Übrigens ein sehr großes Lob an YellowRider mit dem Syntax Highlightning ^^ Ist echt spitze, vorallem mit den automatischen Hilfe-links |
||
Llama 1 Llama 2 Llama 3
Vielen Dank an Pummelie, der mir auf seinem Server einen Platz für LlamaNet bietet. |
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ja, die Syntaxbox hat aus irgendeinem Grund alle Backslashes rausgeschnitten.
Ich habe nun wieder auf die Codebox umgestellt, sollte jetzt gehen. |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
![]() |
Chrise |
![]() Antworten mit Zitat ![]() |
---|---|---|
sehr schön, funktioniert gut! Ist bestimmt nützlich wie Spiele wo man mit Mausgesten irgendwas zerschneiden muss, was den Weg blockiert ![]() |
||
Llama 1 Llama 2 Llama 3
Vielen Dank an Pummelie, der mir auf seinem Server einen Platz für LlamaNet bietet. |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group