Progetto Di Grafica

Galleria Borromini di Palazzo Spada a Roma

Riproduzione del modello ottico in grafica 3D

Realizzato da: Roberto Valenti

 

Indice

  1. Introduzione
  2. Il colonnato
  3. L'arco
  4. Altri Oggetti
  5. La scena
  6. Appendice A (codice sorgente della scena)

Introduzione

La galleria Borromini (anche conosciuta come galleria prospettica) è il frutto di studi matematici ed architettonici del Borromini in collaborazione con il padre. A rendere questa galleria famosa è l'effetto ottico che essa produce: la sua lunghezza sembra essere superiore ai 30 metri, mentre non ne supera i 9. Questo progetto prende in considerazione la galleria come potrebbe apparire all'occhio e non il modello reale che lo produce. Della galleria verrà dunque solo ripreso lo stile architettonico cercando di interpretare al meglio il modello virtuale partendo da una sua foto.

I pacchetti software utilizzati per questo scopo sono, come da specifiche di progetto, xcmodel, xcsurf e xcrayt, quindi sono state utilizzate alcune soluzioni non ottimali per realizzare alcuni effetti (come ad esempio superfici booleane).

Il Colonnato

Per la realizzazione del colonnato si è partiti dalla creazione del cilindro che diventerà l'elemento principale della colonna. Il cilindro è una superficie di rotazione generata dalla rotazione di un apposita curva di grado 1 (rettangolare aperta) attorno all'asse z (vedi colonna#.db).

Anche i capitelli sono generati con il medesimo metodo, ma utilizzando una curva di grado superiore che potesse creare l'effetto di rotondità richiesto (Fig 1).

Fig 1

Dopo aver creato opportune copie delle colonne e dei capitelli, si è proceduto con il posizionamento delle suddette nello spazio (attraverso "Numeric Modify" del pacchetto xcsurf) ruotando di 180° le mesh dei capitelli della base (capitellodown#.db) per trasformarli nei capitelli che andranno a posizionarsi sulla parte alta della colonna (capitelloup#.db). Si è creata la base del colonnato (bottom.db) attraverso lo "scale" di un cubo (una superficie di rotazione generata da una curva "rettangolare aperta" avente altezza coincidente al doppio della larghezza, con grado 1 nella direzione di rotazione).

Traslando tutti gli elementi nella loro opportuna posizione il colonnato inizia a prendere la sua forma (Fig 2).

Fig 2

Le "barrette" che compaiono al di sopra e al di sotto dei capitelli (barra#up.db e barra#down.db) non sono altro che la prosecuzione dei capitelli stessi e sono state create con lo stesso metodo usato per la creazione della base, in quanto non era possibile creare una superficie spigolosa e rotonda nella direzione di rotazione senza andare a toccare i CP (Control Point). Dopo averle posizionate (Fig. 3) è stata generata la parte alta del colonnato utilizzando sempre la stessa tecnica (top.db). La curva è stata creata con il pacchetto xccurv per poter riuscire ad avere una maggior flessibilità nel cercare di rendere questa superficie il più possibile simile a quella originale. Dopo aver posizionato anche quest'ultima superficie il colonnato è completo (Fig. 4).

Fig. 3
Fig. 4

L'arco

L'arco è un classico esempio di superficie booleana, ottenuta attraverso una differenza tra un cubo ed un cilindro.

Non potendo utilizzare superfici booleane si è cercato di ricreare l' effetto facendo extrude/skinning di curve semplici. E' il caso della parte frontale e anteriore del profilo dell'arco (front.db, back.db).

Fig. 5

Per poter realizzare l'arco caratteristico dell'arcata si è utilizzata una superficie tubolare creata replicando una linea (curva piana) nella traiettoria di un semicerchio. Naturalmente il semicerchio di traiettoria e quello utilizzato per lo skinning coincidono, in modo da poter mantenere un match perfetto tra le due superfici. Nella Fig. 6 si può vedere il risultato della combinazione di queste 3 superfici appena create.

Fig. 6 Fig. 7

La superficie nella figura 6 è stata creata interattivamente con xcsurf, creando una base di CP rettangolare sull'asse xy, e modificando successivamente le altezze di ogni CP sull'asse delle z. La superficie, propriamente copiata, traslata e scalata, costuitirà i rilievi primari dell'arco (abbellimento.db, abbellimento2.db, portante.db) visibili in Fig. 7 . Utilizzando lo stesso procedimento utilizzato per top.db (la parte alta del colonnato) si è realizzata la parte alta dell'arco (tettoarco.db). Si è scelto di non comlpletare l'arco in tutti i suoi lati in quanto non utile e non visualizzabile ai fini alla resa.

Fig. 8 Fig. 9

Per realizzare il contorno dell'arco (archiabb.db, Fig 11) è stato utlizzato lo stesso semicerchio impegnato nella costruzione dell'arco, ripetuto sulla traiettoria di una curva ondulata.

Per la stella (stellaleft.db, stellaright.db) è stata disegnata una curva rappresentante la sua proiezione, poi è stata copiata, scalata al massimo e spostata leggermente in avanti. Un successivo skinning delle due shape ottenute dà luogo alla mesh in Fig.10, da replicare e posizionare sull'arco.

Fig. 10 Fig. 11

Il risultato finale, in wireframe ed in shading , è mostrato nelle figure 12 e 13.

Fig. 12 Fig. 13

Altri Oggetti

Gli altri oggetti impiegati sono per lo più muri (muroleft.db, muroright.db, muroup.db, muroback.db) e pavimenti (pavement.db, floor.db), che sono stati realizzati traslando e scalando cubi nella giusta posizione. Inoltre ci sono altri due oggetti, la cornice del quadro (cornice.db) e lo scalino (scalino1.db, scalino2.db) che appare davanti ai primi due colonnati. La cornice è stata ottenuta tramite una curva rettangolare chiusa rappresentante il bordo interno, copiata e scalata per ottenere il bordo esterno. Utilizzando lo strumento "InBetween" sono state create altre 3 copie posizionate all'interno delle 2 shape che sono state spostate avanti ed indietro per creare la forma della cornice. Lo scalino non è altro che una solita superficie di rotazione generata da una curva, ma i CP di un lato sono stati scalati fino a raggiungere la forma di una linea, per poi essere spostati al centro dell'asse di rotazione. Naturalmente la parametrizzazione di questo oggetto non è ottimale, ma non avendo a disposizione altri strumenti questa soluzione è stata considerata accettabile.

Le figure 14 e 15 mostrano i wireframe degli oggetti descritti.

Fig. 14
Fig.15

La scena

Una volta creati tutti gli oggetti si è passati alla composizione della scena utilizzando la libreria "descriptor". Il listato di questo passo è disponibile nell'Appendice A. La figura 16 mostra la scena in fase di realizzazione.

Fig. 16

Le prossime immagini mostrano la scena finita e guardata da diverse inquadrature, renderizzata con raytrace a 2 livelli.

Fig. 17
Fig. 18

 

Fig. 19
Fig. 20

 

Fig. 21

 

Appendice A (listato del codice c per la creazione della scena)

#include "descriptor/descriptor.h"
int main(void) {
         ITEM commonattribute,white;
         ITEM colonnato1,colonnato2,colonnato3,colonnato4,colonnato5,colonnato6,
              colonnato7,colonnato8,arco1,arco2,arco3,arco4,floor,pavement,
              muroleft,muroup,muroright,muroback,scalino1,scalino2,quadro,cornice;
         ITEM scene;
// SETTAGGIO LUCI E AMBIENTE
         set_background(0.1,0.1,0.1,TRUE);
         set_ambient_light(0.9,0.9,0.9,0.7);
         create_distant_light(-0.5,-0.5,-0.3,1,1,0.9,1,"Distant");
         create_point_light(2,3,6,1,1,0.9,1,3, "light1");
         create_point_light(2,0,1,1,1,0.9,1.5,10, "light2");
         create_point_light(2,-6,1,1,1,0.9,1.5,5, "light3");
         create_point_light(2,-12,1,1,1,0.9,1.5,5, "light4");
         create_point_light(2,-18,1,1,1,0.9,1.5,5, "light5");
         create_point_light(0,-20,2,1,1,0.9,1.5,20, "light6");
 // ATTRIBUTI
         commonattribute = create_attribute("commonattribute");
         set_color(commonattribute,0.89,0.76,0.65,0.1,0.8);
         set_reflectivity(commonattribute,0.1,10);
         white = create_attribute("white");
         set_color(white,0.95,0.95,0.95,0.2,0.8);
         set_reflectivity(white,0,0);
 // LETTURA OGGETTI DELLA SCENA
         muroleft = read_nurbs("muroleft.db");
         muroup = read_nurbs("muroup.db");
         muroright = read_nurbs("muroright.db");
         muroback=read_nurbs("muroback.db");
         floor = read_nurbs("floor.db");
         pavement= read_nurbs("pavement.db");
         scalino1=read_nurbs("scalino.db");
         scalino2=read_nurbs("scalino.db");
         quadro=read_nurbs("quadro.db");
         cornice=read_nurbs("cornice.db");
         colonnato1 = read_obj("colonnato.obj", "colonnato_1");
         colonnato2 = create_copy(colonnato1, "colonnato_2");
         colonnato3 = create_copy(colonnato1, "colonnato_3");
         colonnato4 = create_copy(colonnato1, "colonnato_4");
         colonnato5 = create_copy(colonnato1, "colonnato_5");
         colonnato6 = create_copy(colonnato1, "colonnato_6");
         colonnato7 = create_copy(colonnato1, "colonnato_7");
         colonnato8 = create_copy(colonnato1, "colonnato_8");
         arco1 = read_obj("arco.obj", "arco_1");
         arco2 = create_copy(arco1, "arco_2");
         arco3 = create_copy(arco1, "arco_3");
         arco4 = create_copy(arco1, "arco_4");
 // TEXTURE MAPPING/SET ATTRIBUTE
         set_attribute(colonnato1,white);
         set_attribute(colonnato2,white);
         set_attribute(colonnato3,white);
         set_attribute(colonnato4,white);
         set_attribute(colonnato5,white);
         set_attribute(colonnato6,white);
         set_attribute(colonnato7,white);
         set_attribute(colonnato8,white);
         set_attribute(arco1,white);
         set_attribute(arco2,white);
         set_attribute(arco3,white);
         set_attribute(arco4,white);
         set_attribute(cornice,commonattribute);
         set_projection_texture(muroright,commonattribute,"wall.hr",1,1,0.5,0.5);
         set_projection_texture(muroup,commonattribute,"wall.hr",1,1,0.5,0.5);
         set_projection_texture(muroleft,commonattribute,"wall.hr",1,1,0.5,0.5);
         set_projection_texture(pavement,white,"pavement.hr",2,0,0.5,1);
         set_projection_texture(floor,commonattribute,"wall.hr",2,1,0.5,0.5);
         set_projection_texture(muroback,commonattribute,"wall.hr",2,1,0.5,0.5);
// POSIZIONAMENTO OGGETI NELLA SCENA
         set_scale(muroright,1,10,1);
         set_scale(muroup,0.55,10,0.66);
         set_scale(muroleft,1,10,1);
         set_scale(muroback,1.3,1,2);
         set_translate(muroright,0,-12,0);
         set_translate(muroup,3.5,-12,4);
         set_translate(muroleft,4,-12,0);
         set_translate(muroback,5.5,-25,-2.5);
         set_translate(quadro,4.5,-24,-0.5);
         set_translate(cornice,4.5,-24,-0.5);
         set_projection_texture(quadro,white,"galleria.hr",1,2,0.5,0.5);
         set_scale(pavement,1,10,1);
         set_translate(pavement,2,-8,0);
         set_scale(floor,6.5,20,1);
         set_translate(floor,2,-8,-2.1);
         set_translate(scalino2,4,0,0);
         set_translate(colonnato2,4,0,0);
         set_translate(colonnato3,0,-6,0);
         set_translate(colonnato4,4,-6,0);
         set_translate(colonnato5,0,-12,0);
         set_translate(colonnato6,4,-12,0);
         set_translate(colonnato7,0,-18,0);
         set_translate(colonnato8,4,-18,0);
         set_scale(arco1,0.9,0.9,0.9);
         set_translate(arco1,2,-0.2,2.5);
         set_scale(arco2,0.9,0.9,0.9);
         set_translate(arco2,2,-6,2.5);
         set_scale(arco3,0.9,0.9,0.9);
         set_translate(arco3,2,-12,2.5);
         set_scale(arco4,0.9,0.9,0.9);
         set_translate(arco4,2,-18,2.5);
// CREAZIONE SCENA
         scene = create_list(colonnato1, "scene");
         scene = insert_in_list(scene,colonnato2);
         scene = insert_in_list(scene,colonnato3);
         scene = insert_in_list(scene,colonnato4);
         scene = insert_in_list(scene,colonnato5);
         scene = insert_in_list(scene,colonnato6);
         scene = insert_in_list(scene,colonnato7);
         scene = insert_in_list(scene,colonnato8);
         scene = insert_in_list(scene,arco1);
         scene = insert_in_list(scene,arco2);
         scene = insert_in_list(scene,arco3);
         scene = insert_in_list(scene,arco4);
         scene = insert_in_list(scene,floor);
         scene = insert_in_list(scene,pavement);
         scene = insert_in_list(scene,muroleft);
         scene = insert_in_list(scene,muroup);
         scene = insert_in_list(scene,muroright);
         scene = insert_in_list(scene,muroback);
         scene = insert_in_list(scene,quadro);
         scene = insert_in_list(scene,cornice);
         scene = insert_in_list(scene,scalino1);
         scene = insert_in_list(scene,scalino2);
         save_scene("progetto.md","scene_progetto",scene);
           return(0);
         }