Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Go Back  Xtreme Visual Basic Talk > > > Exploring 3D graphics with VB.Net, but without using DirectX or XNA


Reply
 
Thread Tools Display Modes
  #21  
Old 12-16-2014, 06:20 AM
boops boops's Avatar
boops boops boops boops is offline
Centurion
 
Join Date: Dec 2006
Location: Holland and France
Posts: 146
Default


Thanks for looking at the code Passel.

The appropriate wheel delta divisor depends on the mouse hardware. Dividing by 10 is fine for me, but I should remind people to adjust it for their own system.

Your change to the Point3D.p2D function effectively deals with the geometrical error with negative Z (the black hole effect). I had initially worked out the geometry on a scrap of paper (just similar triangles, after all) and it seemed to work first time; but I wrongly identified eye location with camera location.

I think I have identified the cause of the lockup. In the form's Paint event handler, replace the SetClip statement by a FillPath; and remove the face.Paint statement to skip the fill colors.
Code:
If gp IsNot Nothing Then
	Try
		'e.Graphics.SetClip(gp, Drawing2D.CombineMode.Exclude)
		e.Graphics.FillPath(Brushes.White, gp)
	Catch
		Debug.WriteLine("graphics path error")
	End Try
End If
'face.Paint(e.Graphics)
Now we have an anatomically correct glass cube with opaque white lettering. Zooming into the cube goes smoothly until the camera hits the glass. Then the whole thing smashes to smithereens.

I suppose you could call that realistic, and maybe it's an nice effect for some situations. But the aim was to pass noiselessly through the glass and show a view of the cube interior. A little rethinking is called for.

Anyway, my conclusion for the moment is that grinding to a halt was the result of using a series of complex paths (with over 15K pathpoints counting all the visible faces) to set the graphics clip. GDI+ clipping apparently can't cope with it, but GraphicsPath.Fill has no problem with the same data.

BB
Reply With Quote
  #22  
Old 12-16-2014, 05:03 PM
passel's Avatar
passelExploring 3D graphics with VB.Net, but without using DirectX or XNA passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,024
Default

Quote:
Originally Posted by boops boops View Post
... I had initially worked out the geometry on a scrap of paper (just similar triangles, after all) and it seemed to work first time; but I wrongly identified eye location with camera location.
...
I suppose you have the correct understanding now, although I don't know if the terms are used correctly.
The eye location and the camera location are typically considered to be the same thing, I think.
But there is that distance from camera/eye to the viewing plane which is what we're talking about and I don't know if that quantity has a specific term, like eye distance, or focal length, or some other term that connotes that value. It is directly related to the Field of View of course, but is not the Field of View.
At this point, that Z value can be considered relative. Are we moving the camera back by that Z value, or moving the object away by that Z value, in our calculations.

I guess now that you're not filling the faces, the following two comments don't matter, but I'll post them anyway.

1. I noticed that you draw the text (fillpath), before you draw the face.
I like the contrast a lot better when you draw the text on the face, rather than showing "through" the face.
Code:
'in the paint code
        If gp IsNot Nothing Then
          face.Paint(e.Graphics)  '<=== moved face.Paint to here
          Try
            ' e.Graphics.SetClip(gp, Drawing2D.CombineMode.Exclude)
            e.Graphics.FillPath(Brushes.White, gp)
          Catch
            'skip spurious error
          End Try
        End If
        'face.Paint(e.Graphics)
'        e.Graphics.ResetClip()
      End If
2. When the cube was rotating I noticed occasional flashes along the seams.
It turned out that the cause was it was drawing the silver backside color on the front for a frame or two during the back to front transitions. (It also drew front colors for a frame or two going the other way).
The reason was in the Face Paint sub, the Me.FrontPresentation property was using stale Vertices2d data, while the drawing later in the paint calculated new values and drew with them. So I just had the vertices fetched up front (calculating the new 2d values) so FrontPresentation used the latest values, and those were also then used in the FillPolygon.
Code:
 Public Overridable Sub Paint(g As Graphics)
    Dim clr As Color
    Dim bogus() As PointF = Me.Vertices2D 'get new calculated values before getting FrontPresentation
    If Me.FrontPresentation Then
      clr = FillColor
      Debug.Print("Front")
    Else
      clr = FillColorBack
      Debug.Print("Back")
    End If
    Using sbr As New SolidBrush(clr)
      '      g.FillPolygon(sbr, Me.Vertices2D)
      g.FillPolygon(sbr, bogus) 'draw with the prefetched values
    End Using
  End Sub
As for the breaking up, in the p2D function, when the zDist goes negative, your X and Y values for those points jump to the other hemispheres so you get those typical hour glass polygons, instead of a closed figure.
There should be a way to calculate those points, but for now, all I did was cap the zDist to a minumum of 0.1 and increased the eye to screen distance to 2000 for a narrower field of view.
You can see the letters slide on on surface because the points behind the eyepoint freeze at the .1 distance, but at least it looks better than the hourglass shaped squares.
Code:
  'get 2D projection on Z=0 plane of a Point3D:
  Private Function p2D(p3D As Point3D) As PointF
    Dim zDist As Double = Scene.Camera.Z - p3D.Z
    If zDist <= 0 Then
      zDist = 0.1
      '     Return New PointF(CSng(p3D.X), CSng(p3D.Y))
      '   Else
    End If
    '      Dim f As Double = Scene.Camera.Z / zDist
    Dim f As Double = 2000 / zDist
    'If p3D.Z < 0 Then f = 1 / f
    Return New PointF(CSng(p3D.X * f), CSng(p3D.Y * f))
    ' End If
  End Function
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
  #23  
Old 12-17-2014, 10:44 AM
boops boops's Avatar
boops boops boops boops is offline
Centurion
 
Join Date: Dec 2006
Location: Holland and France
Posts: 146
Default

Quote:
Originally Posted by passel View Post
I suppose you have the correct understanding now, although I don't know if the terms are used correctly.
The eye location and the camera location are typically considered to be the same thing, I think.
But there is that distance from camera/eye to the viewing plane which is what we're talking about and I don't know if that quantity has a specific term, like eye distance, or focal length, or some other term that connotes that value. It is directly related to the Field of View of course, but is not the Field of View.
At this point, that Z value can be considered relative. Are we moving the camera back by that Z value, or moving the object away by that Z value, in our calculations.
I think the terms Camera and EyeDistance are defensible. The latter is now a property of Scene with a default Z of 2000.
Quote:
I guess now that you're not filling the faces, the following two comments don't matter, but I'll post them anyway.

1. I noticed that you draw the text (fillpath), before you draw the face.
I like the contrast a lot better when you draw the text on the face, rather than showing "through" the face.
That's up to you. Now you can specify whatever face-fill colors and text color you like, and reverse them at the click of a CheckBox. I've solved the problem of clipping out the text by using the GraphicsPath itself. Adding a the source rectangle to the path takes advantage of the default FillMode.Alternate to flip the fill colors.
Code:
Private Function WarpTextPath(face As Face3D, fnt As Font, inverse As Boolean) As Drawing2D.GraphicsPath
	Dim gp As New Drawing2D.GraphicsPath
	With face
		gp.AddString(face.DisplayText, fnt.FontFamily, 1, fnt.Size, srcRect, New StringFormat)
		Dim destpoints() As PointF = _
		{.Vertices(0).To2D, .Vertices(1).To2D, .Vertices(3).To2D, .Vertices(2).To2D}
		gp.Warp(destpoints, srcRect, Nothing, Drawing2D.WarpMode.Perspective)

		If inverse Then gp.AddPolygon({.Vertices(0).To2D, .Vertices(1).To2D, .Vertices(2).To2D, .Vertices(3).To2D})
	End With
	Return gp
End Function
Quote:
2. When the cube was rotating I noticed occasional flashes along the seams.
It turned out that the cause was it was drawing the silver backside color on the front for a frame or two during the back to front transitions. (It also drew front colors for a frame or two going the other way).
The reason was in the Face Paint sub, the Me.FrontPresentation property was using stale Vertices2d data, while the drawing later in the paint calculated new values and drew with them.
So I just had the vertices fetched up front (calculating the new 2d values) so FrontPresentation used the latest values, and those were also then used in the FillPolygon.
Thanks for spotting that. I solved it by getting the values through the property getter, which I should have done in the first place. In the present version I'm not using different colors for inside the cube, but I've checked that they now work.
Quote:
As for the breaking up, in the p2D function, when the zDist goes negative, your X and Y values for those points jump to the other hemispheres so you get those typical hour glass polygons, instead of a closed figure.
There should be a way to calculate those points, but for now, all I did was cap the zDist to a minumum of 0.1 and increased the eye to screen distance to 2000 for a narrower field of view.
You can see the letters slide on on surface because the points behind the eyepoint freeze at the .1 distance, but at least it looks better than the hourglass shaped squares.
You are largely right about the cause: you can't render anything correctly behind the camera. I have solved that by truncating faces and edges at a chosen Z plane (e.g. Camera.Z - 200). My code walks round each face, adding any vertex within the chosen Z maximum to a list. When it meets a transition from inside to outside the limit (or vice-versa) it adds the point of intersection with the Z plane to the list. It doesn't add points exceeding the maximum. I use the result to apply Graphics.Clip to the rendering each face. Here's my clipping algorithm for faces; possibly it could be more compact: I haven't checked if the final If..Else is really needed.
Code:
'find this face's intersecting polygon with the given Z plane:
Public Function ClipPolygon(zMax As Double) As PointF()
	Dim clipVertices As New List(Of PointF)
	For Each edge In Me.FaceEdges
		With edge
			Dim z1 As Double = .P3D1.Z
			Dim z2 As Double = .P3D2.Z
			If z1 < zMax Then clipVertices.Add(.P3D1.To2D)
			If (z1 < zMax) <> (z2 < zMax) Then
				'find and add the intersection:
				Dim x, y As Double
				If z1 < z2 Then
					Dim f As Double = (zMax - z1) / (z2 - z1)
					x = .P3D1.X + f * (.P3D2.X - .P3D1.X)
					y = .P3D1.Y + f * (.P3D2.Y - .P3D1.Y)
				Else
					Dim f As Double = (zMax - z2) / (z1 - z2)
					x = .P3D2.X + f * (.P3D1.X - .P3D2.X)
					y = .P3D2.Y + f * (.P3D1.Y - .P3D2.Y)
				End If
				clipVertices.Add(New Point3D(x, y, zMax).To2D)
			End If
		End With
	Next
	Return clipVertices.ToArray
