Logo
Toggle Menu
  • home
  • blog
  • about
    • about this site
    • contact
    • privacy policy
  • cinema 4d
    • plugins
    • creating c4d plugins
    • plugin cookbook
    • software
  • models
    • nodes
    • plants 1
    • other models - 1
    • other models - 2
  • osl
    • writing osl shaders
    • osl shaders for download

Creating a new plugin: 12

Ribbons

Displaying the backbone of a protein, for example as a ribbon, is an excellent way to show the structure of the protein in a way that looking at atoms and/or bonds in a chain, cannot do. This is the display mode I want to add to the plugin.

To do this, instead of drawing each atom what we will do is create a spline for each chain between some representative point in each amino acid (or nucleotide). For amino acids, although there doesn't appear to be a 'standard' method, by convention (as far as I can tell) that point is the alpha carbon in each amino acid, since all of them have one and only one atom labelled 'CA' - which is the alpha carbon. For nucleotide chains, since they don't have an alpha carbon, we will use the atom 'C1'' (that is, 'C1 prime').

Creating the spline(s)

This is really easy. For each amino acid chain, all we do is find the 'CA' atom in each residue and add that as a point in the spline. When the end of the chain is reached, the spline is created and the process repeated for the next chain. The process is the same for nucelotide chains, but we will look for the C1' atom instead. Here's the core code for how this works. We create two arrays, one for the points of a spline, and the other an array of the SplineObjects we're going to create. Then we just iterate through the atoms:

Code to iterate through atoms looking for the CA or C1' atoms.

At the end of each chain, we create the spline itself.:

Creating a SplineObject from the array of points.

We now have a SplineObject for the chain of amino acids (or nucleotides). What do we do with it? There's a complication here because the protein might have more than one chain, so we could be left with multiple splines. In theory, that's easy enough to deal with: we could make each one a child of a null object, then return the null object to the calling function (which will be GetVirtualObjects()). The problem with that is that if we then create a Sweep object, add a profile spline and then add this plugin as the direction spline, it won't work. No geometry will be created.

Instead, we can create the splines then make them all child objects of a Connect object and return that. This works fine, and using a Sweep object we can add a profile spline and create geometry to display a ribbon for each chain. Or, we could render the spline using the Hair render in the standard renderer, or render the spline in Redshift. Note that to do that, the PDBLoader plugin would have to be made editable first, because it won't render using those methods if it is not.

(As an aside, that's because we're using GetVirtualObjects to generate geometry, which we have to do to display atoms and/or bonds. To render a spline with Hair or Redshift, the object to render must be a SplineObject - but GetVirtualObjects returns a BaseObject. We could use GetContour to return a SplineObject, but that function can't return a BaseObject! As far as I know, it isn't possible for a plugin to use both GetVirtualObjects and GetContour, only one or the other. Frankly, this is a mess and it's a pity Maxon didn't do something about it when updating the API.)

This solution isn't perfect, though. We might want to colour the ribbons for the various chains, giving a different colour to each one, or add a different material to each ribbon. With only one Sweep object, we can't do that. However, we could add each SplineObject to an array, then when all the atoms are processed and the splines built, we can treat the chains separately.

Before that, however, we will need to set some basic parameters for the splines. These will be derived from the plugin interface and would include such things as the spline type, which by default is a cubic spline (but the user might want to change that), the interpolation type, and the parameters associated with that. If all we want to do is return a spline, we can return the Connect object with its child splines and there's no more to do.

Adding Sweep objects

With the splines created the only way to have different colours or materials for the chains is to create a Sweep object for each chain, colour it as required, then return all the Sweep objects as child objects of a Null object. This works perfectly, and it has the advantage of also allowing us to add a different material to each ribbon, which is great if we want to colour the ribbons with a gradient, so we can see the start and end of the chain. The downside is that this requires a fair bit of extra code to make it work, and that's after we've created the spline. Among other things, we'll have to decide which of the usual Sweep object parameters we will need to replicate in the interface.

For the parameters, we're going to want a few things:

  • a growth setting, so the chain growth can be animated;
  • a spline custom GUI in the description to reproduce the Sweep object 'Scale' parameter, which controls the size of the geometry along the length of the spline;
  • and the 'Parallel Movement' switch, because this can give some interesting results.

Implementing growth and parallel movement is simply a matter of getting the values from the plugin interface then setting them into the BaseContainer of the Sweep objects we create. However, the 'Scale' setting uses a spline custom GUI in the Sweep object and if we replicate that in the plugin interface, it isn't quite as easy to transfer the settings. Here is the code to create the Sweep:

