3636import processing .opengl .PGraphicsOpenGL .InGeometry ;
3737import processing .opengl .PGraphicsOpenGL .TessGeometry ;
3838import processing .opengl .PGraphicsOpenGL .Tessellator ;
39+ import processing .opengl .PGraphicsOpenGL .VertexAttribute ;
3940
41+ import java .nio .Buffer ;
4042import java .util .Arrays ;
4143import java .util .HashSet ;
4244import java .util .Stack ;
@@ -533,6 +535,13 @@ protected void finalizePolyBuffers() {
533535 PGraphicsOpenGL .finalizeVertexBufferObject (glPolyShininess , context );
534536 }
535537
538+ for (VertexAttribute attrib : attribs .values ()) {
539+ if (attrib .glName != 0 ) {
540+ PGraphicsOpenGL .finalizeVertexBufferObject (attrib .glName , context );
541+ }
542+ }
543+
544+
536545 if (glPolyIndex != 0 ) {
537546 PGraphicsOpenGL .finalizeVertexBufferObject (glPolyIndex , context );
538547 }
@@ -1125,6 +1134,46 @@ public void normal(float nx, float ny, float nz) {
11251134 }
11261135 }
11271136
1137+ @ Override
1138+ public void attrib (String name , float ... values ) {
1139+ VertexAttribute attrib = attribImpl (name , PGL .FLOAT , values .length );
1140+ if (attrib != null ) attrib .set (values );
1141+ }
1142+
1143+
1144+ @ Override
1145+ public void attrib (String name , int ... values ) {
1146+ VertexAttribute attrib = attribImpl (name , PGL .INT , values .length );
1147+ if (attrib != null ) attrib .set (values );
1148+ }
1149+
1150+
1151+ @ Override
1152+ public void attrib (String name , boolean ... values ) {
1153+ VertexAttribute attrib = attribImpl (name , PGL .BOOL , values .length );
1154+ if (attrib != null ) attrib .set (values );
1155+ }
1156+
1157+
1158+ protected VertexAttribute attribImpl (String name , int type , int size ) {
1159+ if (4 < size ) {
1160+ PGraphics .showWarning ("Vertex attributes cannot have more than 4 values" );
1161+ return null ;
1162+ }
1163+ VertexAttribute attrib = attribs .get (name );
1164+ if (attrib == null ) {
1165+ attrib = new VertexAttribute (name , type , size );
1166+ attribs .put (name , attrib );
1167+ inGeo .initAttrib (attrib );
1168+ tessGeo .initAttrib (attrib );
1169+ }
1170+ if (attrib .size != size ) {
1171+ PGraphics .showWarning ("New value for vertex attribute has wrong number of values" );
1172+ return null ;
1173+ }
1174+ return attrib ;
1175+ }
1176+
11281177
11291178 @ Override
11301179 public void endShape (int mode ) {
@@ -1381,6 +1430,11 @@ protected void applyMatrixImpl(PMatrix matrix) {
13811430 firstPolyVertex , lastPolyVertex );
13821431 root .setModifiedPolyVertices (firstPolyVertex , lastPolyVertex );
13831432 root .setModifiedPolyNormals (firstPolyVertex , lastPolyVertex );
1433+ for (VertexAttribute attrib : attribs .values ()) {
1434+ if (attrib .isPosition () || attrib .isNormal ()) {
1435+ root .setModifiedPolyAttrib (attrib , firstPolyVertex , lastPolyVertex );
1436+ }
1437+ }
13841438 }
13851439
13861440 if (is3D ()) {
@@ -1604,7 +1658,7 @@ public void setVertex(int index, float x, float y, float z) {
16041658
16051659 // TODO: in certain cases (kind = TRIANGLE, etc) the correspondence between
16061660 // input and tessellated vertices is 1-1, so in those cases re-tessellation
1607- // wouldnt' be neccessary .
1661+ // wouldn't be necessary .
16081662 inGeo .vertices [3 * index + 0 ] = x ;
16091663 inGeo .vertices [3 * index + 1 ] = y ;
16101664 inGeo .vertices [3 * index + 2 ] = z ;
@@ -3784,6 +3838,15 @@ protected void initPolyBuffers() {
37843838 pgl .bufferData (PGL .ARRAY_BUFFER , sizef ,
37853839 tessGeo .polyShininessBuffer , glUsage );
37863840
3841+ for (String name : attribs .keySet ()) {
3842+ VertexAttribute attrib = attribs .get (name );
3843+ tessGeo .updateAttribBuffer (attrib .name );
3844+ if (!attrib .bufferCreated ()) attrib .createBuffer (pgl );
3845+ pgl .bindBuffer (PGL .ARRAY_BUFFER , attrib .glName );
3846+ pgl .bufferData (PGL .ARRAY_BUFFER , attrib .sizeInBytes (size ),
3847+ tessGeo .attribBuffers .get (name ), PGL .STATIC_DRAW );
3848+ }
3849+
37873850 pgl .bindBuffer (PGL .ARRAY_BUFFER , 0 );
37883851
37893852 tessGeo .updatePolyIndicesBuffer ();
@@ -3893,6 +3956,9 @@ protected boolean contextIsOutdated() {
38933956 PGraphicsOpenGL .removeVertexBufferObject (glPolySpecular , context );
38943957 PGraphicsOpenGL .removeVertexBufferObject (glPolyEmissive , context );
38953958 PGraphicsOpenGL .removeVertexBufferObject (glPolyShininess , context );
3959+ for (VertexAttribute attrib : attribs .values ()) {
3960+ PGraphicsOpenGL .removeVertexBufferObject (attrib .glName , context );
3961+ }
38963962 PGraphicsOpenGL .removeVertexBufferObject (glPolyIndex , context );
38973963
38983964 PGraphicsOpenGL .removeVertexBufferObject (glLineVertex , context );
@@ -3917,6 +3983,7 @@ protected boolean contextIsOutdated() {
39173983 glPolySpecular = 0 ;
39183984 glPolyEmissive = 0 ;
39193985 glPolyShininess = 0 ;
3986+ for (VertexAttribute attrib : attribs .values ()) attrib .glName = 0 ;
39203987 glPolyIndex = 0 ;
39213988
39223989 glLineVertex = 0 ;
@@ -3988,6 +4055,10 @@ protected void deletePolyBuffers() {
39884055 glPolyShininess = 0 ;
39894056 }
39904057
4058+ for (VertexAttribute attrib : attribs .values ()) {
4059+ attrib .deleteBuffer (pgl );
4060+ }
4061+
39914062 if (glPolyIndex != 0 ) {
39924063 PGraphicsOpenGL .deleteVertexBufferObject (glPolyIndex , context , pgl );
39934064 glPolyIndex = 0 ;
@@ -4121,6 +4192,17 @@ protected void updateGeometryImpl() {
41214192 firstModifiedPolyShininess = PConstants .MAX_INT ;
41224193 lastModifiedPolyShininess = PConstants .MIN_INT ;
41234194 }
4195+ for (String name : attribs .keySet ()) {
4196+ VertexAttribute attrib = attribs .get (name );
4197+ if (attrib .modified ) {
4198+ int offset = firstModifiedPolyVertex ;
4199+ int size = lastModifiedPolyVertex - offset + 1 ;
4200+ copyPolyAttrib (attrib , offset , size );
4201+ attrib .modified = false ;
4202+ attrib .firstModified = PConstants .MAX_INT ;
4203+ attrib .lastModified = PConstants .MIN_INT ;
4204+ }
4205+ }
41244206
41254207 if (modifiedLineVertices ) {
41264208 int offset = firstModifiedLineVertex ;
@@ -4264,6 +4346,18 @@ protected void copyPolyShininess(int offset, int size) {
42644346 }
42654347
42664348
4349+ protected void copyPolyAttrib (VertexAttribute attrib , int offset , int size ) {
4350+ tessGeo .updateAttribBuffer (attrib .name , offset , size );
4351+ pgl .bindBuffer (PGL .ARRAY_BUFFER , attrib .glName );
4352+ Buffer buf = tessGeo .attribBuffers .get (attrib .name );
4353+ buf .position (attrib .size * offset );
4354+ pgl .bufferSubData (PGL .ARRAY_BUFFER , attrib .sizeInBytes (offset ),
4355+ attrib .sizeInBytes (size ), buf );
4356+ buf .rewind ();
4357+ pgl .bindBuffer (PGL .ARRAY_BUFFER , 0 );
4358+ }
4359+
4360+
42674361 protected void copyLineVertices (int offset , int size ) {
42684362 tessGeo .updateLineVerticesBuffer (offset , size );
42694363 pgl .bindBuffer (PGL .ARRAY_BUFFER , glLineVertex );
@@ -4393,6 +4487,20 @@ protected void setModifiedPolyShininess(int first, int last) {
43934487 modified = true ;
43944488 }
43954489
4490+ protected void setModifiedPolyAttrib (VertexAttribute attrib , int first , int last ) {
4491+ if (first < attrib .firstModified ) attrib .firstModified = first ;
4492+ if (last > attrib .lastModified ) attrib .lastModified = last ;
4493+ attrib .modified = true ;
4494+ modified = true ;
4495+ }
4496+
4497+ protected void setModifiedPolyAttribs (VertexAttribute attrib , int first , int last ) {
4498+ if (first < attrib .firstModified ) attrib .firstModified = first ;
4499+ if (last > attrib .lastModified ) attrib .lastModified = last ;
4500+ attrib .modified = true ;
4501+ modified = true ;
4502+ }
4503+
43964504
43974505 protected void setModifiedLineVertices (int first , int last ) {
43984506 if (first < firstModifiedLineVertex ) firstModifiedLineVertex = first ;
0 commit comments