Skip to main content

Dynamic parameteric plot 3D

A low-level example of working with indexed geometry

Here we will make an adapter for ParametericPlot3D to work dynamically morph one shape into another one. Since it naturally does not support dynamic updates, we need to manually wire dynamic symbols to each primitive supplying vertices, normals and indexes.

Download original notebook

Our shapes

sample[t_] := With[{
   complex = ParametricPlot3D[
     (1 - t) * {
       (2 + Cos[v]) * Cos[u],
       (2 + Cos[v]) * Sin[u],
       Sin[v]
     } + t * {
       1.16^v * Cos[v] * (1 + Cos[u]),
       -1.16^v * Sin[v] * (1 + Cos[u]),
       -2 * 1.16^v * (1 + Sin[u]) + 1.0
     },
     {u, -\[Pi], \[Pi]},
     {v, -\[Pi], \[Pi]},
     MaxRecursion -> 2,
     Mesh -> None
   ][[1, 1]]
   },
  {
   complex[[1]],
   Cases[complex[[2]], _Polygon, 6] // First // First,
   complex[[3, 2]]
  }
]

Then we can use the output of this function to feed data into our GraphicsComplex

LeakyModule[{
    vertices, normals, indices
  },
    {
      EventHandler[InputRange[0,1,0.1,0], Function[value,
        With[{res  = sample[value]},
          normals = res[[3]];
          indices = res[[2]];
          vertices = res[[1]];
        ];
      ]],

      {vertices, indices, normals} = sample[0];
      
      Graphics3D[{
        MeshMaterial[MeshToonMaterial[]], Gray, 
        SpotLight[Red, 5 {1,1,1}], SpotLight[Blue, 5 {-1,-1,1}], 
        SpotLight[Green, 5 {1,-1,1}], PointLight[Magenta, {10,10,10}],
        GraphicsComplex[vertices // Offload, {
          Polygon[indices // Offload]
        }, VertexNormals->Offload[normals, "Static"->True]]
      }, Lighting->None]
    } // Column // Panel 
]
(*BB[*)(Panel[(*GB[*){{(*VB[*)(EventObject[<|"Id" -> "6cefd35b-96e1-4165-b469-9a58a39163e1", "Initial" -> 0, "View" -> "1059ab52-7641-4ab0-8fc4-ce353d630947"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKGxqYWiYmmRrpmpuZGOqaJCYZ6FqkJZvoJqcamxqnmBkbWJqYAwB5LxUO"*)(*]VB*)}(*||*),(*||*){(*VB[*)(Graphics3D[{MeshMaterial[MeshToonMaterial[]], GrayLevel[0.5], SpotLight[RGBColor[1, 0, 0], {5, 5, 5}], SpotLight[RGBColor[0, 0, 1], {-5, -5, 5}], SpotLight[RGBColor[0, 1, 0], {5, -5, 5}], PointLight[RGBColor[1, 0, 1], {10, 10, 10}], GraphicsComplex[Offload[vertices$110624], {Polygon[Offload[indices$110624]]}, VertexNormals -> Offload[normals$110624, "Static" -> True]]}, Lighting -> None])(*,*)(*"1:eJyVkdtOwkAQhhc8gMbTK5j4AKLGWxMxwYuCphDvVzrbbrLsNLsLgbf1Pbwoe7AtqYQAF3/oP9Nv/s7cfmPMWoQQfWzlHUXC2u7p3MpA0TzjU/34xjplR8S1Cf0XVoagsyE1oDgVjDj35s+dIMqq4vvPAnEVwQKEIv738xKmudo4RxPxNDPsyFldK/HgtY8CFXcATkoJDWUafuL8SvYDViyPbgB/i6IIciCwtSthA+gW/Ilc7vHNWyK6t2sJxeuNk/VxlgtYhs27430wJpAmvmkByvAp6Lte7/754ak+f33cjk8nVinK/4wrN1cmm4h2iYjnAvSl/fNlh8ByhGpGhQ71JkOG4lbG+NQt3FAb1HsTNYfGlK5PbJfHZerdEUpYAycxnYg="*)(*]VB*)}}(*]GB*)])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KWlMIB4/kAgoyi/LTElN8S8oyczPK05jAElwgCQS81JznPIrIEpBGoNKc1KDwSakJqYEs8LUAADiShU/"*)(*]BB*)