In the last post, we introduced some code to generate transient graphics using WorldGeometry.Shell(). In this post we’ll make one simple addition: we’ll add per-vertex colours, to see the effect on the generated box.
We’re not going to perform complex calculations to determine the appropriate colours for each vertex: we’ll just use the index of the vertex itself, in much the same way as we did for the faces. As faces and vertices in no way match, index-wise, we should see some interesting effects.
Here’s the modified C# code. There is only one addition to the previous code: a call to VertexData.SetTrueColors() at the end of the constructor for the TransientBox class.
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Colors;
using System.Collections.Generic;
namespace TransientSelection
{
public class TransientBox : Transient
{
// Internal state
private TextStyle _style;
Point3dCollection _verts;
IntegerCollection _faces;
EdgeData _edgeData;
FaceData _faceData;
VertexData _vertData;
public TransientBox(double side)
{
// Create the style for our text
_style = new TextStyle();
_style.Font =
new FontDescriptor("Calibri", false, true, 0, 0);
_style.TextSize = 10;
// Add our vertices manually (8 of them for a box)
_verts = new Point3dCollection();
_verts.Add(Point3d.Origin); // 0
_verts.Add(new Point3d(side, 0, 0)); // 1
_verts.Add(new Point3d(side, side, 0)); // 2
_verts.Add(new Point3d(0, side, 0)); // 3
_verts.Add(new Point3d(0, 0, side)); // 4
_verts.Add(new Point3d(side, 0, side)); // 5
_verts.Add(new Point3d(side, side, side)); // 6
_verts.Add(new Point3d(0, side, side)); // 7
// Our faces are defined in sets of 3 vertices
// (listed below two per line, each making a square face)
int[] polys =
{
0, 1, 2, 2, 3, 0, // Bottom
0, 4, 5, 5, 1, 0, // Front
1, 5, 6, 6, 2, 1, // Right
2, 6, 7, 7, 3, 2, // Back
0, 3, 7, 7, 4, 0, // Left
4, 7, 6, 6, 5, 4 // Top
};
const int polySize = 3;
// Create our faces from the polys array
_faces = new IntegerCollection();
for (int p = 0; p < (polys.Length / polySize); p++)
{
_faces.Add(polySize);
for (int v = 0; v < polySize; v++)
{
_faces.Add(polys[p * polySize + v]);
}
}
// Create our edge data
_edgeData = new EdgeData();
// Each face's edges should have the same colour as the face
_edgeData.SetColors(
new short[]
{
1, 1, 1, 2, 2, 2, 3, 3, 3,
4, 4, 4, 5, 5, 5, 6, 6, 6,
7, 7, 7, 8, 8, 8, 9, 9, 9,
10, 10, 10, 11, 11, 11, 12, 12, 12
}
);
// Create our face data
_faceData = new FaceData();
// The face colours match their edges
_faceData.SetColors(
new short[]
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
}
);
// Create our vertex data
_vertData = new VertexData();
_vertData.OrientationFlag = OrientationType.Clockwise;
_vertData.SetTrueColors(
new EntityColor[]
{
new EntityColor(ColorMethod.ByAci, 1),
new EntityColor(ColorMethod.ByAci, 2),
new EntityColor(ColorMethod.ByAci, 3),
new EntityColor(ColorMethod.ByAci, 4),
new EntityColor(ColorMethod.ByAci, 5),
new EntityColor(ColorMethod.ByAci, 6),
new EntityColor(ColorMethod.ByAci, 7),
new EntityColor(ColorMethod.ByAci, 8)
}
);
}
protected override int SubSetAttributes(DrawableTraits traits)
{
return (int)DrawableAttributes.None;
}
protected override void SubViewportDraw(ViewportDraw vd)
{
// Draw our screen-fixed text
DrawText(vd.Geometry, "ViewportDraw");
}
protected override bool SubWorldDraw(WorldDraw wd)
{
// Draw our box
wd.Geometry.Shell(
_verts, _faces, _edgeData, _faceData, _vertData, false
);
// Draw our screen-fixed text
DrawText(wd.Geometry, "WorldDraw");
return true;
}
private void DrawText(Geometry g, string text)
{
// We make use of another interface to push our transforms
if (g != null)
{
// Push our transforms onto the stack
g.PushOrientationTransform(OrientationBehavior.Screen);
g.PushPositionTransform(
PositionBehavior.Screen,
new Point2d(30, 30)
);
// Draw our screen-fixed text
g.Text(
new Point3d(0, 0, 0), // Position
new Vector3d(0, 0, 1), // Normal
new Vector3d(1, 0, 0), // Direction
text, // Text
true, // Rawness
_style // TextStyle
);
// Remember to pop our transforms off the stack
g.PopModelTransform();
g.PopModelTransform();
}
}
protected override void OnDeviceInput(DeviceInputEventArgs e)
{
base.OnDeviceInput(e);
}
protected override void OnPointInput(PointInputEventArgs e)
{
base.OnPointInput(e);
}
}
public class Commands
{
TransientBox _tb = null;
[CommandMethod("TB")]
public void TransientBox()
{
_tb = new TransientBox(10);
// Tell AutoCAD to call into this transient's extended
// protocol when appropriate
Transient.CapturedDrawable = _tb;
// Go ahead and draw the transient
TransientManager.CurrentTransientManager.AddTransient(
_tb, TransientDrawingMode.Main,
128, new IntegerCollection()
);
}
[CommandMethod("TBR")]
public void RemoveTransientBox()
{
// Erase the transient graphics and dispose of the transient
if (_tb != null)
{
TransientManager.CurrentTransientManager.EraseTransient(
_tb,
new IntegerCollection()
);
_tb.Dispose();
_tb = null;
}
}
}
}
This time when in wireframe mode, the graphics already look very different:
But we need a shaded visual style to get the full impact of the change:
The effect is fairly striking: the colours assigned to each vertex have been blended nicely across the connecting faces.