Code to create a Sweep object for the ribbon.

What this does is get the SplineData custom data object from the plugin interface - this is 'uispline'. It also creates a new SplineData object - this is 'spdata'. Then it gets each knot from the interface spline and simply copies that into the 'spdata' object. Finally, the Sweep object's BaseContainer ('sbc') sets that SplineData object into the Sweep object. After that, all that remains is to set the growth and parallel movement parameters.

Finishing up

So, we have a Sweep object and the direction spline - there may be more than one, of course. But to complete the Sweep we need a profile spline. For user convenience, the plugin will come with a small number of preset profiles, such as a flat ribbon, thick ribbon, circular object like a tube, and so on. We can create as many of these as we like, and we can also let the user add their own profile if they want to. The preset profiles are all primitive splines with appropriate settings; a custom profile can be any spline. The final thing is to give each Sweep object a colour (the same colours as are used for chains) or a material. For materials, I decided to use a simple InExclude list which could contain as many materials as required. The first Sweep object - that is, the first chain of the protein - would get the first material from the list, the second Sweep the second material and so on. If there aren't enough materials for every Sweep object, the Sweep will simply be coloured.

The results

Below are a selection of proteins shown with various ribbon profiles, colours, and materials. The thing that stands out from this is the way you can clearly see coiling of the chains which you cannot with the other display types.

  • Glucagon
  • Insulin
  • Transferase
  • Ligase
  • Oxidoreductase
  • Insulin (again)
  • Glucagon
    Uses the default flat ribbon.
  • Insulin
    Two chains, using the thick ribbon profile.
  • Transferase
    Uses the circular profile and with a shiny green plastic material.
  • Ligase
    Four chains, no materials, uses the diamond profile.
  • Oxidoreductase
    Spline only (no Sweep object), made editable then rendered with Redshift using OpenPBR with a Ramp node.
  • Insulin (again)
    Two chains each with a different gradient material applied. Uses the rounded rectangle profile.

What next?

Next comes the trickiest part of the whole plugin, or at least, that's how I see it at the moment. Proteins can contain atoms and molecules which are not part of an amino acid or nucleotide chain, but which are essential to the protein. How do we handle those?

Page last updated July 8th 2026

Blog articles

Creating a new plugin: 13 (July 13th 2026)

Creating a new plugin: 12 (July 8th 2026)

Creating a new plugin: 11 (June 29th 2026)

Creating a new plugin: 10 (June 12th 2026)

Creating a new plugin: 9 (June 7th 2026)

Creating a new plugin: 8 (June 4th 2026)

Creating a new plugin: 7 (May 31st 2026)

Creating a new plugin: 6 (May 28th 2026)

Creating a new plugin: 5 (May 26th 2026)

Creating a new plugin: 4 (May 23rd 2026)

Creating a new plugin: 3 (May 22nd 2026)

Creating a new plugin: 2 (May 20th 2026)

Creating a new plugin: 1 (May 17th 2026)

The 'Space' plugins (May 7th 2026)

Creating PBR materials (March 24th 2026)

Data Storage - Then and Now (March 6th 2026)

Old Poser assets (March 2nd 2026)

More Noise, please (January 18th 2026)

Using GIT in VS 2022 (December 26th 2025)

Handling missing plugins (December 12th 2025)

Plugin compatibility with R2026 (November 24th 2025)

Affinity is now free! (November 3rd 2025)

World Creator 2025.1 (October 10th 2025)

So that was Cinema R2026? (September 19th 2025)

How to browse 3D assets (August 24th 2025)

Using Unity assets in Cinema 4D (August 15th 2025)

Plant Factory->Cinema 4D->World Creator (August 12th 2025)

Viewing glTF files (August 9th 2025)

Tessellation part 2 (August 5th 2025)

Shader writing with OSL - 3 (July 11th 2025)

Tessellation (June 23rd 2025)

Creating plants for C4D (June 15th 2025)

Adobe alternatives (May 28th 2025)

Using Graswald assets in C4D (May 7th 2025)

Which Mac for plugin development? (May 3rd 2025)

Why do plugin writers do it? (April 11th 2025)

Updating StarScape (February 26th 2025)

Using Cinema 4D shaders in Redshift (January 31st 2025)

PHP and MySQL (December 19th 2024)

Shader writing with OSL - 2 (November 11th 2024)

Shader writing with OSL (October 29th 2024)

StarScape (September 25th 2024)

Converting plugins from C4D 2024 to 2025 (September 16th 2024)

Cinema 4D 2025 and macOS plugins (September 15th 2025)

© 2021-2025 Microbion. All Rights Reserved.