Ich habe Probleme, meinen Kopf um das Farb-/Materialsystem von C# -WPF-Projekten zu bekommen, derzeit aktualisiere ich die Farbe eines ganzen Punktsystems auf jedem Update des Modells, wenn ich stattdessen nur die Farbe eines einzelnen Punktes aktualisieren möchte (wie es hinzugefügt wird).Aktualisiere Farbe eines einzelnen Punktes von GeometryModel3D Material statt eines ganzen Punktsystems
AggregateSystem Klasse
public class AggregateSystem {
// stack to store each particle in aggregate
private readonly Stack<AggregateParticle> particle_stack;
private readonly GeometryModel3D particle_model;
// positions, indices and texture co-ordinates for particles
private readonly Point3DCollection particle_positions;
private readonly Int32Collection triangle_indices;
private readonly PointCollection text_coords;
// brush to apply to particle_model.Material
private RadialGradientBrush rad_brush;
// ellipse for rendering
private Ellipse ellipse;
private RenderTargetBitmap render_bitmap;
public AggregateSystem() {
particle_stack = new Stack<AggregateParticle>();
particle_model = new GeometryModel3D { Geometry = new MeshGeometry3D() };
ellipse = new Ellipse {
Width = 32.0,
Height = 32.0
};
rad_brush = new RadialGradientBrush();
// fill ellipse interior using rad_brush
ellipse.Fill = rad_brush;
ellipse.Measure(new Size(32,32));
ellipse.Arrange(new Rect(0,0,32,32));
render_bitmap = new RenderTargetBitmap(32,32,96,96,PixelFormats.Pbgra32));
ImageBrush img_brush = new ImageBrush(render_bitmap);
DiffuseMaterial diff_mat = new DiffuseMaterial(img_brush);
particle_model.Material = diff_mat;
particle_positions = new Point3DCollection();
triangle_indices = new Int32Collection();
tex_coords = new PointCollection();
}
public Model3D AggregateModel => particle_model;
public void Update() {
// get the most recently added particle
AggregateParticle p = particle_stack.Peek();
// compute position index for triangle index generation
int position_index = particle_stack.Count * 4;
// create points associated with particle for circle generation
Point3D p1 = new Point3D(p.position.X, p.position.Y, p.position.Z);
Point3D p2 = new Point3D(p.position.X, p.position.Y + p.size, p.position.Z);
Point3D p3 = new Point3D(p.position.X + p.size, p.position.Y + p.size, p.position.Z);
Point3D p4 = new Point3D(p.position.X + p.size, p.position.Y, p.position.Z);
// add points to particle positions collection
particle_positions.Add(p1);
particle_positions.Add(p2);
particle_positions.Add(p3);
particle_positions.Add(p4);
// create points for texture co-ords
Point t1 = new Point(0.0, 0.0);
Point t2 = new Point(0.0, 1.0);
Point t3 = new Point(1.0, 1.0);
Point t4 = new Point(1.0, 0.0);
// add texture co-ords points to texcoords collection
tex_coords.Add(t1);
tex_coords.Add(t2);
tex_coords.Add(t3);
tex_coords.Add(t4);
// add position indices to indices collection
triangle_indices.Add(position_index);
triangle_indices.Add(position_index + 2);
triangle_indices.Add(position_index + 1);
triangle_indices.Add(position_index);
triangle_indices.Add(position_index + 3);
triangle_indices.Add(position_index + 2);
// update colour of points - **NOTE: UPDATES ENTIRE POINT SYSTEM**
// -> want to just apply colour to single particles added
rad_brush.GradientStops.Add(new GradientStop(p.colour, 0.0));
render_bitmap.Render(ellipse);
// set particle_model Geometry model properties
((MeshGeometry3D)particle_model.Geometry).Positions = particle_positions;
((MeshGeometry3D)particle_model.Geometry).TriangleIndices = triangle_indices;
((MeshGeometry3D)particle_model.Geometry).TextureCoordinates = tex_coords;
}
public void SpawnParticle(Point3D _pos, Color _col, double _size) {
AggregateParticle agg_particle = new AggregateParticle {
position = _pos, colour = _col, size = _size;
}
// push most-recently-added particle to stack
particle_stack.Push(agg_particle);
}
}
wo AggregateParticle
ein POD-Klasse ist, bestehend aus Point3D position
, Color color
und double size
Felder, die selbsterklärend sind.
Gibt es eine einfache und effiziente Methode, um die Farbe des einzelnen Partikels zu aktualisieren, wie es in der Update
Methode und nicht das gesamte System der Partikel hinzugefügt wird? Oder muss ich eine List
(oder eine ähnliche Datenstruktur) von DiffuseMaterial
Instanzen für jedes Partikel im System erstellen und Pinsel für die jeweils erforderliche Farbe auftragen?
[Letzteres ist etwas, was ich um jeden Preis vermeiden möchte, teilweise aufgrund der Tatsache, dass es große strukturelle Änderungen an meinem Code erfordern würde, und ich bin mir sicher, dass es einen besseren Weg gibt, das zu erreichen - also dort MUSS eine einfache Möglichkeit sein, Farbe auf eine Reihe von Texturkoordinaten anzuwenden, sicher ?!.]
Weitere Einzelheiten
AggregateModel
ist eine einzelne InstanzModel3D
Bereichparticle_model
entspricht, die zu einerModel3DGroup
desMainWindow
hinzugefügt wird.soll ich beachten Sie, dass, was ich speziell zu erreichen versuchen, hier ein „Gefälle“ von Farben für jedes Teilchen in einer Gesamtstruktur ist, wo ein Teilchen mit einem
Color
in einem „Temperatur-Gradient“ hat (an anderer Stelle berechnet in das Programm), das von der Reihenfolge abhängig ist, in der es erzeugt wurde - dh Partikel haben eine kältere Farbe, wenn sie früher erzeugt wurde, und eine wärmere Farbe, wenn sie später erzeugt wird. Diese Farbliste wird vorberechnet und an jedes Partikel in derUpdate
-Methode übergeben, wie oben zu sehen ist.Eine Lösung Ich versuchte, eine separate
AggregateComponent
Instanz für jedes Partikel zu erstellen, wo jedes dieser ObjekteModel3D
und damit eine entsprechende Bürste zugeordnet ist. Dann wurde eineAggregateComponentManager
Klasse erstellt, die dieList
von jedemAggregateComponent
enthielt. Diese Lösung funktioniert, aber es ist schrecklich langsam, da jede Komponente jedes Mal aktualisiert werden muss, wenn ein Partikel hinzugefügt wird, so Speicherverbrauch explodiert - gibt es eine Möglichkeit, dies anzupassen, wo ich bereits gerendertenAggregateComponent
s cache ohne ihreUpdate
Methode jeweils aufrufen müssen Zeit ein Partikel hinzugefügt wird?
Der vollständige Quellcode (C# -Code in dem DLAProject
Verzeichnis) auf GitHub zu finden: https://github.com/SJR276/DLAProject
@EvilTak Aber wie kann dann dieses Array von 'Material' auf die einzelne' particle_model' Instanz von 'AggregateSystem' angewendet werden? Soweit ich weiß, benötigt ein 'GeometryModel3D' nur eine einzige' Material'-Instanz. – ArchbishopOfBanterbury
Entschuldigung, das war ein Missverständnis meinerseits. Lesen Sie weiter: Ich sehe nicht, was Sie hier versuchen. Implementieren Sie ein Partikelsystem? Wenn dem so ist, würde ich empfehlen, separate Modelle (technisch nur ein Dreieck oder Quad) für jedes "Partikel" zu verwenden und das Rendering für jedes Partikel separat zu behandeln. – EvilTak
@EvilTak Ja, es ist im Wesentlichen ein Partikelsystem (mit speziellen Eigenschaften), das implementiert wird. Ich sehe, ich werde einen Blick auf diese Art von Lösung werfen müssen. Ich habe einen Link zum vollständigen Quellcode auf github hinzugefügt, wenn Sie den Rest der Projektstruktur sehen möchten, es gibt zu viel Code, um hier zu posten. – ArchbishopOfBanterbury