#!/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); }