End Function
However, there is still some flashing when rendering steeply inclined side faces with text. This shows up particularly when zoomed right into the cube with the form maximized on a wide screen. From the look of it I think it's due to the GraphicsPath.Warp losing some pathpoints under extreme conditions, allowing the path to leak. But setting the eye distance to 2000 has helped a lot.

Now a lot of things work, but there are still some bugs. What happens when you zoom the camera in past the origin...? The new version, attached, is best viewed maximized. The anim is slow, but that's mainly because of all the transparent colors. Try running it without rendering and you'll see how much time is saved per frame!

BB
Attached Files
File Type: zip PerspectiveWarp3_v3.zip (29.5 KB, 20 views)
Reply With Quote
  #24  
Old 12-17-2014, 09:49 PM
passel's Avatar
passelExploring 3D graphics with VB.Net, but without using DirectX or XNA passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,024
Default

Quote:
Originally Posted by boops boops View Post
... The anim is slow, but that's mainly because of all the transparent colors. ...
I also didn't like the stalling of the animation when rolling the wheel.
The anim seem especially slow when zoomed in.

The anim can be easily sped up an appreciable amount by drawing in a BufferGraphics object and rendering to the screen from it.
Also, doing that drawing and rendering from a background thread prevents the stalling of the animation when wheel scrolling or mouse dragging (I had dragging on the form up and down with the mouse move the camera as well, at one point).

Adding the basic BufferedGraphics object and a background thread to do the rendering wasn't difficult. Just moved the drawing code out of the paint event and dropped it in a loop in the background thread and used the BufferedGraphics Graphics object in place of the picturebox graphics object.

Since you only updated the graphics when desired (through Invalidate or Refresh), I wanted the background thread to do the same (rather than just render continually as fast as it could), so added a variable that the GUI side increments any time a change has been made that needs the screen updated, and the background thread loop sees the value change and does an update.

So, the basic change in drawing paradigm was reasonably simple, but then there was the issue of you mentioning maximizing the form. I had to add code to watch for the various resize cases, and readjust the BufferedGraphics object to match the size change. I took the approach of ending the background thread, and restarting it, which as part of its initialization would initialize the BufferedGraphics object to the current form size.

The last piece was even though we aren't painting in the paint event any longer, we still need to know when windows thinks the form should be repainted (someone dragged a window across), so there is a line to increment the form redraw variable in that case as well.

See if it seems a little zippier for you as well.
For me, v3 on my machine ran at about 20fps at startup, around 17fps full screen (1920x1080), and 8.3 fps zoomed in close (z = 90).
v3m using the BufferedGraphics object ran at around 64fps in all three of those situations.
The 64fps seems suspiciously like something is tied to the 64hz clock tick that most winform timers are limited to.
In the past I've had a BufferedGraphics object able to update a window thousands of times a second, and I know that transparent drawing is going to cut the framerate nearly in half, but being 64hz for all three situations just feels like something else is throttling the thread.
I have a sleep(1) in there, and I believe on my machine a Sleep(1) will usually actually sleep the 15.625ms (64hz) period, but I commented that out, so the background thread wasn't calling the sleep, just running in an endless loop, and it still updated at 64 hz.
Oh, wait a minute. I just realized of course. Your timer is bumping the flag at 64 hz, and the background thread only draws then, so I'm sync'd to your timer.

Moving your timer code into the background loop with some minor adjustment (can't access the checkbox crossthread), it runs a little faster. About 88fps at startup, just about the same speed, 87 or so at full screen, and 77fps, zoomed in (Z=90) and fullscreen.

The attached zip file doesn't have this last modification in it, and I prefer to have the sleep(1) to give a small rest to the processor each loop.
The times above were with the sleep(1) in it. If I comment that out, the default startup speed is running at about 95 fps.
That BufferedGraphics object really helps this particular situation.

p.s. One more thing that I forgot to add, and became apparent when running the background thread at full throttle so it was rendering at max speed, when closing the main form we need to gracefully exit the background thread, or the form that the thread is trying to render on might be pulled out from under it mid render. So add the following.
Code:
  Private Sub Form1_v3_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    stopThread = True 'Tell the background thread to exit (stop rendering)
    tickThread.Join() 'Wait for it to finish before exiting 
  End Sub
p.p.s ***!!!!!!!!!!!!!!!!!!!************************************************ *****************************
My timings were all wrong above.
The BufferdGraphics was faster, but not nearly that much faster.
The first timings of 64hz, was because the timing was done in your timer_tick event, and all it was really timing was how many times the timer fired. Since there was no graphics being done in the GUI thread, the timer was able to fire at its full 64hz rate.
When I copied the code over to the Background thread, I left it in the timer so now the frames count was being incremented by both, so the fps count was 64hz faster than it should have been.
So, the real numbers aren't nearly as impressive.
The speed increase was only about 50%, not 400%, so the default startup ran at about 32hz, vs the 20hz of the non-BufferedGraphics code.
And the fullscreen, Z=90 zoom speed was about 14hz, vs 8.3 hz.

I don't know that I can detect much difference between SmoothingMode.HighQuality and commenting that line out, but commenting it out did boost the 32hz speed to around 43hz, so is probably worth not having it high quality.
Attached Files
File Type: zip PerspectiveWarp3_v3m.zip (32.3 KB, 13 views)
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 12-18-2014 at 07:05 AM.
Reply With Quote
  #25  
Old 12-25-2014, 12:58 PM
dotnetwrassler dotnetwrassler is offline
Regular
 
Join Date: Sep 2014
Location: USA (Pacific/West Coast)
Posts: 71
Default boops boops and passel post multiple attachments!

I go away for a little while and suddenly there's multiple posts from two of the forum's graphics experts!

The latest version (3m) seems to go fast in bursts, but was smoother on my machine with sleep enabled.
There's no better person on the forum to tesk a multi-thread version using Buffered Graphics than passel, though.
I totally trust his results.


What I found most noteworthy in the back-and-forth discussions of the last few posts
was the mention of eye to screen distances and a the value of using a narrowing field of view.

I'm still working to understand how the camera placement not only effects the slanting of the sides of the cube,
but also the mapping of the texture to the vertices (it offsets it strangely sometimes).



Quote:
Originally Posted by boops boops
My code walks round each face, adding any vertex within the chosen Z maximum to a list.
When it meets a transition from inside to outside the limit (or vice-verse) it adds the point of intersection with the Z plane to the list
You totally lost me on this..

Did this solve the "smithereens" issue you mentioned in post #21:
Quote:
Now we have an anatomically correct glass cube with opaque white lettering.
Zooming into the cube goes smoothly until the camera hits the glass.
Then the whole thing smashes to smithereens.
I would love to be able to move a camera threw a cube face without the texturemapping going awry.

I love the opaque white lettering, though.
Which brings us to the question back in post #18 about a "movie with a 3D fly thru sequence".
The movie was called "Hackers".
Of course Hollywood got it totally wrong in the hacking scenes, but there was a nice special effect in the movie
that simulating a mythical mainframe named "Gibson" (after the cyberpunk novelist that inspired it).

This was actually done not with computers (remember the movie came out in 1995),
but with a 3D model constructed out of acrylic plastic boxes.

Here is the Aterm portfolio page for the work the special effects house did on the movie.
Down at the bottom of the page is a gallery of photos showing the non-computerized way the effect was produced.

I'll also through in a screenshot at the bottom of this post that shows the buildings
that make up the "City of Text" dataspace (which is a little
of what your PerspectiveWarp attachments seem to be working toward..)



By the by --some programmer actually came up with a screensaver (which he called
"The Gibson" project), based on this City of Text sequence.
It was a 15 post development effort.

Here is post 14 that shows a very crowded set of text cubes for the second "spline" picture.
The download zip for the project (which doesn't work on my computer) is on this page.



Quote:
Originally Posted by boops boops
The real time guzzler in your code is the texture mapping.
I can think of some ways it might be possible to speed it up, but it is never going to get anywhere
near the hardware-accelerated methods of DirectX etc.
I'm more concerned with camera placement (inside the cube)
and moving to more complex 3D texture mapped shapes
than performance at this point.

However your and passel's efforts at tweaking the speed are still appreciated.



Quote:
My guess is that you are repeatedly superimposing the same shape,
scaling it down and increasing the opacity each time.
But I'm sure it's possible to do it with a PathGradientBrush.
You are right, but I'm thinking the corners of the round rect graphics path need to have less arc
as they approach to corners of the cube so this means I will not only
have to play with the opacity but the path shaping as well.

It's really tricky to get the opacity gradient to look the way
I want - with a stronger "glow" in the corners than along the cube edges.
I guess I will have to play around with the overlapping some more --even one pixel overlap differences have big effects.



Quote:
Rotations around cube center points other than (0,0,0) also don't work correctly (yet).
Maybe I'll put off sorting that out until I've replaced the Point3D rotate methods by something with quaternions.
I look forward with great eagerness to any quaternion code you can come up with!

The code in the attachment to post #4 of this thread is really the best non-transparent cube texturemapping with rotation code I have seen,
and I'm still working to realize all the potential ways to work the camera in order to do different things.

Speaking of which - I'm sorry I've slacked off on posting to this thread recently.

I spent most of this week coming up with some holiday themed graphics which I posted here.
It uses the code from post#4 for a Christmas present wrapped base for under the Xmas tree.


Last (but not least) the answer to the other question in post #18 (about the Keanu Reeves with a 3D tanagram) was "Johnny Mnemonic".
It's hard to capture the video sequence with VR gloves re-arranging the parts of the tanagram,
but I'll post a graphic that sort of shows a frame snapshot of the 3D shuffling.

If you watch the extended YouTube cut from the movie (at minute 44 approximately) you'll see
there is also shadowing/shading and a "lightning effect" involved.


However, just thinking about shading, lighting, and shadowing of a 3D cube rotating inside a 3D room
and you'll realize how long and daunting a task it is to have GDI+ try to replicate more hardware accelerated GPU tasks.

Oh well, we'll see how far we can get with this thread.
Attached Images
File Type: jpg screenshot_hackers_city_of_text.jpg (341.9 KB, 17 views)
File Type: jpg two_pics--unlocking_a_3D_tanagram.jpg (122.7 KB, 16 views)
Attached Files
File Type: zip alphaGradient_RoundRect.zip (39.4 KB, 23 views)

Last edited by dotnetwrassler; 12-26-2014 at 12:57 AM.
Reply With Quote
  #26  
Old 12-26-2014, 12:04 AM
dotnetwrassler dotnetwrassler is offline
Regular
 
Join Date: Sep 2014
Location: USA (Pacific/West Coast)
Posts: 71
Default It takes a book to explain things sometimes..

I was doing some searching for mathematical conversions between the different types of 3D rotation:
1.) matrix rotation
2.) Euler angle rotation
3.) Quaternion rotation
..and this one book kept coming up as a recommended primer:
3D Math Primer for Graphics and Game Development

