Skip to main content
Home Forums Silverlight Programming Programming with .NET - General 3d Rotating Picture Cube in Iron Python (lots of code)
7 replies. Latest Post by Jubber on July 11, 2007.
(0)
mrtrombone
Member
65 points
33 Posts
07-02-2007 4:23 AM |
Hi all. I can't be bothered blogging so thought I would share this with anyone who is interested. It is the source for a rotating picture cube, similar to the Telerik control - although I haven't turned it into a control (this shouldn't be hard) or handled clicks yet (this might be). The images are stored in an images folder in the root directory. I used photos from the photoviewer example and cropped them square. The pictures array contains the image names.
This is my first real experimentation with IronPython and I must tell you that it is really very nice and succinct to develop with compared to C#. Also much faster since don't need to compile. I have just been developing from notepad.
The brains behind the code actually comes from the following flash tutorial so full props to them. I encourage other users to get busy converting interesting flash examples across to Silverlight so the community can learn:
http://www.senocular.com/flash/tutorials/transformmatrix/
Anyway I hope someone finds this useful
Cheers
Mark
XAML CODE
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="1000" Height="800" x:Name="Root" Background="#FF000000" > <x:Code Source="Code.py" Type="text/python" /> <Canvas Loaded="Loaded" /> <Canvas.Resources> <Storyboard x:Name="timer"><DoubleAnimation Duration="00:00:0.02" /></Storyboard> </Canvas.Resources> <Canvas x:Name="Inner" Width="300" Height="300" Canvas.Top="200" Canvas.Left="300"/> <Rectangle x:Name="rec" Width="30" Height="30" Fill="Blue" Opacity="0"/></Canvas>
Python Code
import clrimport Systemfrom System.Windows.Controls import *from System.Windows.Media import *from System.Windows import *from System.Windows.Shapes import *from System.Windows.Media.Animation import *from System.Math import *pictures = ['sqjaguar', 'sqgorilla', 'sqgyr', 'sqheron', 'sqeagle', 'sqtamarin']rotations = {'x': 0, 'y': 0, 'z': 0}boxPoints = [{'x': -50, 'y': -50, 'z': -50}, {'x': 50, 'y': 50, 'z': -50}, {'x': -50, 'y': 50, 'z': -50}, {'x': -50, 'y': -50, 'z': 50}, {'x': 50, 'y': -50, 'z': 50}, {'x': 50, 'y': 50, 'z': 50}]curX = 0curY = 0 def pointsTransform(tripoints, rotations): v10 = Sin(rotations['x']) v12 = Cos(rotations['x']) v8 = Sin(rotations['y']) v11 = Cos(rotations['y']) v7 = Sin(rotations['z']) v9 = Cos(rotations['z']) v1 = len(tripoints)-1 v17 = [{'x': 0, 'y': 0}, {'x': 0, 'y': 0}, {'x': 0, 'y': 0}, {'x': 0, 'y': 0}, {'x': 0, 'y': 0}, {'x': 0, 'y': 0}] while (v1>=0): v16 = tripoints[v1]['x'] v15 = tripoints[v1]['y'] v3 = tripoints[v1]['z'] v5 = v12 * v15 - v10 * v3 v4 = v10 * v15 + v12 * v3 v18 = v11 * v4 - v8 * v16 v6 = v8 * v4 + v11 * v16 v14 = v9 * v6 - v7 * v5 v13 = v7 * v6 + v9 * v5 v17[v1] = {'x': v14, 'y': v13} v1 -= 1 return v17def canvasPointTransform(i, a, b, c): photo = Root.FindName("Photo%i" % i) photo.Opacity = pointsIsVisible(a, b, c) if (photo.Opacity==0): return mt = Root.FindName("Matrix%i" % i) matrix = mt.Matrix matrix.OffsetX = b['x'] matrix.OffsetY = b['y'] matrix.M11 = (a['x'] - b['x']) / photo.Width matrix.M12 = (a['y'] - b['y']) / photo.Width matrix.M21 = (c['x'] - b['x']) / photo.Height matrix.M22 = (c['y'] - b['y']) / photo.Height mt.Matrix = matrix def pointsIsVisible(a, b, c): v5 = b['x'] - a['x'] if (v5==0): return (a['y'] > b['y']) == (c['x'] > a['x']) v4 = c['x'] - a['x'] if (v4==0): return (a['y'] > c['y']) == (b['x'] < a['x']) return (((b['y'] - a['y']) / v5) < ((c['y'] - a['y']) / v4)) != ((a['x'] < b['x']) == (a['x'] > c['x'])) def CreatePhoto(sequence, x, y, path): t = XamlReader.Load(""" <Canvas xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' x:Name='Photo%i' Width='111' Height='111' Canvas.Left='%d' Canvas.Top='%d' Background='#FFFFFFFF'> <Image Width='111' Height='111' Canvas.Left='0' Canvas.Top='0' Source='%s' /> <Canvas.RenderTransform> <MatrixTransform x:Name='Matrix%i' Matrix="1,0,0,1,0,0"/> </Canvas.RenderTransform> </Canvas>""" % (sequence,x, y, path,sequence)) Inner.Children.Add(t) def timer_Completed(sender, e): rotations['x'] -= curY / 2000 rotations['y'] += curX / 2000 try: v2 = pointsTransform(boxPoints, rotations) canvasPointTransform(0, v2[2], v2[0], v2[3]) canvasPointTransform(1, v2[5], v2[1], v2[2]) canvasPointTransform(2, v2[0], v2[2], v2[1]) canvasPointTransform(3, v2[4], v2[3], v2[0]) canvasPointTransform(4, v2[3], v2[4], v2[5]) canvasPointTransform(5, v2[1], v2[5], v2[4]) except System.Exception, e: debug.TextWrapping = System.Windows.TextWrapping.Wrap debug.Text = e.ToString() timer.Begin()def mouseMove(sender, e): global curX global curY pt = e.GetPosition(Inner) curX = pt.X curY = pt.Ydef Loaded(sender, e): global pictures global boxPoints global rotations elt = System.Windows.XamlReader.Load(""" <Canvas xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' Canvas.Top="50" Width="500" Height="500"> <TextBlock x:Name='debug' Foreground="White" Width="500" Height="500" Text='' /> </Canvas>""" ) Root.Children.Add(elt) sequence = 0 while sequence < len(pictures): CreatePhoto(sequence,0, 0,"images/%s.jpg" % pictures[sequence]) sequence += 1 Inner.MouseMove += mouseMove timer.Completed += timer_Completed timer.Begin()
heuertk
Participant
1387 points
423 Posts
07-02-2007 1:20 PM |
do you have a site where this is working so we can see it in action?
07-02-2007 4:14 PM |
No I'm afraid not. If someone else wants to host it I can email the files.
07-02-2007 4:38 PM |
yeah, send me the files, i'll put it up...
07-03-2007 1:44 PM |
posted here: http://timheuer.com/blog/archive/2007/07/03/14127.aspx
Jubber
40 points
24 Posts
07-04-2007 12:01 AM |
Hey Mark,
great example of what's possible with Silverlight.
I did find that the anything you draw on the side of the cube, is drawn backwards. I'm still trying to decypher the code. Have to think back to highschool and Matrix calculations
I found that if you update that 'canvasPointTransform' method, and replace :
matrix.OffsetX = b['x'] matrix.OffsetY = b['y'] matrix.M11 = (a['x'] - b['x']) / photo.Width matrix.M12 = (a['y'] - b['y']) / photo.Width
WITH
matrix.OffsetX = a['x'] matrix.OffsetY = a['y'] matrix.M11 = (b['x'] - a['x']) / photo.Width matrix.M12 = (b['y'] - a['y']) / photo.Width
you will get the canvas of each photo drawn the corrent way.
Thanks for sharing this.
Vadim
07-04-2007 4:40 AM |
Good to know thanks Vadim. It would be quite interesting to extend the example and put things like buttons on the different canvases
Also would be good to figure the math for a click so you could determine which photo was clicked on.
07-11-2007 2:49 AM |
I've been playing around with the cube here and there, but given that I'm not python guru, I decided to convert it to C#.
It's not the most elegant of code, but hey, I'm just playing. I've got a control now on each side of the cube and when clicked on, it plays a video.
Here is link to the example.
and here's the link to the source zip.
Thanks for sharing your python code. This has been quite fun actually.
I also talk a little about it in my blog - VTonMS.