2015-11-03 21 views
14

Ho un cerchio che orbita ogni 10 secondi. E sto provando a gettare un'ombra che è inclinata verso l'origine dell'orbita (la sorgente luminosa), tenendo anche conto anche dell'angolazione della telecamera.Spostare un'ombra attorno a un cerchio

L'ombra funziona per alcuni angoli, ma come la fotocamera passa più vantaggio sul o più dall'alto verso il basso, si comincia a guardare meno accurato e non ho idea di come correggere per esso - sembra come un complicato problema di matematica che io sono lottando per capire come risolvere.

Questa è l'animazione: http://jsfiddle.net/8y2bm88w/

E il mio codice sorteggio per l'ombra:

ctx.beginPath(); 

//rotate shadow with the planet 
ctx.translate(originX + obj[i].x, originY + obj[i].y); 
ctx.rotate(obj[i].angle); //rotate around origin 
ctx.translate(-(originX + obj[i].x), -(originY + obj[i].y)); 


var offsetX = -(10 * Math.sin(obj[0].angle)); //i feel this is the issue 
var offsetY = 0; //this too 

ctx.rect(originX + obj[i].x + offsetX, originY + obj[i].y + offsetY - 10, 20, 20); 
ctx.fillStyle = 'rgba(213,0,0,0.9)'; //red shadow - easier to see 
ctx.fill(); 

Il codice ha più senso attraverso il JSFiddle come si mette il codice in più contesto.

Quindi penso che questo abbia a che fare con le matematiche per le variabili offsetX e offsetY, poiché l'utente modifica l'angolo della telecamera rispetto alla necessità dell'offset di adattarsi e modificare il modo in cui l'ombra si sposta. Ma questo è davvero fonte di confusione su come risolvere.

+0

Quindi, se ho capito bene, si desidera che l'emisfero del cerchio rivolto verso l'origine da illuminare, e il resto per essere scuro. Questo è vero indipendentemente dall'angolo della telecamera. Corretta? –

+0

@AsadSaeeduddin dovrebbe prendere in considerazione l'angolo che si sta osservando il pianeta. Quindi credo che tu abbia capito bene. – Sir

+0

@AsadSaeedudddin punto buono, in pratica ha solo bisogno di sembrare corretto dagli occhi dello spettatore. Se guardi il bordo su 'camera angle = 0' dovrebbe gettare un'ombra completa e nessuna ombra ecc., Dall'alto in basso' camera angle = 1', getterebbe mezza ombra tutto il tempo. – Sir

risposta

7

si sta colpendo questo perché il vostro obj[i].angle si basa sulle coordinate ellisse e non i coordinate XY della vista dall'alto verso il basso (che è in realtà quello che si sta generando tutto il resto da così noi no bisogno di fare calcoli per questo).

Avrete bisogno di entrambi gli angoli, quindi ho aggiunto una seconda proprietà per l'altro angolo. L'angolo dell'ellisse è necessario per la rotazione del contesto in modo da poter essere perpendicolare al vettore dall'origine come visualizzato. Il nuovo angolo è per i calcoli. Puoi considerarlo come una versione non mappata in 2D.

obj[i].trueAngle = angle; 

Ora abbiamo il valore di lavorare con, suggerisco disegnando un semicerchio per il "lato oscuro" e poi aggiungendo o tagliando fuori da questa regione, come richiesto usando una curva di vostra scelta per completare la ombra, ad es

// centre on planet 
ctx.translate(originX + obj[i].x, originY + obj[i].y); 
ctx.rotate(obj[i].angle - Math.PI/2); 
// semicircle dark side 
ctx.arc(0, 0, 12, 0, Math.PI, false); 
// path along terminator 
var offset_terminator = -20 * Math.sin(obj[0].trueAngle) * (1 - camera.angle); 
ctx.bezierCurveTo(-7, offset_terminator, 7, offset_terminator, 12, 0); 
//fill 
ctx.fillStyle = 'rgba(213,0,0,0.9)'; //red shadow - easier to see 
ctx.fill(); 

Qui ho fatto anche l'ombra di un paio di px più grande del pianeta, ho solo giocato con i numeri fino a quando ho trovato alcuni che sembrava buono.

Si prega di notare ho creato rotazione in modo 0, 0 è al centro del pianeta e il asse x si muove lungo il terminatore

DEMO

+0

Se vuoi più mezzelune sottili, prova a ridurre lo scalare di 'offset_terminator' da' -20' a qualcosa come '-14', in effetti lo fa sembrare abbastanza bello –

+0

Perché i numeri magici 12 e 7? Non dovrebbero essere rispettivamente 10 e 5? Capisco che sia per spiegare il colpo, ma non avrebbe più senso semplicemente sbarazzarsi del tratto e espandere il raggio del cerchio, invece? –

+1

@FuzzyLogic Ho scelto '12' per assicurarmi che il colore dell'ombra sia su tutti i pixel anche quando i bordi sono sfumati in quanto potrebbero non andare perfettamente a pixel di' 10'. OP ha una struttura che potrebbe nascondere questo però. '11' non funzionerebbe su entrambi i lati. Per quanto riguarda '7', perché ha dato una bella curva più bella. –