There are two editions:
the 1st edition has 449 pages, and the second edition has 845 pages.

If you google the book title you'll probably find a bunch of free PDFs, like this one.


There's some heavy heavy duty matrix math as well as vector math --which is basically
dealing with first order tensors (see the "fun math" graphic below - the circle with the "x" inside
is the funny/strange math symbol for tensor product)
However, at least there are a few pictures and diagrams thrown in as well.


If you don't want to gulp down that many pages I recommend (for only a casual interest)
at least taking a look at Chapter 8, "Rotations in three dimensions".
That's the one that details the with conversions between different types of 3D rotations.


Chapter 10 also has some nice diagrams like the one I'll attach below that chart
"Coordinate Spaces versus Matrix Operations" (there are at least 5 such spaces --that's why even boops boops/passel had to
do a little "sync up" to get on the same page about coordinate space terminology).

There's also a series of PowerPoint slides (related to the book) on this download page.

Buried amongst all the math in the slide shows, is the story of the man who flashed on the fundamental equation for quaternions
while crossing a bridge (the story is detailed in the huge 400 pixel vertical scrolling graphic attached below
made from some of the slides of just one of the .pptx downloads).
Don't try to view this graphics in the forum's lightbox preview --I recommend copy/pasting the jpg
into the old ribbon-less version of MsPaint that runs under Win7 for easy scrollable viewing.

Here's a quaternion quote from the book:
Quote:
There is a mathematical reason for why using only three numbers to represent
a 3-space orientation is guaranteed to cause the problems we discussed with Euler angles, such as Gimbal lock.
It has something to do with some fairly advanced math terms like “manifolds.”
A quaternion avoids these problems by using four numbers to express an orientation (hence the name: quaternion, where "quat" refers to "4").

Does it have any VB.Net code?
Sorry, its all .cpp and .h files for the book's 1st edition source code (that C plus plus code only) --and I couldn't
find any source code download available for the 2nd edition.


I did find, though, a C# translation of some of the books C++ vectors code,
which I will endeavor to convert to VB.net so I can (maybe/possibly)
do something with simple 3D falling physics involving multiple 3D objects.

See y'all next year...
Attached Images
File Type: jpg Coordinate_Spaces-n-Matrix_Operations.JPG (60.5 KB, 20 views)
File Type: jpg fun_math_from_chapter_10.jpg (106.7 KB, 16 views)
File Type: jpg Thoughts_from_October1843--math_etched_in_a_bridge.jpg (820.9 KB, 16 views)
File Type: jpg 3D_falling_objects.jpg (35.7 KB, 13 views)

Last edited by dotnetwrassler; 12-26-2014 at 12:57 AM.
Reply With Quote
  #27  
Old 01-11-2015, 07:04 PM
dotnetwrassler dotnetwrassler is offline
Regular
 
Join Date: Sep 2014
Location: USA (Pacific/West Coast)
Posts: 71
Default First new post in the new year..

Welcome to 2015!

Sorry I really slacked off after the double posting at the end of 2014,
but I did have a chance to play around with the different perspective warp attachments from previous thread posts..


I really like the white text lettering with the semi-transparent cube face color tinting,
but I wanted to be able use the mouse to drag rotate in different axises,
so I refactor things a bit.

The working code for PerspectiveWarp5 is attached below.
The mouse drag is not as sensitive as I would like and could probably be adjusted if

I knew a bit more about how the Math.Cos was being used to generate numbers such as:
rx = 0.054800597194520351
ry = 1.00990000333328884



