September 2014

Sun Mon Tue Wed Thu Fri Sat
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        








« Generating a transient box inside AutoCAD using .NET | Main | Retro computing with the Raspberry Pi »

October 01, 2012

Adding per-vertex colours to a transient AutoCAD shell using .NET

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:

Wireframe mode is a little dark

But we need a shaded visual style to get the full impact of the change:

With per-vertex colouring... ooooh

The effect is fairly striking: the colours assigned to each vertex have been blended nicely across the connecting faces.

blog comments powered by Disqus

Feed/Share

10 Random Posts