Hi ... I am developing a comic software, where the character can be posed.
The character is built using various body parts, and each body part has the following properties
1) Location 2) Rotation Point (Joint) and 3) Rotation Angle
They are each individually set and a default pose is created. (You can check the first image)
Now I want to allow the user to be able to create a new pose for this. While doing this, I have to rotate attached parts together (For example, if lower arm is rotated, the palm should rotate). Unfortunately I am unable to arrive at the right logic, probably due to my limited capability of thought. Can some one help me here ? I have attached 2nd Image which talks about it (Lower arm is rotated, but the palm is going elsewhere)
I tried these methods Method A:
1) TranslateTransform to RotLoc of Lower arm,
2) RotateTransform by new angle required
3) Draw Lower arm
4) TranslateTransform to RotLoc of Palm,
5) Rotate Transform by Palms original angle
6) Draw Palm
8) Reset Transform Method B
1) TranslateTransform to RotLoc of Lower arm,
2) RotateTransform by new angle required
3) Draw Lower arm
4) Find out new RotLoc of Palm by the sweep of newangle-old angle using two methods
newX= oldX+ radius * cos(angle)
newX= oldY+ radius* cos(angle)
5) Translate to the newX,newY
6) Rotate Transform by Palms original angle
7) Draw Palm
First of all what you are trying to do is more complex than I think you think it is.
Basically you are going to have to keep track of all rotation center points you want to animate, what body parts own those points and what body parts use them for rotation.
Some of those points will be relocating to new positions as the body parts move.
First of all what you are trying to do is more complex than I think you think it is.
Basically you are going to have to keep track of all rotation center points you want to animate, what body parts own those points and what body parts use them for rotation.
Some of those points will be relocating to new positions as the body parts move.
The Protected Overrides Sub OnPaint() Event is where the magic happens.
Beyond that I would suggest you try to request help from passel. He is well versed in graphics.
Yeah I know the level of complexity involved. In the default pose, each image is individually handled, and so, the join points, locations, angles are saved. From there, for posing, it is a different path I need to follow. Images are linked. So I started with a basic set of two objects (Lower arm and Palm), so that once successful, I can work with others.
Okay. Up to you. What the sample code shows it that you translate the center point of the image to 0,0 ,rotate, then translate back to the original position. (or something similar.)
Burn the land and boil the sea
You can't take the sky from me
Okay. Up to you. What the sample code shows it that you translate the center point of the image to 0,0 ,rotate, then translate back to the original position. (or something similar.)
Yep, thanks for it. I already achieved it in setting the Default Pose.
Without the images to play with, or a project, I can't do a lot.
But perhaps a recent example in another thread might be useful.
Its quite simple, so won't fit what you're doing exactly, but it does contain a number of visual objects, that are connected together (essentially a chain) so that they twist and move together.
The images are around 200 pixels wide, so the logic is that you drag from one end, it rotates around its center, and there is a "hitch" point at the other end where the next images is attached by its drag point.
In Post #3 of that thread is another example, but this time is not as related, as it is just an example showing the start of drawing an avionics instrument. The interesting part, I think, is that is has an interactive Step by Step mode that goes through the drawing process, explaining what the code is doing, and illustrates the point of view I take when interpreting how the drawing context is managed.
That is, rather than thinking of the matrix as moving an object to 0,0 acting on it, and moving it back to where it was, I think of the drawing process as moving the coordinate system origin out to some point, and transforming the coordinate system and drawing the object always the same way (i.e. straight up), but it isn't drawn straight up because the coordinate system has been rotated.
Both ways of viewing how the transformations work are valid interpretations and have the same result, I just find it easier when drawing multiple objects at different areas and rotations as viewing that from the objects perspective, the coordinate system never changes, (0,0) is always at the center of rotation of whatever part is being manipulated, it is just like you're constantly moving the graph paper that your object is draw on around, and rotating and or scaling that.
Don't know if you are digesting the previous examples, but I thought this would be entertaining enough, that I've worked up another example. Didn't quite finish all the parts (the feet are the last parts I planned for the example, but I've got some other work to do, so will pack this up as is.
To start working on the example, I wanted to find a suitable image to work with I did a search on Paper Puppets, the cardboard figures with a rivet at the joints where you can rotate the parts, and found a site which had a good size image with the rivet points identified, so captured it and worked in paint to pull it into pieces, and get the offset numbers for the various points.
The reference point (in this context) of an image is the pixel offset (x,y) in the bitmap that you want to align with a joint, which the image will rotate around. The joint of a part is the pixel offset (x,y) relative to the reference point of that part, where the next part's reference point is to be located.
So, a hand which is at the end of a series of connect points will have a reference point (its point to be attached), but no joint point, as there is not a subsequent part to be attached to the hand. (the class does have a joint point, but it isn't set to anything, and the fact that there is not a "next part" object reference in the class is what indicates this is the end of the connected parts.
So, the parts are linked reference point to joint in a hierarchy.
The top level is the body, and the reference point for the body is an (x,y) offset somewhere near the center of the body. The reference point is the point that specifies the objects position, and is what the object rotates around if you want that.
The Joints that are part of the body (left,right shoulder (I misspelled shoulder throughout my code and notes) and left and right hips) are defined relative to the reference point, so the left side coordinates have a negative X offset, and the shoulders, which are above the bodies reference point have a negative value.
So, the method I use to draw the body follow this outline
Code:
Paint
TransLate to Center of body Pin
Call DrawBody
Rotate body
Save Matrix
TransLate to LeftSholder Pin
Call LeftShoulder
Rotate Sholder
Save Matrix
Tranlate to Left Arm Pin
Call LeftArm
Rotate LeftArm
Save Matrix
Translate to Hand Pin
Call LeftHand
Rotate LeftHand
Draw Hand
Return
Restore Matrix
Draw LeftArm
Return
Restore Matrix
Draw Sholder
Return
Restore Matrix
Translate to RightSholder Pin
Call RightSholder
....
Restore Matrix
Translate to LeftHip Pin
Call LeftHip
...
Restore Matrix
Translate to RightHip Pin
Call RightHip
Note that in this example I draw in order from the hand back to the body. This is because that is the way paper puppets are put together, overlapping from center to extremities.
In actual practice, there would probably be a more involved drawing order, with parts of the main body probably drawn at different times in the process, likely with some clipping areas, so that the arms can show in front of the body, and not go behind the body because of the drawing order.
Used a couple of classes to reduce redundant code, one that supports a single chain of parts (hooked reference point to joint, with a reference to the next part in the chain.
The other is the main body part, which has a list of parts that are linked to it. (which I guess technically is using a small class within the class to tie those joints to the first part of a chain (possibly) of parts.
Before I wrote any code, once I selected the picture, I wrote down some notes about the offsets in the picture also what things I figured I wanted in a class to support the task, and an outline of the logic flow when painting (which I copied and pasted above).
I'll include the notes file as well, although there shouldn't be much to glean from that at this point.
p.s. I forgot to mention you can drag with the left mouse on the picturebox to re-position the figure. Dragging left or right with the right mouse will change the size of the drawing.
Last edited by passel; Jan 24th, 2019 at 01:52 PM.
For no particular reason, I thought I'd create a doppelganger puppet, (a mini-me) for a little entertainment, using the existing parts defined for the first puppet. Since they use the same parts, they should move in synchronization when the parts are manipulated.
So in the declaration's area where the first puppet is created, create a second one, but locate it further to the right and up a bit (since it will be smaller) from the other.
Code:
Private aPuppet As New Puppet(My.Resources.body, New Point(200, 300), New Point(65, 247)) '(image, location, rotation point)
'For extra entertainment, lets create a doppleganger puppet to mimic the first, (but will make it smaller later)
Private puppetB As New Puppet(My.Resources.body, New Point(600, 150), New Point(65, 247)) '(image, location, rotation point)
In the Form_Load event handler, link the same parts to it by copying the code from the first (Changed to using a 'With clause' to make copy easier). Also scale the second puppet to 1/2 size.
Code:
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
With aPuppet
.Add(LeftUpperArm, New Point(-39, -83))
.Add(rightUpperArm, New Point(37, -83))
.Add(leftUpperLeg, New Point(-28, 74))
.Add(rightUpperLeg, New Point(29, 74))
End With
With puppetB
.Add(LeftUpperArm, New Point(-39, -83))
.Add(rightUpperArm, New Point(37, -83))
.Add(leftUpperLeg, New Point(-28, 74))
.Add(rightUpperLeg, New Point(29, 74))
End With
puppetB.Scale = 0.5
End Sub
Then add the code to draw the second puppet in the Paint event, resetting the drawing matrix to its default value between puppet drawings
Code:
Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
With aPuppet
e.Graphics.TranslateTransform(.Location.X, .Location.Y)
.Draw(e.Graphics)
End With
e.Graphics.ResetTransform()
With puppetB
e.Graphics.TranslateTransform(.Location.X, .Location.Y)
.Draw(e.Graphics)
End With
End Sub
That's it. Could actually use an array and create a bunch of puppets all moving in sync with the control inputs, but not much point in that.
p.s. .... but, what the hay.
Code:
Private gang(8) As Puppet
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
With aPuppet
.Add(LeftUpperArm, New Point(-39, -83))
.Add(rightUpperArm, New Point(37, -83))
.Add(leftUpperLeg, New Point(-28, 74))
.Add(rightUpperLeg, New Point(29, 74))
End With
With puppetB
.Add(LeftUpperArm, New Point(-39, -83))
.Add(rightUpperArm, New Point(37, -83))
.Add(leftUpperLeg, New Point(-28, 74))
.Add(rightUpperLeg, New Point(29, 74))
End With
puppetB.Scale = 0.5
Dim b As Bitmap = New Bitmap(My.Resources.body)
Dim rp As Point = New Point(65, 247)
Dim p As Integer
For y As Integer = 0 To 2
For x As Integer = 0 To 2
p = y * 3 + x
gang(p) = New Puppet(b, New Point(400 + x * 75, 300 + y * 150), rp)
With gang(p)
.Add(LeftUpperArm, New Point(-39, -83))
.Add(rightUpperArm, New Point(37, -83))
.Add(leftUpperLeg, New Point(-28, 74))
.Add(rightUpperLeg, New Point(29, 74))
.Scale = 0.25
End With
Next
Next
End Sub
'...
Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
With aPuppet
e.Graphics.TranslateTransform(.Location.X, .Location.Y)
.Draw(e.Graphics)
End With
e.Graphics.ResetTransform()
With puppetB
e.Graphics.TranslateTransform(.Location.X, .Location.Y)
.Draw(e.Graphics)
End With
For Each p As Puppet In gang
e.Graphics.ResetTransform()
e.Graphics.TranslateTransform(p.Location.X, p.Location.Y)
p.Draw(e.Graphics)
Next
End Sub
Last edited by passel; Jun 22nd, 2016 at 03:28 PM.
Don't know if you are digesting the previous examples, but I thought this would be entertaining enough, that I've worked up another example. Didn't quite finish all the parts (the feet are the last parts I planned for the example, but I've got some other work to do, so will pack this up as is.
To start working on the example, I wanted to find a suitable image to work with I did a search on Paper Puppets, the cardboard figures with a rivet at the joints where you can rotate the parts, and found a site which had a good size image with the rivet points identified, so captured it and worked in paint to pull it into pieces, and get the offset numbers for the various points.
The reference point (in this context) of an image is the pixel offset (x,y) in the bitmap that you want to align with a joint, which the image will rotate around. The joint of a part is the pixel offset (x,y) relative to the reference point of that part, where the next part's reference point is to be located.
So, a had which is at the end of a series of connect points will have a reference point (its point to be attached), but no joint point, as there is not a subsequent part to be attached to the hand. (the class does have a joint point, but it isn't set to anything, and the fact that there is not a "next part" object reference in the class is what indicates this is the end of the connected parts.
So, the parts are linked reference point to joint in a hierarchy.
The top level is the body, and the reference point for the body is an (x,y) offset somewhere near the center of the body. The reference point is the point that specifies the objects position, and is what the object rotates around if you want that.
The Joints that are part of the body (left,right shoulder (I misspelled shoulder throughout my code and notes) and left and right hips) are defined relative to the reference point, so the left side coordinates have a negative X offset, and the shoulders, which are above the bodies reference point have a negative value.
So, the method I use to draw the body follow this outline
Code:
Paint
TransLate to Center of body Pin
Call DrawBody
Rotate body
Save Matrix
TransLate to LeftSholder Pin
Call LeftShoulder
Rotate Sholder
Save Matrix
Tranlate to Left Arm Pin
Call LeftArm
Rotate LeftArm
Save Matrix
Translate to Hand Pin
Call LeftHand
Rotate LeftHand
Draw Hand
Return
Restore Matrix
Draw LeftArm
Return
Restore Matrix
Draw Sholder
Return
Restore Matrix
Translate to RightSholder Pin
Call RightSholder
....
Restore Matrix
Translate to LeftHip Pin
Call LeftHip
...
Restore Matrix
Translate to RightHip Pin
Call RightHip
Note that in this example I draw in order from the hand back to the body. This is because that is the way paper puppets are put together, overlapping from center to extremities.
In actual practice, there would probably be a more involved drawing order, with parts of the main body probably drawn at different times in the process, likely with some clipping areas, so that the arms can show in front of the body, and not go behind the body because of the drawing order.
Used a couple of classes to reduce redundant code, one that supports a single chain of parts (hooked reference point to joint, with a reference to the next part in the chain.
The other is the main body part, which has a list of parts that are linked to it. (which I guess technically is using a small class within the class to tie those joints to the first part of a chain (possibly) of parts.
Before I wrote any code, once I selected the picture, I wrote down some notes about the offsets in the picture also what things I figured I wanted in a class to support the task, and an outline of the logic flow when painting (which I copied and pasted above).
I'll include the notes file as well, although there shouldn't be much to glean from that at this point.
p.s. I forgot to mention you can drag with the left mouse on the picturebox to re-position the figure. Dragging left or right with the right mouse will change the size of the drawing.
This is awesome... The first example, though I understood drag and hitch points, I couldn't really make use of them in my piece of work. The second example you gave exactly suits my requirement. I will look into the code and keep you posted, how it worked for me. I am sure it would work 100% for me. Thank you so much.
There is a little more extension on the Q, how do you arrive at the Ref Point and Join point, dynamically?
Last edited by sridharavijay; Jun 23rd, 2016 at 03:36 AM.