void RayRenderVRML2()

in layer1/Ray.cpp [1251:1640]


void RayRenderVRML2(CRay * I, int width, int height,
                    char **vla_ptr, float front, float back,
                    float fov, float angle, float z_corr)
{

  /* 

     From: pymol-users-admin@lists.sourceforge.net on behalf of Chris Want
     Sent: Tuesday, February 07, 2006 1:47 PM
     To: pymol-users@lists.sourceforge.net
     Subject: [PyMOL] VRML patch

     Hi Warren,

     I took your advice and modified the RayRenderVRML2() function to
     support triangles. I also threw out the sphere code that was already
     there and rewrote it (the code there was for VRML1, not
     VRML2). While I was at it, I also implemented export for cylinders
     and sausages.

     The code in the attached patch (diff-ed against cvs, and tested with
     two VRML2 readers) can be regarded as being in the public domain.

     Regards,
     Chris

     cwant_at_ualberta.ca

   */

  char *vla = *vla_ptr;
  ov_size cc = 0;               /* character count */
  OrthoLineType buffer;
  float mid[3];                 /*, wid[3]; */
  float h_fov = cPI * (fov * width) / (180 * height);
  int identity = (SettingGetGlobal_i(I->G, cSetting_geometry_export_mode) == 1);

  RayExpandPrimitives(I);
  RayTransformFirst(I, 0, identity);
  RayComputeBox(I);
  /*
     mid[0] = (I->max_box[0] + I->min_box[0]) / 2.0;
     mid[1] = (I->max_box[1] + I->min_box[1]) / 2.0;
     mid[2] = (I->max_box[2] + I->min_box[2]) / 2.0;
     wid[0]  = (I->max_box[0] - I->min_box[0]);
     wid[1]  = (I->max_box[1] - I->min_box[1]);
     wid[2]  = (I->max_box[2] - I->min_box[2]);
   */

  copy3f(I->Pos, mid);
  UtilConcatVLA(&vla, &cc, "#VRML V2.0 utf8\n"  /* WLD: most VRML2 readers req. utf8 */
                "\n");
  if(!identity) {
    sprintf(buffer, "Viewpoint {\n" " position 0 0 %6.8f\n" " orientation 1 0 0 0\n" " description \"Z view\"\n" " fieldOfView %8.6f\n" /* WLD: use correct FOV */
            "}\n"
            /* WLD: only write the viewpoint which matches PyMOL
               "Viewpoint {\n"
               " position %6.8f 0 0\n"
               " orientation 0 1 0 1.570796\n"
               " description \"X view\"\n"
               "}\n"
               "Viewpoint {\n"
               " position 0 %6.8f 0\n"
               " orientation 0 -0.707106 -0.7071061 3.141592\n"
               " description \"Y view\"\n"
               "}\n" */ ,
            -z_corr,            /* *0.96646  for some reason, PyMOL and C4D cameras differ by about 3.5% ... */
            h_fov
            /*(wid[2] + wid[1]),
               (wid[0] + wid[1]),
               (wid[1] + wid[2]) */
      );
    UtilConcatVLA(&vla, &cc, buffer);
  }
  if(!identity) {
    float light[3];
    auto lightv = SettingGet<const float*>(I->G, cSetting_light);
    copy3f(lightv, light);
    normalize3f(light);
    sprintf(buffer,
            "DirectionalLight {\n"
            " direction %8.6f %8.6f %8.3f\n" "}\n", light[0], light[1], light[2]);
    UtilConcatVLA(&vla, &cc, buffer);
  }
  UtilConcatVLA(&vla, &cc,
                "NavigationInfo {\n" " headlight TRUE\n" " type \"EXAMINE\"\n" "}\n");
  {
    int a, b;
    CPrimitive *prim;
    float *vert;
    int mesh_obj = false, mesh_start = 0;

    CBasis *base = I->Basis + 1;

    for(a = 0; a < I->NPrimitive; a++) {
      prim = I->Primitive + a;
      vert = base->Vertex + 3 * (prim->vert);

      if(prim->type == cPrimTriangle) {
        if(!mesh_obj) {
          /* start mesh */
          mesh_start = a;
          UtilConcatVLA(&vla, &cc,
                        "Shape {\n"
                        " appearance Appearance {\n"
                        "  material Material { diffuseColor 1.0 1.0 1.0 }\n"
                        " }\n"
                        " geometry IndexedFaceSet {\n"
                        "  coord Coordinate {\n" "   point [\n");
          mesh_obj = true;
        }
      } else if(mesh_obj) {
        CPrimitive *cprim;
        int tri = 0;
        /* output connectivity */
        UtilConcatVLA(&vla, &cc, "   ]\n" "  }\n" "  coordIndex [\n");
        for(b = mesh_start; b < a; b++) {
          cprim = I->Primitive + b;
          if(TriangleReverse(cprim))
            sprintf(buffer, "%d %d %d -1,\n", tri, tri + 2, tri + 1);
          else
            sprintf(buffer, "%d %d %d -1,\n", tri, tri + 1, tri + 2);
          UtilConcatVLA(&vla, &cc, buffer);
          tri += 3;
        }

        /* output vertex colors */
        UtilConcatVLA(&vla, &cc,
                      "  ]\n"
                      "  colorPerVertex TRUE\n" "  color Color {\n" "   color [\n");
        for(b = mesh_start; b < a; b++) {
          cprim = I->Primitive + b;
          sprintf(buffer,
                  "%6.4f %6.4f %6.4f,\n"
                  "%6.4f %6.4f %6.4f,\n"
                  "%6.4f %6.4f %6.4f,\n",
                  cprim->c1[0], cprim->c1[1], cprim->c1[2],
                  cprim->c2[0], cprim->c2[1], cprim->c2[2],
                  cprim->c3[0], cprim->c3[1], cprim->c3[2]);
          UtilConcatVLA(&vla, &cc, buffer);
        }

        /* output vertex normals */
        UtilConcatVLA(&vla, &cc,
                      "  ] } \n"
                      "  normalPerVertex TRUE\n" "  normal Normal {\n" "   vector [\n");
        for(b = mesh_start; b < a; b++) {
          cprim = I->Primitive + b;
          {
            float *norm = base->Normal + 3 * base->Vert2Normal[cprim->vert];
            sprintf(buffer, "%6.4f %6.4f %6.4f,\n" "%6.4f %6.4f %6.4f,\n" "%6.4f %6.4f %6.4f,\n", norm[3], norm[4], norm[5],    /* transformed cprim->n1 */
                    norm[6], norm[7], norm[8],  /* transformed cprim->n2 */
                    norm[9], norm[10], norm[11]);       /* transformed cprim->n3 */
            UtilConcatVLA(&vla, &cc, buffer);
          }
        }
        UtilConcatVLA(&vla, &cc, "  ] }\n" "  normalIndex [ \n");
        tri = 0;
        for(b = mesh_start; b < a; b++) {
          cprim = I->Primitive + b;
          if(TriangleReverse(cprim))
            sprintf(buffer, "%d %d %d -1,\n", tri, tri + 2, tri + 1);
          else
            sprintf(buffer, "%d %d %d -1,\n", tri, tri + 1, tri + 2);
          UtilConcatVLA(&vla, &cc, buffer);
          tri += 3;
        }

        /* close mesh */
        UtilConcatVLA(&vla, &cc, " ] \n" " }\n" "}\n");
        mesh_obj = false;
      }

      switch (prim->type) {
      case cPrimSphere:
        sprintf(buffer,
                "Transform {\n"
                " translation %8.6f %8.6f %8.6f\n"
                " children Shape {\n"
                "  geometry Sphere { radius %8.6f }\n"
                "  appearance Appearance {\n"
                "   material Material { diffuseColor %6.4f %6.4f %6.4f \n"
                "                       specularColor 0.8 0.8 0.8 \n"
                "                       shininess 0.8 }\n"
                "  }\n"
                " }\n"
                "}\n",
                vert[0] - mid[0],
                vert[1] - mid[1],
                vert[2] - mid[2], prim->r1, prim->c1[0], prim->c1[1], prim->c1[2]);
        UtilConcatVLA(&vla, &cc, buffer);
        break;
      case cPrimCone:
        /* TO DO */
        break;
      case cPrimCylinder:
      case cPrimSausage:
        {
          float *d, vert2[3], axis[3], angle;
          OrthoLineType geometry;
          /* find the axis and angle that will rotate the y axis onto
           * the direction of the length of the cylinder
           */
          d = base->Normal + 3 * base->Vert2Normal[prim->vert];
          if((d[0] * d[0] + d[2] * d[2]) < 0.000001) {
            /* parallel with y */
            axis[0] = 1.0;
            axis[1] = 0.0;
            axis[2] = 0.0;
            if(d[1] > 0) {
              angle = 0.0;
            } else {
              angle = cPI;
            }
          } else {
            axis[0] = d[2];
            axis[1] = 0.0;
            axis[2] = -d[0];
            normalize3f(axis);
            angle = d[1];
            if(angle > 1.0)
              angle = 1.0;
            else if(angle < -1.0)
              angle = -1.0;
            angle = acos(angle);
          }
          /* vrml cylinders have origin in middle, not tip, that is why we
           * use prim->l1/2
           */
          scale3f(d, prim->l1 / 2, vert2);
          add3f(vert, vert2, vert2);
          if(prim->type == cPrimSausage) {
            OrthoLineType geom_add;
            sprintf(geometry,
                    "  Shape {\n"
                    "   geometry Cylinder {\n"
                    "    radius %8.6f\n"
                    "    height %8.6f\n"
                    "    bottom FALSE\n"
                    "    top    FALSE\n"
                    "   }\n"
                    "   appearance Appearance {\n"
                    "   material Material { diffuseColor %6.4f %6.4f %6.4f \n"
                    "                       specularColor 0.8 0.8 0.8 \n"
                    "                       shininess 0.8 }\n"
                    "   }\n",
                    prim->r1, prim->l1,
                    (prim->c1[0] + prim->c2[0]) / 2,
                    (prim->c1[1] + prim->c2[1]) / 2, (prim->c1[2] + prim->c2[2]) / 2);
            /* WLD: format string split to comply with ISO C89 standards */
            sprintf(geom_add,
                    "  }\n"
                    "  Transform {\n"
                    "   translation 0.0 %8.6f 0.0\n"
                    "   children Shape {\n"
                    "    geometry Sphere { radius %8.6f }\n"
                    "    appearance Appearance {\n"
                    "   material Material { diffuseColor %6.4f %6.4f %6.4f \n"
                    "                       specularColor 0.8 0.8 0.8 \n"
                    "                       shininess 0.8 }\n"
                    "    }\n"
                    "   }\n"
                    "  }\n", prim->l1 / 2, prim->r1, prim->c1[0], prim->c1[1], prim->c1[2]
              );
            strcat(geometry, geom_add);
            /* WLD: format string split to comply with ISO C89 standards */
            sprintf(geom_add,
                    "  Transform {\n"
                    "   translation 0.0 %8.6f 0.0\n"
                    "   children Shape {\n"
                    "    geometry Sphere { radius %8.6f }\n"
                    "    appearance Appearance {\n"
                    "   material Material { diffuseColor %6.4f %6.4f %6.4f \n"
                    "                       specularColor 0.8 0.8 0.8 \n"
                    "                       shininess 0.8 }\n"
                    "    }\n"
                    "   }\n"
                    "  }\n",
                    -prim->l1 / 2, prim->r1, prim->c2[0], prim->c2[1], prim->c2[2]);
            strcat(geometry, geom_add);
          } else {
            sprintf(geometry,
                    "  Shape {\n"
                    "   geometry Cylinder {\n"
                    "    radius %8.6f\n"
                    "    height %8.6f\n"
                    "   }\n"
                    "   appearance Appearance {\n"
                    "   material Material { diffuseColor %6.4f %6.4f %6.4f \n"
                    "                       specularColor 0.8 0.8 0.8 \n"
                    "                       shininess 0.8 }\n"
                    "   }\n"
                    "  }\n",
                    prim->r1, prim->l1,
                    (prim->c1[0] + prim->c2[0]) / 2,
                    (prim->c1[1] + prim->c2[1]) / 2, (prim->c1[2] + prim->c2[2]) / 2);
          }
          sprintf(buffer,
                  "Transform {\n"
                  " translation %8.6f %8.6f %8.6f\n"
                  " rotation %8.6f %8.6f %8.6f %8.6f\n"
                  " children [\n"
                  "%s"
                  " ]\n"
                  "}\n",
                  vert2[0] - mid[0],
                  vert2[1] - mid[1],
                  vert2[2] - mid[2], axis[0], axis[1], axis[2], angle, geometry);
          UtilConcatVLA(&vla, &cc, buffer);
        }
        break;
      case cPrimTriangle:
        /* output coords. connectivity and vertex colors handled above/below */
        sprintf(buffer,
                "%8.6f %8.6f %8.6f,\n"
                "%8.6f %8.6f %8.6f,\n"
                "%8.6f %8.6f %8.6f,\n",
                vert[0] - mid[0], vert[1] - mid[1], vert[2] - mid[2],
                vert[3] - mid[0], vert[4] - mid[1], vert[5] - mid[2],
                vert[6] - mid[0], vert[7] - mid[1], vert[8] - mid[2]);
        UtilConcatVLA(&vla, &cc, buffer);
        break;
      }
    }

    if(mesh_obj) {
      CBasis *base = I->Basis + 1;
      CPrimitive *cprim;
      int tri = 0;
      /* output connectivity */
      UtilConcatVLA(&vla, &cc, "   ]\n" "  }\n" "  coordIndex [\n");
      for(b = mesh_start; b < a; b++) {
        cprim = I->Primitive + b;
        if(TriangleReverse(cprim))
          sprintf(buffer, "%d %d %d -1,\n", tri, tri + 2, tri + 1);
        else
          sprintf(buffer, "%d %d %d -1,\n", tri, tri + 1, tri + 2);
        UtilConcatVLA(&vla, &cc, buffer);
        tri += 3;
      }

      /* output vertex colors */
      UtilConcatVLA(&vla, &cc,
                    "  ]\n" "  colorPerVertex TRUE\n" "  color Color {\n" "   color [\n");
      for(b = mesh_start; b < a; b++) {
        cprim = I->Primitive + b;
        sprintf(buffer,
                "%6.4f %6.4f %6.4f,\n"
                "%6.4f %6.4f %6.4f,\n"
                "%6.4f %6.4f %6.4f,\n",
                cprim->c1[0], cprim->c1[1], cprim->c1[2],
                cprim->c2[0], cprim->c2[1], cprim->c2[2],
                cprim->c3[0], cprim->c3[1], cprim->c3[2]);
        UtilConcatVLA(&vla, &cc, buffer);
      }

      /* output vertex normals */
      UtilConcatVLA(&vla, &cc,
                    "  ] } \n"
                    "  normalPerVertex TRUE\n" "  normal Normal {\n" "   vector [\n");
      for(b = mesh_start; b < a; b++) {
        cprim = I->Primitive + b;
        {
          float *norm = base->Normal + 3 * base->Vert2Normal[cprim->vert];
          sprintf(buffer, "%6.4f %6.4f %6.4f,\n" "%6.4f %6.4f %6.4f,\n" "%6.4f %6.4f %6.4f,\n", norm[3], norm[4], norm[5],      /* transformed cprim->n1 */
                  norm[6], norm[7], norm[8],    /* transformed cprim->n2 */
                  norm[9], norm[10], norm[11]); /* transformed cprim->n3 */
          UtilConcatVLA(&vla, &cc, buffer);
        }
      }
      UtilConcatVLA(&vla, &cc, "  ] }\n" "  normalIndex [ \n");
      tri = 0;
      for(b = mesh_start; b < a; b++) {
        cprim = I->Primitive + b;
        if(TriangleReverse(cprim))
          sprintf(buffer, "%d %d %d -1,\n", tri, tri + 2, tri + 1);
        else
          sprintf(buffer, "%d %d %d -1,\n", tri, tri + 1, tri + 2);
        UtilConcatVLA(&vla, &cc, buffer);
        tri += 3;
      }

      /* close mesh */
      UtilConcatVLA(&vla, &cc, " ] \n" " }\n" "}\n");
      mesh_obj = false;
    }
  }

  *vla_ptr = vla;
}