I've also been playing around some more with multiplely transformed perspective mappings
(remember my not fully successful attempt back in post #15)

There's some images attached below.
After I got done playing around with the red rotated perspective mapping I realized
that just flipping the blue perspective mapping would give me what I need.


Going forward I want to add a snapTo function to the 4 point drag distort code (from post #9)
so that the textures can be adjusted to align with the intersections of the perspective lines
shown in attachment "Perspective_mapping4d.jpg" below.

Somehow I need to find/determine the x,y values for the points for the perspective line intersections.

Maybe I'll just end up manually coloring the intersection points orange and loop through them
with GetPixel (or FastBitmap) to establish a preliminary point array for tiny "drop zones".

This vb.net code has a way to drag around a set of stored points in an array,
but I'll still need to store the second set of orange pixel points drop zones point in another array to test against.

This would hopefully eventually allow me to make up the walls, floor, and ceiling of a
texture mapped 2.5D "room" of sorts that could be zoomed into (but non-rotatable, though).

I would also like to try and have a "cube array" placed along a baseline floor the City of Text attachment in post #25 above.
Attached Images
File Type: jpg Perspective_mapping4a.jpg (100.8 KB, 10 views)
File Type: jpg perspect_map4b.jpg (77.4 KB, 10 views)
File Type: jpg Perspective_mapping4d.jpg (78.2 KB, 10 views)
Attached Files
File Type: zip PW5_whitetext_MouseDragRotate.zip (118.3 KB, 26 views)

Last edited by dotnetwrassler; 01-11-2015 at 10:20 PM.
Reply With Quote
  #28  
Old 01-12-2015, 02:51 PM
passel's Avatar
passelExploring 3D graphics with VB.Net, but without using DirectX or XNA passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,024
Default

Quote:
Originally Posted by dotnetwrassler View Post
...
I really like the white text lettering with the semi-transparent cube face color tinting,
but I wanted to be able use the mouse to drag rotate in different axises,
so I refactor things a bit.
...
Being able to drag on the cube to move it is a natural thing to try to do.
I also wanted to add some mouse interaction, and I did back before Christmas break, but I didn't post it because I was playing around a bit with the code and had a number of modifications, such as precalculating and caching the Sin,Cos values for the rotations and using the cached value in the point rotations rather than regenerating them for each point. For the limited number of points in these examples, it doesn't increase the speed appreciably and could be considered subverting the class structures and interaction boopsboops has designed so I didn't want to add extra methods and interactions between levels of the class without a big improvement to justify the extra work.

But, I do like the mouse moving modification I made to the demo, so I grabbed a clean copy of boopsboops v3 code (before my BufferedGraphics object modification), and added my axis mouse movement modification to it, so you can at least see that.

Since bb was using a counter to modify the movement of the x and y axis, and the z just moved at a constant, I just moved the rx,ry and rz variables out to where they could be modified by mouse movement, and used a "friction" value to reduce the values, rather than multiplying by the count factor.

So, just a little modification to allow some basic mouse interaction.
If you use the left button it rotates around the Y axis when you move the mouse left and right, and around the X axis when you move the mouse up and down.
If you use the right button, it rotates around the Z axis when you move left and right and around the X axis when you move the mouse up and down.

Moving the mouse will give the rotation some speed, which will continue after you release the mouse (unless you set brake to a low number near or equal to 0).
The code modifications are:
Code:
  Private rx As Double  'moved to the declarations area
  Private ry As Double
  Private rz As Double

'added a MouseMove event handler
  Private Sub Form1_v3_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
    Static lloc As Point
    Dim sensitivity As Double = 100  '100 good when brake is high(e.g. 0.9 to 0.96),
    '                                 10 is good for brake=0 (about one face rotation with one full swipe across page)
    If e.Button = Windows.Forms.MouseButtons.Left Then
      ry += -(e.X - lloc.X) / sensitivity  'Left/Right movement rotates around Y axis
      rx += -(e.Y - lloc.Y) / sensitivity  'Up/Down movement rotates around X axis
    ElseIf e.Button = Windows.Forms.MouseButtons.Right Then
      rz += (e.X - lloc.X) / sensitivity   'Left/Right movement rotates around Z axis
      rx += -(e.Y - lloc.Y) / sensitivity  'Up/Down movement rotates around X axis
    End If
    lloc = e.Location
  End Sub

'Modified the Timer to adjust rx,ry,rz by a braking value at the bottom of the sub.
  Private Sub Timer1_Tick(sender As Object, e As System.EventArgs) Handles Timer1.Tick
    '	Static count As Integer
    '	count = (count + 1) Mod 200
    frames += 1
    'Dim rx = 0.15 - Math.Cos(count / 180) / 10
    'Dim ry = 0.01 + Math.Cos(count / 100) ^ 2
    'Dim rz = 0.15

    For Each face In Cube1.Faces
      For Each corner In face.Vertices
        corner.RotateX(rx / 2, Cube1.Center)
        corner.RotateY(ry / 2, Cube1.Center)
        corner.RotateZ(rz / 2, Cube1.Center)
      Next
    Next
    For Each face In Tet1.Faces
      For Each corner In face.Vertices
        corner.RotateX(0.7 - rx * 4.8, Tet1.Center)
        corner.RotateY(-rz * 2.5, Tet1.Center)
        corner.RotateZ(-ry * 5, Tet1.Center)
      Next
    Next
    Dim Brake As Double = 0.95 '1.0 = no braking, 0.0 = instant braking
    rx *= Brake  '* slow down factor 
    ry *= Brake
    rz *= Brake

    If CheckBox1.Checked Then
      Me.Refresh()
      CheckBox1.Enabled = False
    End If
  End Sub
That's it. I still like the BufferedGraphics object version as the rotation doesn't stop when you rotate the Mouse Wheel. I guess that is a useful thing to be aware of, which I wasn't before, that if you're using a GUI timer to update an image, moving the Mouse Wheel is going to interfere with the timer ticks severely.

p.s. Don't forget to enable the animation by clicking the start/stop button. It won't react to the mouse movements until you enable the animation. I should have defaulted to animation being enabled, I guess, but already posted so won't rework that.
Attached Files
File Type: zip PerspectiveWarp3_v3_modMouse.zip (30.7 KB, 25 views)
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 01-12-2015 at 03:07 PM.
Reply With Quote
  #29  
Old 01-12-2015, 09:07 PM
passel's Avatar
passelExploring 3D graphics with VB.Net, but without using DirectX or XNA passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,024
Default

Since someones already down loaded it, I'll double post rather than add a p.p.s to the previous post, where some may miss the addition.
For the Z-Rotation, it is probably better to change the direction of rotation with mouse movement depending on whether the mouse is above or below the middle of the window.
That is, if the mouse is above the middle and you're moving to the right, then the top of the block should move in the direction of the mouse, i.e. clockwise.
If the mouse is below the middle and moving to the right, then the bottom of the block should move in the direction of the mouse so the block should appear to be rotating counter-clockwise.
The modified MouseMove sub.
Code:
 Private Sub Form1_v3_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
    Static lloc As Point
    Dim sensitivity As Double = 50  '100 good when brake is high(e.g. 0.9 to 0.96),
    '                                 10 is good for brake=0 (about one face rotation with one full swipe across page)
    If e.Button = Windows.Forms.MouseButtons.Left Then
      ry += -(e.X - lloc.X) / sensitivity  'Left/Right movement rotates around Y axis
      rx += -(e.Y - lloc.Y) / sensitivity  'Up/Down movement rotates around X axis

    ElseIf e.Button = Windows.Forms.MouseButtons.Right Then
      If e.Y < ClientSize.Height / 2 Then    'If above the middle of the form
        rz += (e.X - lloc.X) / sensitivity   '  Left to Right movement rotates clockwise around Z axis
      Else                                   'Else
        rz -= (e.X - lloc.X) / sensitivity   ' Left to Right movement rotates counter-clockwise around Z axis
      End If
      rx += -(e.Y - lloc.Y) / sensitivity  'Up/Down movement rotates around X axis
    End If
    lloc = e.Location
  End Sub
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
  #30  
Old 01-14-2015, 04:49 PM
boops boops's Avatar
boops boops boops boops is offline
Centurion
 
Join Date: Dec 2006
Location: Holland and France
Posts: 146
Default

Nice work Passel! I particularly like user-propelled motion with braking effect. The original text cube was meant primarily as a demo of the possibilities of GraphicsPath.Warp. The rotating animation with Refresh provided a reliable way of measuring the frame rate because the Refresh has to be completed before the loop can iterate. Of course, I couldn't resist the temptation to pretty it up.

In case it isn't clear, the Sin and Cos formulae I used to calculate the rotation increments (rx, ry, rz) were just meant to provide pseudo-random motions of the cube which exposed all faces at some or other point. They have no connection with 3D geometry.

I spent some time looking at the BufferedGraphics code in post #24. When run, it produces much larger movements between frames, giving an impression of speed. But the movement was much more jittery and the black edges seemed slightly disconnected from the coloured faces.

I wondered what was going on. My guess is as follows. The rendergraphics.Render statement in the rendering loop doesn't produce an instant update of the screen in the same way as DirectX or XNA would. Presumably it goes through a software layer in the same way as GDI+ rather than writing directly to GPU memory. Consquently the screen is updated only once in several iterations of the loop.

I found that dividing the increment values rx, ry, rz by 8 gave roughly the same speed of movement as the original anim. I couldn't see any obvious difference in the frame rate, but I am not sure how to measure it anyway in that situation. Presumably it's a bit faster because the rendering arithmetic can take place partly in parallel with the screen update on a multi-core processor (in contrast to using Refresh which does one then the other).

There are scenarios were multi-threading could be useful in a processor-hungry animation -- perhaps to compute various resolutions in parallel, so that the anim can always be updated at least with a low-res versions of the graphics. It would be ideal to combine that with faster rendering.

Staying in the Windows Forms biotope, you might think it's a pity there isn't a high-speed PictureBox that uses GPU acceleration to display an image. People have in fact made things like that, such as this XNA Control. I am looking into the possibility of making something similar based on WPF, which does at least put a bitmap on the screen at something like DirectX speed (e.g. about 1 ms compared to GDI 300 ms for putting a 12MP photo into a maximized window). I prefer WPF for this purpose because it's part of the DotNet framework so it doesn't require the user to install the right version of additional dlls.

BB
Reply With Quote
  #31  
Old 01-24-2015, 06:36 PM
dotnetwrassler dotnetwrassler is offline
Regular
 
Join Date: Sep 2014
Location: USA (Pacific/West Coast)
Posts: 71
Default Just popping in to check on the thread..

I'm still working on some of the coding I mentioned at the end of post #27
I'm having trouble "deconstructing" the perspective warp demo in a way that I can distort the cube so that opposing cube faces can be different sizes (and the "joining" faces have angled edge lines).

Meanwhile, it looks like passel and boops boops have been at it while I've been gone.

Re: passel posting
Quote:
Originally Posted by passel
Being able to drag on the cube to move it is a natural thing to try to do.
I'm glad you agree (and thanks for the code update).

I have incorporated this new passel drag code (with braking) into the attachment below (using the white text and backed off camera setting from PW5 attachment to post #27).

I also added this line to the end of the form_load event to auto-press the button to start the timer,
(which acts as a almost a game loop for keeping the 3D graphics refreshed as 3D rotation via dragging is accomplished):
Code:
Button1_Click(Button1, New EventArgs())

Re: boops boops posting
Quote:
Originally Posted by boops boops
I am looking into the possibility of making something similar based on WPF, which does at least put a bitmap on the screen at something like DirectX speed (e.g. about 1 ms compared to GDI 300 ms for putting a 12MP photo into a maximized window). I prefer WPF for this purpose because it's part of the DotNet framework so it doesn't require the user to install the right version of additional dlls.

I'm still not really sold on WPF (the old "Avalon").

For one thing most of the old samples are in C# (instead of VB.Net).

For another thing:
WPF 3D doesn't know how to draw lines.
Here is Eric Sink's long explaination of this as well as his proposed solution --ScreenSpaceLines3D.

Unfortunately ScreenSpaceLines3D has some issues.

Per this Microsoft social forum thread:

Quote:
ScreenSpaceLines3D was included in the early WPF builds but was removed before release.
(Here is a link regarding that.)

This CodePlex page contains the source for version 1.01 of 3D tools:
http://3dtools.codeplex.com/releases/view/2058

Quote:
The problem with ScreenSpaceLines3D that leads to memory leaks.
Per this page:
Quote:
Originally Posted by Charles Petzold
This job requires that ScreenSpaceLines3D know about all the transforms that are applied to the visual because it must invert the transform chain to determine the dimensions and orientation of the line that it renders. What makes this job particularly tricky is that these transforms can be animated. For that reason, ScreenSpaceLines3D installs a handler for the CompositionTarget.Rendering event, and walks the parent/child chain up to Viewport3D on each vertical retrace of the video display. As Eric notes, this is a problem.

For me, the most serious problem with ScreenSpaceLines3D was the line joins.
[so] I've also provided a property in WireBase named Rounding of type int that lets you specify the number of little pie slices used to approximate the rounding of the ends of each line
Wirebase is part of a larger code library call "Petzold.Media3D" (which is used in most of his book samples as a dll).

Of course Charles Petzold's book comes with only C# (intermixed with xaml) code:
http://www.microsoft.com/mspress/com...9780735623941/

There was an effort to translate the book samples to VB.Net and for a while there existed a downloadable file called "Petzold_WPF_VB_All.zip"

There are dead links all over the place for this file, including these pages:
http://blogs.msdn.com/b/vbteam/archi...b-samples.aspx
https://vakul.wordpress.com/2008/04/...samples-in-vb/

..and even this old Internet archive page won't get you the file.


It is the earlier "3DTools.dll" that is included in a great many WPF 3D samples online (which are mostly C# based).

One nice set of samples comes from one of the few other books that shows how to use VB.Net with WPF:
http://www.apress.com/9781430272403

(Note: check the "Source Code/Downloads" tab on this apress book page for a link to the zip file).

All of these links are for boops boops.
I would be interested to see any VB.Net code you come up with for working with 3D mesh geometries using WPF.

The attached teapot demo is based on Martin Newell's famous Utah Teapot code (converted to xaml, of course).
The zip has both VB.Net and C# versions inside.

The teapot demo also has issues if you try to extend it in different ways.
See here for an explaination of the potential pitfalls.

However it could be deformed if you could extend the Point3DCollection Class
(used by the MeshGeometry3D.Positions Property)
to create what is missing from WPF, a PointCollectionAnimation class.

This article goes into this a little as well as presenting a way to do a deformation of the mesh making up the teapot.

I should mention I often come across this section of the MSDN a lot when searching for how to do 3D stuff in .Net.

It includes a sub-page on WPF performance optimization.

WPF Pixel Shader effects would be nice to have in GDI+,
(but then again so would having access to vertex shaders).

Working with the Unreal Development Toolkit (UDK) you can turn off all the lightning, textures, and shading
to reveal the complex wire-framed geometries underneath.
I'll attach a screenshot.
Can you imagine composing a scene like that with .Net (even in wireframe)?
Attached Images
File Type: jpg screenshot_Perspective_warp_5c.JPG (89.7 KB, 4 views)
File Type: jpg screenshot_WPF_rotating_teapot.JPG (33.3 KB, 4 views)
File Type: jpg UDK_scene_wireframe.JPG (389.3 KB, 6 views)
Attached Files
File Type: zip PerspectiveWarp5c.zip (75.7 KB, 20 views)
File Type: zip Animated_3D_WPF_TeaportRotation.zip (173.8 KB, 19 views)

Last edited by dotnetwrassler; 01-24-2015 at 07:42 PM.
Reply With Quote
  #32  
Old 02-07-2015, 08:19 PM
dotnetwrassler dotnetwrassler is offline
Regular
 
Join Date: Sep 2014
Location: USA (Pacific/West Coast)
Posts: 71
Default Quaternions revisited..

After post #26 the readers of this thread are probably tired of hearing about quaternions - well, too bad!

With my failure to be able to adjust the boops boops Perspective Warp code to support independent cubes with offset centers,
I have to turn back to code posted in the attachment in post #4 of this thread.

Here's a line of code from the "Quaternions.vb" file of that attachment:
Code:
Public Structure Quaternion
Seems like a pretty hum-drum, boring line of code?

However if you search the MSDN for this public structure you end up on this Quaternion page:
https://msdn.microsoft.com/en-us/lib...vs.111%29.aspx

..part of the System.Numerics.Vectors library that also has a complex structure:
https://msdn.microsoft.com/en-us/lib...vs.111%29.aspx

..which "initializes a new instance of the Complex structure using the specified real and imaginary values."

Don't remember downloading any VB.Net code samples from the Internet that have/use these structures?

That's no surprise to me.

There is virtually no quaternion using VB.Net GDI+ code anywhere on the Internet.

If you've seen any such VB.Net code (outside of some DirectX/XNA related code),
please feel free to post with a link,
because I have spent much time searching for VB.Net GDI+ quaternion 3D rotation code and there is just very very little out there.

So I asked myself - can this thread's "QuaternionDrawing17b.zip" code be modified to form an array of cubes (i.e. more than one)?

The answer is Yes!
(see attachment and screenshot below).

..and the best part is that each cube can have its own center of rotation.

This means the cubes don't "orbit" an imaginary center point that lies between them,
but instead rotate as if the multiple (different) centers of rotation lie inside of each of the cubes.

This is what I can not get the code for the Perspective Warp cubes to do..

Of course in this revised code each cube has a different texture mapped rendering
(although it's just as easy to have them share a common bmp array).

The trouble is - how to line them up into a Rubik's cube type array, with a set of 27 cubes arranged in a cube shaped formation?

Probably just involves x, y, and z offsets (but the code to do the iterative gapping of these offsets is not obvious to me).

Since we now have multiple 3D texture mapped primitives the possibility arises
they could bump into each other (and undergo collision).

If so, how would one programmatically determine this collision has occurred, in order to build in a 3D collision detection "event",
that could either cause an effect or restrict having one cube rendered inside another (even partly)?

With passel and boops boops concerning themselves recently with just a 2D graphics related forum thread,
I guess it's back to exploring things on my own...
Attached Images
File Type: jpg screenshot_texturemapped_cube_array_with_multi-center pivot_rotation.JPG (44.5 KB, 6 views)
Attached Files
File Type: zip QuaternionDrawing29.zip (345.1 KB, 30 views)

Last edited by dotnetwrassler; 02-07-2015 at 08:24 PM.
Reply With Quote
  #33  
Old 02-08-2015, 03:56 PM
dotnetwrassler dotnetwrassler is offline
Regular
 
Join Date: Sep 2014
Location: USA (Pacific/West Coast)
Posts: 71
Default Re: Having a WWPD moment..

First off --sorry for this long post without any code updates to post.

You're probably wondering what "WWPD" stands for?

Well, I'm sure you've all seen those WWJD bumper stickers.
(where WWJD stands for "What Would Jesus Do")


Unfortunately Jesus didn't write computer source code,
so in situations where some code is needed,
(and I don't have any programmers/coders to talk to or consult with one on one offline),
I've created (in my head) a virtual avatar version of passel.

Thus "WWPD" stands for:
"What would passel do?" (to solve a particular coding challenge)

Unlike the real passel, my personal avatar version of him is available 24/7 to mentor me.

The downside - the avatar can't solve coding issues like the real passel can.

It's basically only my own mind trying to debug itself
and develop workarounds that hopefully lead to a solution.

So the issue today (that my mind won't let go of,
on a slow boring Sunday) is:
Quote:
Alright, I've got the quaternions rotation code working with multiple 3D objects,
but how can a similar (but more general) solution be created for the
Perspective Warp code?

My passel avatar is standing with his arms crossed across his chest,
looking at me with the piercing eyes of a master software engineer, saying:
"You already know the answer"

"I do?" I respond warily..

My passel avatar lets out a breath of...annoyance? exasperation?

"I'll give you a hint --you are working with a class that doesn't have the functionality you need.
So how do you modify it?"

"Uhm..you mean change the way it operates...I guess maybe modify/overwrite the existing class constructor.."

The passel avatar raises one eyebrow in a very Spock-like manner.
Which is the avatar's non-verbal way of saying:
"interesting..but somewhat wrong (not altogether right)".

"No wait..I meant to say 'create a new class constructor..' "

The passel avatar moves his hands to his hips and leans in to say:
"Enough with the blather..show me the code!"

Of course my personal avatar version of passel is much more stern
and demanding than the real life passel
(but I need this because I'm basically a very lazy coder).

But the avatar is loosely based on every thread passel has ever posted.

Here are the two posts where he uses the word "blather"/"blathering":
http://www.xtremevbtalk.com/1014288-post12.html
http://www.xtremevbtalk.com/1186854-post4.html

Of course, everyone also knows passel's work:
"..mostly involved simulators so the programming is mostly integration,
connecting different computers or hardware or applications together
to provide a simulation training environment for things like trains, planes,
submarines, and automobiles (planes include mostly helicopters as of late)."
http://www.xtremevbtalk.com/1385539-post16.html


..and at work he has:
"3000 source files for the Radar Data Processing Set simulation. And more
than 3000 more for the Pipelined Digital Radar Landmass Simulation. Then
there's the rest of the simulator, the Avionics, the Aerodynamics,
Electrical system, etc..."
http://www.xtremevbtalk.com/493336-post10.html

..including:
"I don't know how many computers,
but around a 100 processors of all types, from old Concurrent machines,
Dec Alphas, embedded 68030, and TI DSP, and old Transputer matrixes,
all working together, passing more messages, with an oddball mixture of
big endian to little endian and back conversions.."

I sort of imagine he has a huge office with a 15 foot wide "L"-shaped CAD-engineer-type workstation,
with multiple computers, all super-overclocked, and using multiple top-of-the-line nVidia graphics cards,
feeding 6 huge monitors running IDEs in all kinds of programming languages..

That's based on these posts mentioning different languages passel has used over the years:

post mentioning ADA/Fortran:
http://www.xtremevbtalk.com/466755-post5.html

post mentioning ADA/C++
http://www.xtremevbtalk.com/1188923-post2.html

post mentioning CMS-2 (Navy) and Jovial (AirForce)
http://www.xtremevbtalk.com/476571-post16.html

post mentioning C++ and asm:
http://www.xtremevbtalk.com/973920-post5.html

---------------

Here's what I can't even say to avatar version of passel
(much less the real one):
"But I'm really not comfortable working with classes"

Because everyone on the .net side of the forum knows that .Net is all about classes,
(and no .Net programmer would ever admit to not being thoroughly "embrace-ful" of classes
and writing class code, because "it should be as natural as breathing").


Of course, it was different with VB6 (VB Classic) because dealing with classes (like using a .cls module in every project) wasn't really required.

In fact, there was only one good book that really extensively explored the
use of classes under the "classic" version of VB (as noi_max recommended here).

----------

..and I guess this is the point at which I whine a little about the VS.Net IDE.

I know "it's a poor programmer that blames his tools",
but VS.Net is so slick in some ways
(like how you can drag the tabs around)
and so totally dumb (unhelpful) in others.

For instance,if you were to add a second button to the form,
(automatically named Button2) and double-click it,
the Windows forms designer would create a second event procedure:
Code:
Private Sub Button2_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
    Handles Button2.Click
End Sub
However if you have a project that only has one button (Button1),
and paste that same code into the form,
it would be nice if there was at least an option
to have it pop up a dialog and say:
"Would you like to add Button2 to the form?"

(Sort of like when VB6 would ask about creating a control array)

..and if you said yes, the button would not only be created but
auto-positioned directly below Button1, sized similarly,
with a nice looking gap between the two buttons
(instead of what I imagine the default would
be - to place it in the middle of the form).

There's also the way the VS.Net IDE let's you add a class to a project,
by right clicking on project,
add > new item > and then
select class from the new item dialog

However what if you wanted to create a class that was based on an existing class (already within the project)?
Would you create a blank class then copy/paste the previous class code?

I do that sometimes when creating "branches" from "trunk" code,
(where I'm experimenting with different types of class code).

Of course the old "copy/paste the whole project/solution folder"
works as well.

That's my workaround for not having a multi-undo History slider like Adobe Photoshop:
http://blogs.adobe.com/nandinigupta/...istory_pse.JPG


Wouldn't it be nice, though, if you could click on the tab
showing the existing class (or the file in the solution explorer)
and have a option on the right click menu like:
"Clone new class",
where the dialog would pop-up to give you an option for a new class and/or file name,
then automatically copy over the existing class code into the new class.

I know it sounds like I'm being nitpick-y.

The VS.Net IDE is way better than working with any version of the Eclipse IDE.

However in terms of creating classes I would also like
some kind of wizard that would save just a little bit of typing.

Such a wizard might have combo drop downs for creating different types of standard
class constructors (like "New") and maybe be linked in with the snippet database,
containing class code the programmer has used in other projects,
which VS.Net doesn't really have (and yes, I know there are extensions for this,
but what if you are using an express version that doesn't support extensions).

It just seems like the VS.Net IDE should have someway
to "learn" how a programmer does things over time,
and provide increasing helpful ways
of shortening the coding workflow (and typing needed).


.....

Ultimately, though, my personal passel avatar always fails me.
Because I usually end up saying something like:
"Just tell me what is the code I need...PLEASE!"

His response is always:
"I am the zen-master of all VB graphics,
so I can only tell you to think of the problem as a koan and
work through it yourself.
That is the path to true enlightenment"

..and them he takes a step back toward his super engineering workstation desk and fades from sight.


That's why I'm glad the real passel
always keeps hanging around the forum
even though he probably gets enough coding from his day job.

(..and sorry again, to both passel and everyone else if this post is just complete "blather"..)

Last edited by dotnetwrassler; 02-08-2015 at 04:36 PM.
Reply With Quote
  #34  
Old 02-09-2015, 07:13 PM
boops boops's Avatar
boops boops boops boops is offline
Centurion
 
Join Date: Dec 2006
Location: Holland and France
Posts: 146
Default

For what it's worth, here's a little demo of a multi-object scene based on the beginnings I made with the PerspectiveWarp program. It's easy enough to place objects where you like in the scene: just set the centre position e.g. in the New sub of each solid shape. A defect in the PerspectiveWarp program was that I hadn't implemented the center argument in the Point3D.Rotate subs. Now it is fixed and the vertices can rotate around a specified Point3D and not just around the scene origin.

The demo has a tetrahedron, a cube and a dodecahedron alongside one another. There are two anims: one rotates the formation of solids around the scene centre, and the other rotates each polyhedron individually around its centre.

All the rotations are specified in terms of fixed (global) coordinates -- not for example around axes aligned to the orientation of a cube. For that, a different approach to rotating the solids would be needed.

I'm afraid there is not much chance I will follow up all the bits and pieces you have linked to in previous posts. I don't have the time and energy for that: after all, I'm still exhausted from contributing to that hexagonal picturebox thread about 5 years ago

BB
Attached Images
File Type: jpg polyhedra_anim.jpg (64.1 KB, 4 views)
Attached Files
File Type: zip PerspectiveScene.zip (41.2 KB, 23 views)
Reply With Quote
  #35  
Old 02-13-2015, 08:23 AM
dotnetwrassler dotnetwrassler is offline
Regular
 
Join Date: Sep 2014
Location: USA (Pacific/West Coast)
Posts: 71
Default Towards a complete set of platonic solids...and maybe a scene graph..

It's actual worth quite a lot!

Of course platonic solids have been explored with VB6:
http://www.vb-helper.com/tutorial_platonic_solids.html

But for VB.Net, there is not (AFAIK) a complete code set for drawing all the platonic solids:
http://en.wikipedia.org/wiki/Platonic_solid
Quote:
In Euclidean geometry, a Platonic solid is a regular, convex polyhedron with
congruent faces of regular polygons and the same number of faces meeting at each vertex.
Five solids meet those criteria, and each is named after its number of faces.
-tetrahedron
-cube
-octahedron
-dodecahedron
-icosahedron

I noticed in your dodecahedron class this comment:
Quote:
'The following Cartesian coordinates define the vertices of a
'dodecahedron centered at the origin and suitably scaled and oriented:
' (±1, ±1, ±1)
' (0, ±1/φ, ±φ)
' (±1/φ, ±φ, 0)
' (±φ, 0, ±1/φ)
'where φ = (1 + √5) / 2 is the golden ratio (also written τ) ≈ 1.618.
'The edge length is 2/φ = √5 – 1. The containing sphere has a radius of √3.
That lead me to this Icosahedron coordinates page, which said:
Quote:
Wikipedia says that Cartesian coordinates of icosahedron are:

(0, ±1, ± φ)
(±1, ± φ, 0)
(± φ, 0, ±1)

Where φ = (1 + √5) / 2 is golden ratio ≈ 1.618.
With that..could the Perspective Scene code add an icosahedron class, I wonder?
You've got a the needed phi declaration:
Code:
Dim phi As Double = f / 2 * (1 + Math.Sqrt(5))

Oh..and here's a another (nicer) picture I found of the 5 platonic solids:
http://faculty.wcas.northwestern.edu...onicsolids.gif


Re: what I was working on when I saw boops boops latest post:

Since I couldn't get 3d cubes/tetrahedra to have different centers,
I was going to try for the octahedron inside a cube,
or rotated cubes with a common center (concentric).

Now you've leaped past all that, so it opens up a whole new range of possibilities.



There is still the issue of perspective projection, though.
This generally means that some of the faces of the cube has to be larger than others,
giving joining lines between faces a certain "slanti-ness" (non-right-angled slope).

Here's some links:
Drawing cubes with perspective mapping to different vanishing points
Cubes under perspective projection at wide field of view


The other leap forward is now, being able to generate a "scene",
we are on the edges of (or invoking the potential for) doing a Scene Graph:

Quote:
A scene graph is a collection of nodes in a graph or tree structure.
A tree node (in the overall tree structure of the scene graph) may have many children
but often only a single parent, with the effect of a parent applied to all its child nodes;
an operation performed on a group automatically propagates its effect to all of its members.
In many programs, associating a geometrical transformation matrix at each group level
and concatenating such matrices together is an efficient and natural way to process such operations.
A common feature, for instance, is the ability to group related shapes/objects into a compound object
that can then be moved, transformed, selected, etc. as easily as a single object.


Also just wanted to add...

There has not been much mention up to now of the PolyhedronBase class of the various Perspective Warp code attachments to this thread.

It plays an important roll is "assembling" (grouping?) the Point3D points into 3D shapes,
but doesn't really "expose" these points in a programmatic way,
such that they can manipulated (dragged for instance) after the 3D shape has been rendered.

For instance, I can get the 2D mouse points (e.location.x and e.location.y) for point dragging,
but the question arises:
How to write a detection routine that can know if it's near (or on top of) the 3D shape corner vertices?

I found this StackOverFlow thread with a long-winded answer,
whose equations you might understand (but l really couldn't follow ):
http://stackoverflow.com/questions/9...3d-coordinates

There is also this 2d Mouse Coordinates to 3D MSDN thread.
Most of that thread is about using a ViewPort (which is WPF stuff),
but it mentions:
Quote:
Originally Posted by Jordan Parker
A 2D point maps to a ray in 3D space so there are an infinite number of 3D points.
What you need to do is use the inverse of that 3D -> 2D matrix and pick an arbitrary Z for your 2D point.
That should determine where along that ray you are.
(emphasis on "ray" is mine).

So how to do you code a ray?
There is no "create ray" function anywhere inside the MSDN GDI+ Reference section.

A google search for "convert 2d point in to 3D vector" failed to turn up much interesting, except this page:
Explaining Homogeneous Coordinates & Projective Geometry

It has a few good diagrams, but the math totally lost me.


Your mention of a "different approach" was intriguing:
Quote:
Originally Posted by boops boops
All the rotations are specified in terms of fixed (global) coordinates -- not for example around axes aligned to the orientation of a cube.
For that, a different approach to rotating the solids would be needed.
However, I imagine coding such a different approach would not be a trivial matter.


Lastly..
I also immediately thought (after running the PerspectiveScene code):
It would be nice if you could adjust the spacing between the Perspective Scene shapes using some trackbar controls,
(with their background color set to AntiqueWhite) added inside the toolstrip.

Anyway, thanks for the posting boops boops.
You've been more than generous with your time and efforts in this thread.
Much appreciated!

Last edited by dotnetwrassler; 02-13-2015 at 09:41 AM.
Reply With Quote
  #36  
Old 02-13-2015, 06:45 PM
boops boops's Avatar
boops boops boops boops is offline
Centurion
 
Join Date: Dec 2006
Location: Holland and France
Posts: 146
Default

The dodecahedron was surprisingly hard to work out. Coding the Wiki formulas wasn't the problem but sorting the 20 vertices into 12 sets of 5 (each in the right order) to define the faces. An icosahedron would be a nice addition and might be a little (but not much) easier because triangles are easier to sort than pentagons.

Anyway, if I were going to develop the PerspectiveScene code further (and I'm not promising) I would give priority to transplanting the 3D rotation methods from your QuaternionDrawing17b code and to implementing rotation around local instead of global axes. A simple Sphere solid would be worth thinking about: should it be represented as triangles or pixels? Making the polyhedron vertices draggable shouldn't be too difficult.

Topics like scene graphs and rays go along with ray tracing. The Wikipedia article on Ray Tracing looks fairly accessible. The ray itself is just a 3D line (could be a Structure of two 3D points) but I don't think it will be much use without some vector geometry. At some point you will have to resort to GPU-accelerated APIs (Direct3D/WPF, OpenGL, XNA). Getting at least a reading knowledge of Csharp would help you a lot because that is where most graphics coding takes place.

BB
Reply With Quote
  #37  
Old 02-14-2015, 11:02 AM
dotnetwrassler dotnetwrassler is offline
Regular
 
Join Date: Sep 2014
Location: USA (Pacific/West Coast)
Posts: 71
Default Towards further development of perspective warp and other 3D rotation code.

Quote:
Originally Posted by boops boops
An icosahedron would be a nice addition and might be a little (but not much) easier...
Maybe for you it's "easier" (you are, after all, one of the top experts in VB.Net graphics, both on this xvbt forum and the vbforum.com forum).

Personally I could never have figured out how to do a dodecahedron..and I already had that Wikipedia page bookmarked.

I would take me...well..quite some time..to convert the Cartesian coordinates into VB.Net icosahedron code
(even using you dodecahedron code as a template --and I'm not in any way surprised that it was "surprisingly hard to work out").

I had only barely started on trying to figure out the code needed to produce an octahedron
(which I thought would be the next "easier" platonic solid to produce
because it's basically just two tetrahedrons joined together).

Quote:
Originally Posted by boops boops
At some point you will have to resort to GPU-accelerated APIs.
I'm satisfied with what we have been able to achieve so far
and want to put off that "point" into the future.
Let's see how far we can take things without going "there"...I think
there still a wide swath of ground to cover before that point.

Quote:
Getting at least a reading knowledge of Csharp would help...
If I didn't have that, the QuaternionDrawing17b code would be C# code, not VB.Net code.

The code attached in post #4 of this thread took months of translation
(not days...not weeks..literally months).

So, yes, I agree that "transplanting the 3D rotation methods" of the quaternion rotation VB.net code
(the only VB.Net code of it's kind in existence AFAIK) is a "priority" (i.e. has importance).

I'm just glad to hear (at this point) that you are in general agreement that the QuaternionDrawing17b code
(and the original VB.Net translation attached to post #4 of this thread)
offers a technological superior approach to doing 3D rotation --and I'm not saying that in a boastful way,
since it's really just a translation of someone else's code:
http://www.codeproject.com/Articles/...y-with-C-and-G

Here's the only thing I really understand on that page:
Quote:
In mathematics, quaternions are a non-commutative number system that extend the complex numbers.
They provide a convenient mathematical notation for representing orientations and rotations of objects in three dimensions.
Quaternions have 4 dimensions (each quaternion consists of 4 scalar numbers),
one real dimension w and 3 imaginary dimensions xi + yj + zk that can describe an axis of rotation and an angle.
Quaternions are often used in 3D engines to rotate points in space quickly.
I totally agree with what you said back in post #17:
Quote:
People sometimes use matrices for 3D rendering but it's more in theory than practice.
Besides, quaternions are better for practical purposes.
Their main purpose is for efficiently combining simultaneous rotations around 2 or 3 axes into a single rotation around a different axis.
The quaternion saves quite a bit of computation when rendering 3D points or a texture, and it's immune to gimbal lock.
The attachments regarding quaternions in post #26
(especially the "math_etched_in_a_bridge" attachment)
were mainly for me --my attempt to find an "entry point" so I could peek/peer inside that black box:
Quote:
Originally Posted by boops boops
You don't need to look at the Quaternion class itself or to understand the theory behind it: just treat it like a black box.
In order to transplant it (or do what I call a code "mashup"),
I really do have to a generally "vague" idea of how it works internally..which
includes finding some kind of "handle" on the math (and the use of imaginary numbers).

We (or maybe just "I") need a set of "Rosetta stone" code - the "same" code showing matrix rotation, Euler rotation, and quaternion rotation.
And when I say the "same" I'm talking in a semantic ontological sense - not literal code line by code line sense.



What I can do (since we have a working set of code) is do a step through code trace
and watch how those funny numbers (with a whole lot of digits past the decimal point) change.

The thing is..for both your code and the quaternion code..there's a whole lot of looping --for all the faces,
composed of all those (many) corner vertices (3D points).

Terminology note:
Quote:
I hate the terms "vertex " and "vertices".
I prefer instead just saying "3D point" (even if it's somewhat of a simplification,
and therefore technically less accurate).
From a "let's have this thread appeal to as large a pool of coder/programmers as possible" viewpoint,
I think more of them can "relate" to simply:
"if you are drawing a line it has to go from point A to point B".
Thus a point is a point is a point.
Or...in other words..whether it's a 2D point or 3D point, it's still just a humble "point".
And when you get right down to it --to be drawn on a 2D screen the 3D point has to be "down converted" from x,y,z to just x,y anyway.
With that said, though, I know the positioning of the points and the effective rendering of
everything (points, lines, and texture-mapped pixels) still requires a acknowledgement
that it's a lot of math (and mathematical concepts) embedded inside/behind the code that makes everything work as it should.

Quote:
Making the polyhedron vertices draggable shouldn't be too difficult.
But I'm glad you said this!
But again..a qualifier --not too difficult for you..for me it's definitely not a trivial piece of coding.

Quote:
A simple Sphere solid would be worth thinking about: should it be represented as triangles or pixels?
In the 3D coding world: pixels = texturemapping
I didn't want to bring this up (since we would be getting ahead of ourselves)
but there are somethings called "triangle fans"

The simplistic programmer (3D graphics newbie) might ask:
"Why triangle fans...why not "fans" (or strips) made of rects (rectangles/squares)?"

Because such strips of rects "decompose" into triangle strips rather easily mathematically.
Plus they are easier to "shape" (not sure if that is the right word..maybe "organize") into
3D shapes that are simulating (or approximating) curved surfaces.

Also --curved surfaces "decompose" better into triangle fans than rect strips.
See Mike Hodnick's explanation below.
Reading through many many gamedev.net forum posts,
this comes up again and again for polygons which generally/usually decomposed into triangles.

Here's a link to Delaunay triangulation if anyone wants a starting point for researching.

If anyone goes on to do a search for "3D triangular sub-division",
you'll probably eventually come across a nice graphic of how
one of the 5 platonic solids can be carved out (using triangles) into a sphere.

You'll probably also eventually run into other sub-division methods like:
Catmull-Clark, Loop, Doo-Sabin and 3√ subdivisions
(as mentioned on this "CGAL 4.5.2 - 3D Surface Subdivision Methods" page).

That pages also mentions NURBS (non-uniform rational B-splines), but other than mentioning them in passing
I won't discuss them much in this thread.

It's another thing that Microsoft left out of GDIplus.

You'll see it mostly/mainly mentioned in MSDN with regard to Visio, OpenGL and DirectX/XNA.
As to NURBS in the WPF/XAML "Geometry" section of MSDN, I bookmarked a page on cubic bezier curves,
but most of the complex geometries WPF code I've seen (that's moved past polygons) goes straight into meshes.
Meshes are another topic we might not get into much in this thread (including a discussion of normals).

If you dig around the Internet Archive (Wayback machine) there was a guy named "Mike Hodnick"
who used to have a pretty good introduction to "WPF 3D land" tutorial that (sadly) doesn't exist anymore:
http://www.kindohm.com/technical/WPF3DTutorial.htm
Quote:
Originally Posted by Mike Hodnick
What is a mesh?
A mesh is basically a representation of a surface.
The mesh represents the surface through a system of points and lines.

At a minimum, a surface is a flat plane.
A flat plane needs three points to define it.
Thus, the simplest surface that can be described in a mesh is a single triangle.
It turns out that meshes can only be described with triangles.
That is because a triangle is the simplest, most granular way to define a surface.
A large, complex surface obviously can't be accurately described by one triangle.
Instead, it can be approximated by many smaller triangles.
You could argue that you could use a rectangle to define a surface, but it's not as granular as a triangle.
When you think about it, a rectangle can be broken into two triangles.
Two triangles can much more accurately describe a surface than a single rectangle.
A whole mesh is composed of:
-Mesh Positions
-Triangle indeces
-Triangle normals
..and I'm running up against the post character limit so I'll stop there..

Last edited by dotnetwrassler; 02-14-2015 at 12:52 PM.
Reply With Quote
  #38  
Old 02-22-2015, 12:53 AM
dotnetwrassler dotnetwrassler is offline
Regular
 
Join Date: Sep 2014
Location: USA (Pacific/West Coast)
Posts: 71
Default Cube center movement during item rotation & working towards draggable 3D corners

Okay, I had a chance to fiddle around with the code attached to post #34 of this thread.

This is the first demo code that moves the center of different polyhedra solids to a different point in 3D space.

The awkwardness of the demo is that the cube always stays centered
in the middle of the picturebox whether the scene is rotating,
or whether the solids (the cube, tetrahedron, dodecahedron) are rotating about each of their centers.

I wanted the center of the cube to move while that cube is rotating around its center,
but not while the scene was rotating all the solids around each other.

But how?

The secret (I found out after a lot of trial and error) is changing:
Code:
Public Overridable Property Center As Point3D
to:
Code:
Public Shared Property Center As Point3D
With that change you can use this line:
Code:
PolyhedronBase.Center = New Point3D(-20, 0, 0)
..to get a movement when you press the "Rotate Item" toolstrip button that resembles a train track movement.
(see working attachment of this below)


There is also these noteworthy pieces/snippets of code:
Code:
For Each idr As IDrawable In Scene1.Drawables
   If TypeOf idr Is Point3D Then
        'Declare a 3D corner
        Dim p3d As Point3D = DirectCast(idr, Point3D)
        'Draw circle around the 3D corner point
        MarkVertex(g, p3d)
...

  Private Sub MarkVertex(g As Graphics, vertex As Point3D)    
    'Convert the corners point in 3D space to a point in 2D space
    Dim vtx As PointF = vertex.To2D
    'Form a rect, centered around the 3D corner (vertex)
    Dim r As New RectangleF(vtx.X - 4.0F, vtx.Y - 4.0F, 8.0F, 8.0F)
    'Draw over the 3D corner to highlight it
    g.FillEllipse(Brushes.Gold, r)
    g.DrawEllipse(Pens.Black, r)
  End Sub
The code comments (which I added) tell what's going on.

So I'm thinking --the "r" rectangle might be used for a PtInRect test against the x,y, location of a mouse,
theoretically allowing the changing of the fill ellipse color to another color,
signalling if the mouse is over/near one of these 3D corners.

This would be the first step in developing an If..Then test to set blnDrag,
(in a MouseDown event) to true.

However to do a 2D mouse drag of a Point3D,
the X, Y e.location mouse movement differential
would have to be translated
to a appropriate change of the x, y, and z values defined for the corresponding Point3D.

To do this I'm thinking maybe some kind of 2Dto3D
function..possibly inside the Point3D class?

Unless..somehow...one could loop through the list (array) found in the Vertices2D structure
and somehow (maybe using the Point3D_EqualityComparer class)
pick out which one the mouse was over..?

That's all I got for this week, sorry.
Attached Files
File Type: zip PW_Scene2-TrainTrack_Movement.zip (97.1 KB, 15 views)

Last edited by dotnetwrassler; 02-22-2015 at 01:12 AM.
Reply With Quote
  #39  
Old 02-22-2015, 06:22 PM
dotnetwrassler dotnetwrassler is offline
Regular
 
Join Date: Sep 2014
Location: USA (Pacific/West Coast)
Posts: 71
Default 2nd post this weekend - Rubiks Cube array..

I mentioned back in post #32 about wanting to do such an array.

The PW_Scene attachment to post #34 makes that easy to code (if a little tedious to set up).

Now if I could just figure out how to rotate just a single row of cubes in the array,
we might even have the potential to make a real game of it.
Since selecting a row with a mouse might be difficult,
I'm thinking a set of buttons showing different row rotations
could be the way to go if we get to that point (see attached image).

Oh..and from the attached screenshot below you can see I added
a 3D looking background -- no point in setting for just a 2D gradient background at this point.

Just don't ask me for a Rubik's Dodecahedron!
Attached Images
File Type: jpg screenshot_PW_Scene_RubiksCube_array.JPG (53.1 KB, 8 views)
File Type: gif rubiks_rotate_images.gif (32.2 KB, 5 views)
Attached Files
File Type: zip PW_Scene_RubiksCube_array.zip (196.7 KB, 27 views)

Last edited by dotnetwrassler; 02-22-2015 at 06:56 PM.
Reply With Quote
  #40  
Old 02-24-2015, 10:32 AM
boops boops's Avatar
boops boops boops boops is offline
Centurion
 
Join Date: Dec 2006
Location: Holland and France
Posts: 146
Default

Quote:
Originally Posted by dotnetwrassler View Post
Okay, I had a chance to fiddle around with the code attached to post #34 of this thread.

This is the first demo code that moves the center of different polyhedra solids to a different point in 3D space.

The awkwardness of the demo is that the cube always stays centered
in the middle of the picturebox whether the scene is rotating,
or whether the solids (the cube, tetrahedron, dodecahedron) are rotating about each of their centers.

I wanted the center of the cube to move while that cube is rotating around its center,
but not while the scene was rotating all the solids around each other.

But how?

The secret (I found out after a lot of trial and error) is changing:
Code:
Public Overridable Property Center As Point3D
to:
Code:
Public Shared Property Center As Point3D
With that change you can use this line:
Code:
PolyhedronBase.Center = New Point3D(-20, 0, 0)
..to get a movement when you press the "Rotate Item" toolstrip button that resembles a train track movement.
(see working attachment of this below)
That is a mistake. The purpose of the base class is to provide a template for different types of 3D polyhedron. It's not a place to put magic numbers for a single use. Instead, use the Center argument of the Rotate methods (which is defined in PolyhedronBase and inherited by all the different solids; also in the Point3D class). I even went to the trouble of spelling it the American way. For example, in the Timer.Tick code of the demo from #34, replace all occurrences of Scene.Origin by your chosen Point3D. The "rotate scene" anim will orbit around the chosen point. That's not to say that everything is hunky dory. Now if you try to run both anims at the same time the group of solids will fly apart.The two rotations aren't combining properly, so it's still something I have to work out, maybe with Quaternions. It was just a bit of "luck" that the problem didn't show up when the rotation center was at Scene.Origin.

Quote:
There is also these noteworthy pieces/snippets of code:
Code:
For Each idr As IDrawable In Scene1.Drawables
   If TypeOf idr Is Point3D Then
        'Declare a 3D corner
        Dim p3d As Point3D = DirectCast(idr, Point3D)
        'Draw circle around the 3D corner point
        MarkVertex(g, p3d)
...

  Private Sub MarkVertex(g As Graphics, vertex As Point3D)    
    'Convert the corners point in 3D space to a point in 2D space
    Dim vtx As PointF = vertex.To2D
    'Form a rect, centered around the 3D corner (vertex)
    Dim r As New RectangleF(vtx.X - 4.0F, vtx.Y - 4.0F, 8.0F, 8.0F)
    'Draw over the 3D corner to highlight it
    g.FillEllipse(Brushes.Gold, r)
    g.DrawEllipse(Pens.Black, r)
  End Sub
The code comments (which I added) tell what's going on.
Good comments
Quote:
So I'm thinking --the "r" rectangle might be used for a PtInRect test against the x,y, location of a mouse,
theoretically allowing the changing of the fill ellipse color to another color,
signalling if the mouse is over/near one of these 3D corners.

This would be the first step in developing an If..Then test to set blnDrag,
(in a MouseDown event) to true.

However to do a 2D mouse drag of a Point3D,
the X, Y e.location mouse movement differential
would have to be translated
to a appropriate change of the x, y, and z values defined for the corresponding Point3D.

To do this I'm thinking maybe some kind of 2Dto3D
function..possibly inside the Point3D class?

Unless..somehow...one could loop through the list (array) found in the Vertices2D structure
and somehow (maybe using the Point3D_EqualityComparer class)
pick out which one the mouse was over..?

That's all I got for this week, sorry.
You are thinking on the right lines. A reverse of Point3D.To2D is needed to get correct mouse interaction, so I have included the Point3D.GetFrom2D Function in version 2, attached below.

The new code lets you mouse-drag solids to any position and to deform them any way you like by dragging individual vertices. The cursor changes to show when a vertex or a solid is selectable for dragging.

Other new features besides Point3D.GetFrom2D are:
1. Point3D.DragTranslate, which calls GetFrom2D to drag a Point3D based on 2D coordinates.
2. Point3D.ToString method (useful for debugging)
3. PolyhedronBase.Bounds property, for hit testing and showing a selection rectangle.
4. PolyhedronBase.DragTranslate, for dragging a solid based on 2D coordinates.
These methods are all used on the demo form, in a code region labelled "Mouse Dragging".

I haven't tried your Rubik's Cube code yet, but the pic looks good!

BB
Attached Files
File Type: zip Perspective Scene 2.zip (26.4 KB, 16 views)

Last edited by boops boops; 02-24-2015 at 10:39 AM.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
 
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
Exploring 3D graphics with VB.Net, but without using DirectX or XNA
 
-->