Need maths help - rotating a scaling XYZ for shadows

Blitz3D Forums/Blitz3D Programming/Need maths help - rotating a scaling XYZ for shadows

Rottbott(Posted 2003) [#1]
I'm sure this is a very simple problem but I'm totally stumped!

I'm doing shadows by flattening a black-coloured copy of my player's mesh onto the ground. I use a LinePick to get the position and normal of the ground point where my player is standing, then I use PositionEntity and AlignToVector to position and rotate my shadow on the ground.

Next I set the Roll angle of the shadow to the Yaw value of the player. This makes the shadow sideways on to the ground when the player is sideways on to the light source that is casting the shadow.

However I then have to scale the shadow to be flat on the ground and that has me stumped. I use a scale of 1.2, 1.2, 0.05, but when I rotate my shadow with the player's Yaw, this must obviously be adjusted so the shadow is scaled to 0.05 in the direction of the Global Y-axis and 1.2 on the X and Z axes.

I've tried just about every combination of TFormVector I can think of and none work. The closest I have got to a solution is some simple trigonometry, but it only works at -180, -90, 0, 90, and 180 degree rotations - angles in between cause problems.

Here's the code (with my trig scaling solution):

        Result = LinePick(EntityX#(pThis\EN), EntityY#(pThis\EN), EntityZ#(pThis\EN), 0, -1000.0, 0)
        If Result
          PositionEntity pThis\ShadowEN, PickedX#(), PickedY#() + 3.0, PickedZ#()
          AlignToVector pThis\ShadowEN, PickedNX#(), PickedNY#(), PickedNZ#(), 2
          Yaw# = EntityYaw#(pThis\EN)
          RotateEntity pThis\ShadowEN, EntityPitch#(pThis\ShadowEN), 0.0, Yaw#
          TurnEntity pThis\ShadowEN, -90.0, 0.0, 0.0
          MoveEntity pThis\ShadowEN, 0.0, MeshHeight#(pThis\EN) / 2.0, 0.0
; FIXME
          XScale# = Abs(Sin#(Yaw#)) * 0.05 : XScale# = XScale# + (1.2 * ((0.05 - XScale#) * 20.0))
          ZScale# = Abs(Cos#(Yaw#)) * 0.05 : ZScale# = ZScale# + (1.2 * ((0.05 - ZScale#) * 20.0))
          ScaleEntity pThis\ShadowEN, XScale#, 1.2, ZScale#
        EndIf


pThis = Player type instance
pThis\EN = Player mesh
pThis\ShadowEN = Player shadow mesh

At 90 degree rotation intervals for the player mesh it works beautifully, but at anything in between (37 degrees, -52 degrees, etc.) the shadow is not flattened to the ground - it sticks up at an angle and goes through the ground, because the scale is not correct.

Heeeeeeeelp! *pulls hair out*


Rottbott(Posted 2003) [#2]
OK, I just figured out that my rotation code is totally wrong as well so now I need even *more* help.

I need some way to AlignToVector, except with a floating point axis. So I have an axis defined by a vector XYZ, and I need to align *that* vector, to the normal of the ground I get from LinePick. Instead of just the X, Y or Z axis.

THEN I need to work out the scaling thing.

Sswift... Floyd... anyone? :-) Someone must know this!


Ross C(Posted 2003) [#3]
Mmmmm. How about using the collision normals you get from the linepick collision, and taking the Sin of that, and rotating it? Also, since you shadow is flat, why are you scaling it in the y direction? See the shadow when it's not rotated, is it like a a billboard, in regards to rotation?


Rottbott(Posted 2003) [#4]
Ross,

I scale it in the Y direction because it's basically a copy of the player mesh, so it needs height. It only needs to be flattened on the local axis which corresponds to the global Y-axis - which in actual fact is a bit on the X axis and a bit on the Z axis.

The first thing I need to do is work out how to get "rotation XYZ" for my shadow mesh which will cause "vector XYZ" in the shadow mesh to algin with "normal XYZ" which I get from the LinePick.


TartanTangerine (was Indiepath)(Posted 2003) [#5]
Try not to overcomplicate things.

Try this piece of code after you do a line pick and delete everything else

nx# = PickedNX()
ny# = PickedNY()
nz# = PickedNZ()
AlignToVector pThis\ShadowEN,nx,ny,nz,0

That's all I use and it works perfectly.


Ross C(Posted 2003) [#6]
Why don't you use a sprite for you shadow?

Set the camera to the lights position,

Point the camera at the player,

Color your entity a couple of shades above black,

Set the cameraclscolor to black,

Copy this to a sprite (using copyrect and the VRAM flag on) and you'll have a sprite shadow from the light's location.

You'll need to hide all other entities and lights when doing this, apart from the entity you want a shadow of, of course :).


Rottbott(Posted 2003) [#7]
Ross, doing that for 50 players, 20 horses and maybe some enemies as well, every single frame, would kill it!

Flynn, that seems to be exactly the same as AlignToVector with the third (Z) axis. It works, but I want my shadow to change shape as the player rotates. So if my player turns side-on to the light source, the shadow-player mesh should roll to match the player's yaw, and then it needs rescaling to be flat on to the ground. The problem is getting that to work at any angle.

So the first thing to do is find how to AlignToVector using a local-vector to align with, rather than an axis as Blitz's AlignToVector function uses.


_Skully(Posted 2003) [#8]
lol.. and flattening and displaying "50 players, 20 horses and maybe some enemies as well" wouldn't kill it?

skully


Rottbott(Posted 2003) [#9]
It will merely render each twice, except rather faster since the shadow copies have much smaller textures. The time for flattening should be negligible.

No CopyRect-ing involved, and everything is rendered in one call to RenderWorld.