i'm having trouble getting head around colour/material system of c# wpf projects, updating colour of entire system of points on each update of model when instead update colour of single point (as added).
aggregatesystem class
public class aggregatesystem { // stack store each particle in aggregate private readonly stack<aggregateparticle> particle_stack; private readonly geometrymodel3d particle_model; // positions, indices , texture co-ordinates particles private readonly point3dcollection particle_positions; private readonly int32collection triangle_indices; private readonly pointcollection text_coords; // brush apply particle_model.material private radialgradientbrush rad_brush; // ellipse 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() { // added particle aggregateparticle p = particle_stack.peek(); // compute position index triangle index generation int position_index = particle_stack.count * 4; // create points associated particle 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 particle positions collection particle_positions.add(p1); particle_positions.add(p2); particle_positions.add(p3); particle_positions.add(p4); // create points 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 texcoords collection tex_coords.add(t1); tex_coords.add(t2); tex_coords.add(t3); tex_coords.add(t4); // add position indices 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 apply colour 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 stack particle_stack.push(agg_particle); } } where aggregateparticle pod class consisting of point3d position, color color , double size fields self-explanatory.
is there simple , efficient method update colour of single particle added in update method rather entire system of particles? or need create list (or similar data structure) of diffusematerial instances each , every particle in system , apply brushes necessary colour each?
[the latter want avoid @ costs, partly due fact require large structural changes code, , there better way approach - i.e. there must simple way apply colour set of texture co-ordinates, surely?!.]
further details
aggregatemodelsinglemodel3dinstance corresponding fieldparticle_modeladdedmodel3dgroupofmainwindow.i should note trying achieve, specifically, here "gradient" of colours each particle in aggregate structure particle has
colorin "temperature-gradient" (computed elsewhere in program) dependent upon order in generated - i.e. particles have colder colour if generated earlier , warmer colour if generated later. colour list pre-computed , passed each particle inupdatemethod can seen above.one solution attempted involved creating separate
aggregatecomponentinstance each particle each of these objects has associatedmodel3d, corresponding brush.aggregatecomponentmanagerclass created containedlistof eachaggregatecomponent. solution works, horrendously slow each component has updated every time particle added memory usage explodes - there way adapt can cache renderedaggregatecomponents without having callupdatemethod each time particle added?
full source code (c# code in dlaproject directory) can found on github: https://github.com/sjr276/dlaproject
we create wpf 3d models smallish point clouds (+/- 100 k points) each point added octahedron (8 triangles) meshgeometry3d.
to allow different colors different points (we use selecting 1 or subset of points) in such point cloud, assign texture coordinates small bitmap.
at high level have code this:
bitmapsource bm = getcolorsbitmap(new list<color> { basecolor, selectedcolor }); imagebrush ib = new imagebrush(bm) { viewportunits = brushmappingmode.absolute, viewport = new rect(0, 0, 1, 1) // matches pixels in bitmap. }; geometrymodel3d model = new geometrymodel3d { material = new diffusematerial(ib) }; and texture coordinates
new point(0, 0); new point(1, 0); ... etc.
the colors bitmap comes from:
// creates bitmap has single row containing single pixels given colors. // @ 256 colors. public static bitmapsource getcolorsbitmap(ilist<color> colors) { if (colors == null) throw new argumentnullexception("colors"); if (colors.count > 256) throw new argumentoutofrangeexception("colors", "more 256 colors"); int size = colors.count; (int j = colors.count; j < 256; j++) { colors.add(colors.white); } var palette = new bitmappalette(colors); byte[] pixels = new byte[size]; (int = 0; < size; i++) { pixels[i] = (byte)i; } var bm = bitmapsource.create(size, 1, 96, 96, pixelformats.indexed8, palette, pixels, 1 * size); bm.freeze(); return bm; } we go effort cache , reuse internal geometry structure when updating point cloud.
finally display awesome helix toolkit.