Creazione di files .INC
This Page Have been collected |
|
hit |
Innanzitutto è necessario specificare, a favore dei neofiti, cosa
si intende per file .INC (o file include) in POV:
Un file di questo tipo contiene delle direttive POV di qualsiasi genere
che, in fase di rendering, vengono aggiunte al file in rendering come se
fossero state copiate nel punto dove è inserito il file include.
Per rendere il tutto più comprensibile vediamo un piccolo esempio
:
supponiamo di avere un file, mysphere.inc, che contiene il seguente
codice :
// create a sphere shape
sphere
{
<0, 1, 0> // center of sphere
<X Y Z>
0.5
// radius of sphere
}
Ed un secondo file in cui, ad un certo punto, viene incluso il file precedente
:
....
look_at <0.0 , 0.0 , 0.0>
}
#include "mysphere.inc"
// create a regular point light source
light_source
{
<-10, 0, -20> // light's position
.....
In fase di rendering POV interpreterà il codice precedente come
se fosse il seguente :
....
look_at <0.0 , 0.0 , 0.0>
}
// create a sphere shape
sphere
{
<0, 1, 0>
// center of sphere <X Y Z>
0.5
// radius of sphere
}
// create a regular point light source
light_source
{
<-10, 0, -20> // light's position
.....
Questa funzionalità di POV ci permette di creare facilmente Librerie
di oggetti o di texture da riutilizzare poi nei nostri futuri rendering
senza dover andare a cercare parti di codice su vecchi progetti.
E' importante notare che, come sicuramente saprete già, tutto
il testo che si trova dopo un doppio slash ( // ) viene considerato da
POV come un commento e quindi ignorato.
Utilizzando i files include insieme alle direttive ed alle funzioni
che POV ci mette a disposizione è possibile realizzare anche delle
specie di "Plug-in", cioè dei file che, specificando il valore di
qualche variabile, ci permettono di ottenere oggetti anche complessi.
Per esemplificare bene quella che è la possibilità offerta
vedremo, di seguito, come realizzare un semplice file include che genera
dei poligoni regolari ad n lati con un foro centrale di m
lati.
Cercherò di essere quanto più chiaro possibile nella
spiegazione per rendere il tutto comprensibile anche a chi non conosce
la programmazione e non ha infarinature di matematica, certo che una conoscenza,
almeno di base, di entrambe le cose aiuta molto.
Per
prima cosa decidiamo di lasciare disponibile all'utilizzatore dell'include
la possibilità di decidere quanti lati avrà il poligono,
quanti lati avrà il foro, quale sarà il raggio del cerchio
entro il quale sarà inscritto il poligono e quale sarà il
raggio del cerchio entro il quale sarà inscritto il foro. (vedere
Image 1).
Per fare questo è necessario definire 4 variabili.
Una variabile in POV viene definita con la seguente sintassi :
#declare VARIABLENAME = VARIABLEVALUE
Dove VARIABLENAME è il nome della variabile e VARIABLEVALUE è
il valore assegnato alla variabile (che può essere di diversi tipi,
intero, floating point, stringa, vettore, ecc.).
Nel nostro caso definiremo che le seguenti variabili :
// Parameters for this include
// Parameter
Type
Default Means
// POLY_RADIUS1
float > 0 1
Radius of first poly
// POLY_RADIUS2
float > 0 2
Radius of 2nd poly
// POLY_VERTEX1 integer
> 2 4
Number of vertex of first poly
// POLY_VERTEX2 integer
> 2 4
Number of vertex of 2nd poly
Naturalmente queste variabili dovranno essere dichiarate prima di includere
il nostro file, ma è buona norma verificare, all'inizio del file
che le variabili siano state tutte correttamente dichiarate.
Per eseguire questo controllo ci serviremo della direttiva #ifndef.
La sintassi è la seguente :
#ifndef (VARIABLENAME)
<CODE>
#end
Le righe di codice precedenti significano che, se non è definita
la variabile VARIABLENAME viene "eseguito" il codice <CODE>, che può
essere una qualsiasi serie di direttive POV.
Noi utilizzeremo questa funzione per verificare che, l'utilizzatore
del nostro .inc abbia dichiarato le variabili necessarie, in caso contrario
dichiariamo noi le variabili e assegnamo loro il vaolre di default che
abbiamo specificato :
// Checking Parameters, using #ifndef statement to see if parameter
exist
// if not exist using #declare to instantiate it to default value
#ifndef (POLY_RADIUS1)
#declare POLY_RADIUS1 = 1
#end
#ifndef (POLY_RADIUS2)
#declare POLY_RADIUS2 = 2
#end
#ifndef (POLY_VERTEX1)
#declare POLY_VERTEX1 = 4
#end
#ifndef (POLY_VERTEX2)
#declare POLY_VERTEX2 = 4
#end
A queso punto siamo sicuri di avere tutti i dati che ci servono, quindi
cominciamo a creare il poligono.
Per evitare di dover includere n volte il nosto file in caso servano
molti poligoni uguali invece di "creare" un oggetto poligono nella nostra
scena "dichiareremo" un oggetto poligono nel seguente modo :
#declare POLY =
polygon
{
In questo modo noi andiamo a dichiarare, all'interno del nostro file, una
variabile che conterrà l'intera descrizione del poligono generato.
L'oggetto sarà poi utilizzabile all'interno del file .POV con il
seguente codice :
Utilizzeremo questo perchè ci permette di poter manipolare l'oggetto
come desideriamo cioè, ad esempio, translarlo, ruotarlo, assegnargli
una texture, ecc.
Diamo ora uno sguardo a quella che è la sintassi dell'oggetto
polygon all'interno di POV.
L'help in linea di POV-Ray for windows, alla voce polygon, ci presenta
la seguente sintassi :
polygon {
TOTAL_NUMBER_OF_POINTS,
<A_1>, <A_2>, ..., <A_na>, <A_1>,
<B_1>, <B_2>, ..., <B_nb>, <B_1>,
<C_1>, <C_2>, ..., <C_nc>, <C_1>,
...
}
Come primo dato quindi dovremo dire di quanti vertici è composto
il nostro poligono.
Il
numero di vertici che compongono il poligono, come specificato nell' esempio
dell' Image 2 è dato dal numero di lati del poligono, più
il numero di lati del foro, più 3.
La spiegazione del più tre è semplice, in quanto per
ottenere i due poligoni completamente dobbiamo ripercorrere due volte il
vertice di partenza di ogni poligono (quello esterno e quello interno,
o foro). e questo ci comporta due punti in più. Il terzo punto viene
aggiunto in quanto POV prevede che, in un oggetto polygon, il primo punto
e l'ultimo coincidano.
Per cui, aggiungeremo al nostro file il seguente codice :
// Total Number of vertex
POLY_VERTEX1 + POLY_VERTEX2 + 3,
// +3, because the first and the last vertex
are the same for first radius poly,
// 2nd radius poly and for all the poly
A questo punto dobbiamo solamente cominciare a calcolare le coordinate
dell'oggetto.
Per comodità di riutilizzo Descriveremo l'oggetto appogiato
sul piano XZ, mantenendo le coordinate Y empre uguali a 0. Inoltre il centro
del nostro poligono sarà a coordinate 0,0,0 per cui sapremo sempre
la sua posizione per translarlo e ruotarlo in seguito.
Per eseguire tutti i calcoli necessari avremo bisogno di un valore
costante (che memorizzeremo in una variabile) e di un contatore (cioè
una variabile che conterà il numero dei vertici man mano che andremo
a calcolarli).
Il valore costante che ci sarà necessarrio sarà lo step
in cui dovremo suddividere il cerchio a seconda del numero di lati del
poligono che stiamo costruendo. Per calcolare questo valore utilizzeremo
una costante che ci viene fornita da POV cioè la costante pi
che rappresenta il valore di pigreco (cioè 180° espressi in
radianti).
Questo ci sarà necessario in quanto le funzioni di seno e coseno
che andremo ad utilizzare utilizzano angoli espressi in radianti.
Aggiungiamo quindi le seguenti righe di codice :
// The subdivision of the circle (in radiant)
(using built in const pi (pigreco))
#declare POLY_CIRCLE_STEP = (pi * 2) / POLY_VERTEX1
// Dummy var, use as counter
#declare POLY_DUMMY = 1
Ora dovremo calcolare i valori dei singoli vertici, il valore delle Y sarà
sempre 0, quello delle X sarà derivato dal seno (moltiplicato per
il raggio del cerchio specificato all'inizio) e quello delle Z sarà
derivato dal coseno (anch'esso moltiplicato per il raggio del cerchio specificato
all'inizio).
Siccome partiamo da un angolo di 0° il cui seno è 0 ed il
cui coseno è 1, e siccome dovremo ripetere il primo vertice come
ultimo (come spiegato precedentemente) ci salveremo per comodità
il valore del primo punto in una variabile :
// Saving first point (for use as end point)
#declare POLY_FIRSTP = <0,0,POLY_RADIUS1>
// Adding First point to poly
<POLY_FIRSTP.x,POLY_FIRSTP.y,POLY_FIRSTP.z>
Ho utilizzato direttamente i valori 0,0,POLY_RADIUS1 per evitare inutili
calcoli. Correttamente la dichiarazione del primo punto sarebbe stata :
#declare POLY_FIRSTP = <sin(0)
* POLY_RADIUS1, 0, cos(0) * POLY_RADIUS1>
Siccome abbiamo già detto che il seno di 0 è 0 ed il coseno
di 1 è 0 queste espressioni sarebbero state valutate come :
#declare POLY_FIRSTP = <0
* POLY_RADIUS1, 0, 0 * POLY_RADIUS1>
cioè :
#declare POLY_FIRSTP = <0,0,POLY_RADIUS1>
questo per qualunque numero di lati e per qualunque valore di POLY_RADIUS1.
Per calcolare tutti i vertici del poligono esterno ci serviremo di
un "loop" cioè di una direttiva che permette di eseguire una parte
di codice un certo numero di volte.
POV per fare questo ci mette a disposizione la direttiva #while la
cui sintassi è la seguente :
#while (COND)
<CODE>
#end
Questo, spiegato brevemente, significa esegui il codice <CODE> finchè
la condizione COND è vera.
Ovviamente, all'interno del codice <CODE> ci deve essere qualcosa
che permette di modificare la condizione COND affinchè questa prima
o poi diventi falsa, pena un loop infinito (cosa che, anche se non la ho
mai sperimentata, suppongo che blocchi POV finchè non andrà
esaurita tutta la memoria o lo stack).
Nel nostro caso la condizione di uscita sarà che il contatore
di cui abbiamo accennato prima abbia un valore inferiore o uguale al numero
di vertici che dobbiamo generare.
All'interno del loop che andremo ad aggiungere calcoleremo la posizione
di tutti i nuovi vertici utilizzando le funzioni di seno e coseno come
descritto prima. Aggiungiamo quindi il seguente codice :
#while (POLY_DUMMY <= POLY_VERTEX1)
// Computing current
angle
#declare POLY_CURR_ANGLE
= POLY_CIRCLE_STEP * POLY_DUMMY
// Declaring point (compute
x and z position using sin and cos functions)
<sin(POLY_CURR_ANGLE)
* POLY_RADIUS1,0,cos(POLY_CURR_ANGLE) * POLY_RADIUS1>
// Increase counter
#declare POLY_DUMMY =
POLY_DUMMY + 1
#end
Come detto, qui calcoliamo l'angolo a cui deve trovarsi il prossimo vertice
da aggiungere e, tramite le funzioni di seno e coseno andiamo a calcolarne
l'esatta posizione X e Z. Y rimane sempre a 0.
L'ultima istruzione prima dell' end è l'incremento della variabile
contatore che ci permetterà di uscire dopo aver creato tutti i vertici
che ci sono necessari.
A questo punto dobbiamo fare la stessa cosa per i vertici interni (quelli
del foro), e questo lo faremo con il seguente codice :
// Loop to declare the 2nd radius vertex
// The subdivision of the circle (in radiant)
(using built in const pi (pigreco))
#declare POLY_CIRCLE_STEP = (pi * 2) / POLY_VERTEX2
// Dummy var, use as counter
#declare POLY_DUMMY = 0
#while (POLY_DUMMY <= POLY_VERTEX2)
// Computing current
angle
#declare POLY_CURR_ANGLE
= POLY_CIRCLE_STEP * POLY_DUMMY
// Declaring point (compute
x and z position using sin and cos functions)
<sin(POLY_CURR_ANGLE)
* POLY_RADIUS2,0,cos(POLY_CURR_ANGLE) * POLY_RADIUS2>
// Increase counter
#declare POLY_DUMMY =
POLY_DUMMY + 1
#end
A questo punto dobbiamo aggiungere nuovamente il primo punto calcolato
per "chiudere" il poligono :
// Adding end point (equal to firstpoint)
<POLY_FIRSTP.x,POLY_FIRSTP.y,POLY_FIRSTP.z>
// End of polygon
}
Ed a questo punto, la nostra procedura di creazione di poligoni forati
è terminata.
Utilizzando un semplice file POV possiamo provare il tutto e questo
è un esempio di ciò che potremo ottenere :
Questo lo si ottiene grazie al seguente sorgente POV :
// ==== Standard POV-Ray Includes ====
#include "colors.inc" // Standard Color definitions
#include "textures.inc" // Standard Texture definitions
camera
{
location <0.0 , 0.0 ,-8.0>
look_at <0.0 , 0.0 , 0.0>
}
light_source
{
0*x // light's position (translated below)
color red 1.0 green 1.0 blue 1.0 // light's
color
translate <-10, 0, -20>
}
light_source
{
0*x // light's position (translated below)
color red 1.0 green 1.0 blue 1.0 // light's
color
translate <10, 0, -20>
}
// BackDrop Plane
plane
{
z, // <X Y Z> unit surface normal, vector points "away
from surface"
2.0 // distance from the origin in the direction of the surface
normal
pigment
{
checker White, Black
}
}
// Create first poly (default)
#include "ProgTut1.inc"
object { POLY rotate <-45,0,0> translate <2,2,0> pigment {
color Yellow } }
// Create 2nd poly (poly vertex = 5, Hole vertex = 7)
#declare POLY_VERTEX1 = 7
#declare POLY_VERTEX2 = 5
#include "ProgTut1.inc"
object { POLY rotate <-45,0,0> translate <-2,-2,0> pigment
{ color Yellow } }
E questo è tutto, per ora.
Per comodità potete scaricare uno zip che contiene il file ProgTut1.inc
(include del tutorial) ed il file TutSamp1.pov (per generare l'immagine
Image 3) qui : POVTut1.zip
Per qualsiasi problema relativamente a questo tutorial Inviate una Mail
a Terenziani Gianluca
Se siete interessati a qualche argomento relativo a POV fatecelo sapere
inviando una mail a Terenziani
Gianluca
Back To Index