# \[Solved\] How to easily overwrite partial attributes attached to a geom::SourceMods?

**URL:** <https://discourse.libcinder.org/t/solved-how-to-easily-overwrite-partial-attributes-attached-to-a-geom-sourcemods/1566>\
**Category:** Using Cinder\
**Created:** [September 11, 2019, 8:37am UTC](https://discourse.libcinder.org/t/solved-how-to-easily-overwrite-partial-attributes-attached-to-a-geom-sourcemods/1566 "2019-09-11T08:37:13Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gazoo](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/gazoo/32/61_2.png) [@Gazoo](https://discourse.libcinder.org/u/Gazoo)\
**Post date:** [September 11, 2019, 8:37am UTC](https://discourse.libcinder.org/t/solved-how-to-easily-overwrite-partial-attributes-attached-to-a-geom-sourcemods/1566/1 "2019-09-11T08:37:13Z")

</div>

Hey Embers,

I’m trying to manipulate the color (and eventually also a custom) attribute on a `geom::SourceMods` object in Cinder.

Thanks to some previous inquiries I’ve managed to execute this after the `geom::SourceMods` is turned into a Batch via the following rough code:

```auto
auto glslFullStockLambertColor = ci::gl::getStockShader( ci::gl::ShaderDef().lambert().color() );

// We can either set colors on each cube side super easily
//auto cube = ci::geom::Cube().size( ci::vec3( 20, 20, 20 ) ).colors( ci::Color( "red" ), ci::Color( "yellow" ), ci::Color( "blue" ), ci::Color( "green" ), ci::Color( "purple" ), ci::Color( "white" ) );
//mBatchCube = ci::gl::Batch::create( cube, glslFullStockLambertColor );

// Or we can add it after the cube has been created
auto cube = ci::geom::Cube().size( ci::vec3( 20, 20, 20 ) );
mBatchCube = ci::gl::Batch::create( cube >> ci::geom::Constant( ci::geom::COLOR, ci::ColorAf( "green" ) ), glslFullStockLambertColor );

int colorIdx = 1;
auto mVerticesMesh = mBatchCube->getVboMesh();
uint32_t numVerticesColors = mVerticesMesh->getNumVertices();

ci::gl::VboMesh::MappedAttrib<ci::vec4> vertexColorIter = mVerticesMesh->mapAttrib4f( ci::geom::COLOR, false );
for (uint32_t idx = 0; idx < numVerticesColors; ++idx, ++colorIdx) {
	if (<vertex should stay green>)
		continue;

	ci::vec4 color = ci::vec4( 1.0f, 0.0f, 0.0f, 1.0f );	// Fully red
	*vertexColorIter++ = color;
}
vertexColorIter.unmap();

```

**But!** I’d ideally like to actually manipulate this data prior to it turning into a batch (along with a VboMesh). Why? Because I generate my mesh in a separate thread and VBO meshes don’t share well across OpenGL contexts, as far as I am aware.

But try as I might, I’ve not found any method as simple as the one above to manipulate a partial set of attributes. My dive into the Cinder code also hasn’t been too fruitful, so perhaps the answer is… There isn’t a way, unless I’m willing to start playing around with `gl::VboMesh::Layout` which looks really scary to me. Especially because the mesh I want to manipulate colors on comes from `ci::geom::Extrude`.

Any thoughts/ideas are much appreciated!

Cheers,  
Gazoo

---

<div class="post-metadata">

**Author:** ![Gazoo](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/gazoo/32/61_2.png) [@Gazoo](https://discourse.libcinder.org/u/Gazoo)\
**Post date:** [September 12, 2019, 9:31am UTC](https://discourse.libcinder.org/t/solved-how-to-easily-overwrite-partial-attributes-attached-to-a-geom-sourcemods/1566/2 "2019-09-12T09:31:39Z")

</div>

With a little more time on my hands, and a little bit more sleuthing, it would seem this is a fairly easy way of manipulating the data prior to it becoming a thing on the GPU:

```auto
auto cube = ci::geom::Cube().size( ci::vec3( 20, 20, 20 ) );
auto cubeColored = cube >> ci::geom::Constant( ci::geom::COLOR, ci::ColorAf( "green" ) )

ci::TriMesh temp3 = newGeom;

ci::ColorAf* colorPtr = temp3.getColors<4>();
auto numVertices = temp3.getNumVertices();
for (int vertIndex = 0; vertIndex < numVertices; ++vertIndex)
{
	if ((vertIndex > 75) && (vertIndex < numVertices - 76)) {
		++colorPtr;
		continue;
	}

	*colorPtr = ci::ColorAf( 1.0f, 1.0f, 0.0f, 1.0f );
	++colorPtr;
}

```

Apparently `geom::SourceMods` can turn into a `TriMesh`, which can be manipulated.

What I’ve yet to figure out is how to add a `ci::geom::CUSTOM_0` attribute to a `TriMesh`. I’m not sure it’s possible. ☹

Any ideas / thoughts?

Cheers,  
Gazoo

---

<div class="post-metadata">

**Author:** ![lithium](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/lithium/32/38_2.png) [@lithium](https://discourse.libcinder.org/u/lithium)\
**Post date:** [September 12, 2019, 1:23pm UTC](https://discourse.libcinder.org/t/solved-how-to-easily-overwrite-partial-attributes-attached-to-a-geom-sourcemods/1566/3 "2019-09-12T13:23:50Z")

</div>

I would use an `AttribFn` here I think, though i’m not sure it provides you enough information to determine the `vertIndex` out of the box, but assuming it iterates over the vertices in order, you may be able to keep a running count to know which invocation of the lambda corresponds to which vertex, but i’ll leave that up to you to figure out. Written inline and not tested:

```cpp
auto cube = ci::geom::Cube().size( ci::vec3( 20, 20, 20 ) ) >> ci::geom::Constant( ci::geom::COLOR, ci::ColorAf( "green" ) );
cube = cube >> geom::AttribFn<ColorAf, ColorAf>( geom::COLOR, [] ( const ColorAf& color )
{
    if ( shouldStayGreen )
    {
        return color;
    }else
    {
        return ColorAf(1, 0, 0, 1); // go red!
    }
} );

```

---

<div class="post-metadata">

**Author:** ![Gazoo](https://yyz2.discourse-cdn.com/flex030/user_avatar/discourse.libcinder.org/gazoo/32/61_2.png) [@Gazoo](https://discourse.libcinder.org/u/Gazoo)\
**Post date:** [September 13, 2019, 9:55am UTC](https://discourse.libcinder.org/t/solved-how-to-easily-overwrite-partial-attributes-attached-to-a-geom-sourcemods/1566/4 "2019-09-13T09:55:53Z")

</div>

I was entirely unaware of the `AttribFn` approach. No current sample appears to use it - many thanks for highlighting this approach @lithium.

For anyone reading along, the actual implementation needs to rely on `vec`'s as these are the only defined template specializations (in the cinder library), otherwise you’ll end up with large/confusing linker errors.

A compiling example:

```auto
int vertexIndex = 0;
auto cubeWithAlteredColors = cube >> ci::geom::AttribFn<ci::vec4, ci::vec4>( ci::geom::COLOR, [&vertexIndex]( ci::vec4 ) {
	ci::vec4 color( 1.0f, 0.0f, 0.0f, 1.0f ); // Std. Red

	if (vertexIndex < 4)
		color = ci::vec4( 1.0f, 1.0f, 0.0f, 1.0f );

	++vertexIndex;
	return color;
} );

```
