#!/bin/perl # Computes the vertices & normals of a rectangular patch of a torus # surface, and outputs the body of a POV-Ray mesh object. The torus # which we're taking a patch of is centered at the origin and lies # in the x-z plane, just like a POV-Ray torus object. # # To use with POV-Ray: # # 1. Define a mesh object in your POV-Ray scene like so: # # #declare patch = mesh { # #include "mesh.data" # pigment { color Red } # } # # 2. Modify variables in "stuff to set" section below. # 3. Run script, directing output to mesh.data # 4. Render your POV-Ray scene. # # There's plenty of stuff in this to optimize, but it runs quickly enough. use Math::Trig; # ------------------------------------------------------------------- # stuff to set # major and minor radius of torus \$majorRadius = 9; \$minorRadius = 3; # boundaries of patch in terms of u and v coordinates (in degrees) \$startU = 10; \$endU = 350; \$startV = -230; \$endV = 80; # end stuff to set # ------------------------------------------------------------------- # The next two variables determine mesh density in each direction. # You could set these manually, but the formula seems to yield a # smooth patch independent of its size. \$divU = int(abs(\$endU-\$startU)/3); \$divV = int(abs(\$endV-\$startV)/3); # distance between vertices in each direction \$du = (\$endU-\$startU)/\$divU; \$dv = (\$endV-\$startV)/\$divV; # do it! calculateVerticesAndNormals(); printMeshBody(); sub calculateVerticesAndNormals { my \$u = \$startU; for (my \$i = 0; \$i <= \$divU; \$i++) { my \$v = \$startV; my \$radiansU = deg2rad(\$u); for (my \$j = 0; \$j <= \$divV; \$j++) { my \$radiansV = deg2rad(\$v); \$vertex[\$i][\$j] = vertex(\$radiansU,\$radiansV); \$normal[\$i][\$j] = normal(\$radiansU,\$radiansV); \$v += \$dv; } \$u += \$du; } } sub printMeshBody { for (my \$i = 0; \$i < \$divU; \$i++) { for (my \$j = 0; \$j < \$divV; \$j++) { my \$line = <",\$x,\$y,\$z); } sub normal { my (\$u,\$v) = @_; my \$nx = cos(\$u)*cos(\$v); my \$ny = sin(\$v); my \$nz = sin(\$u)*cos(\$v); return sprintf("<%.4f,%.4f,%.4f>",\$nx,\$ny,\$nz); }