Recently I’ve talked about how to create moving shadows under elements of a face: Active self-moving shadows under elements

Today I’m proud to present to you my newest solution: 3d lighting on rotating hands.

In the spirit of explanation, I will first go through the steps I took in order to create my new scripts if you are interested in ready to use solutions scroll down.

`<TL;DR>`

What is a hand?

In the most simple matter, it is a line that rotates.

What is an active shadow on top of a hand?

It’s a lighter part on the side of a hand that is closer to the sun.

Now, since smartwatches don’t have the option of determining directions of external light sources, we need to make an assumption:

The light source is above us (when watching is flat on the ground the light source is exactly above it).

Now how do we check watch’s position relative to the ground (sky)?

We use `accelerometerRawX()`

and `accelerometerRawY()`

tags.

Now that we have a means to check watch’s position and we know the angle of a hand (just take its rotation tag) we need to check which side of a hand is higher at any given moment.

Remember me talking about the hand being just a line? It’s gone help us now.

Since accelerometer tags give us (pretty much) coordinates of the light source on the face (using more or less Cartesian coordinate system) we need to check mathematically on which side of a line is that point is located.

But not so fast! As I said accelerometers give back coordinates in Cartesian coordinate system, but Facer does not use the Cartesian coordinate system, so all tags giving back angle of hands won’t work as they are.

Typical Cartesian coordinate system has its angle starting

(being =0) and hour 3 and then goint positively counter clockwise (so 90 degs in Cartesian is 12 o’clock), while Facer has angle starting at 12 o’clock and going positively clockwise.

This helps create normal hands, but now we need to compensate it.

Compensation is quite easy: you take original (Facer) angle and subtract it from 90:

`(90-x)`

This, unfortunately, will give as a small trouble a little later in the process, but for now, let’s leave it at that.

We have an angle of a line and coordinates for a point, how does one check on which side of that line is that point situated?

First, let’s create that line’s equation:

y=ax+b

y and x are coordinates of each of line’s points, b shows how much is that line moved from the center (since we have clock hands this will be equal 0) and a shows how much is that line tilted.

As you probably know there is a connection between a and line’s angle:

`a=tan(rad(angle))`

The rad() changes angle from degrees into radians

Sweet, but we need to remember about Facer->Cartesian compensation:

`a=tan(rad(90-x))`

So our end equation for a line representing clock hand is:

`y=(tan(rad(90-x)))*x`

Now (again the same question) that we have that equation how do we check on which side of a line is the point located.

The simplest way is to input x coordinate of the point into that line question and compare point’s y and equations y with each other.

If point’s y is smaller than the point is on the right side of the line (hand should be illuminated on the right side) and then the exact opposite when the point’s y is bigger.

We have our solution!

Except we don’t…

Remember that last problem I mentioned when switching angle from Facer into Cartesian?

When we implement our solution right now it will be flipped when hand will be pointing to the left side of the screen (exactly from 6 o’clock, through 9, untile 12).

`</TL;DR>`

Summarizing:

We need 2 images (hand illuminated from the right and from left) and we need to double them (one set when the hand points to the right and one when it points to the left).

Here you have my solutions:

R 0-180

`$((accelerometerRawX())*(tan(rad(90-x))))>(accelerometerRawY())&&x<180?100:0$`

L 180-360

`$((accelerometerRawX())*(tan(rad(90-x))))>(accelerometerRawY())&&x>180?100:0$`

L 0-180

`$((accelerometerRawX())*(tan(rad(90-x))))<(accelerometerRawY())&&x<180?100:0$`

R 180-360

`$((accelerometerRawX())*(tan(rad(90-x))))<(accelerometerRawY())&&x>180?100:0$`

Use those codes as transparency codes and change x into your hand’s angle.

Here you have an example of it in action: Spekti faces and dynamic 3d lighting

Hope this will help.