yes, I temporarily gave up on creating dotnet UI because I’m not that familiar with it and because it doesn’t have a method for reading cordinates off a spline via a parameter…but I suppose this doesn’t matter…Looking at yr spline code , I was wondering if paste bitmap might be faster than setPixel…also…didn’t quitre see how your bezier handles were able to work…is it hidden in some math somewhere I didn’t see for looking? Anyway, I’m very happy to use dot net drawing methods etc…bring it on paul!
Total HACK! But it worked here.
try(form.close())catch()
clearListener()
form=dotNetObject "form"
graph=dotNetObject "label"
graph.backColor=(dotNetClass "system.drawing.color").fromArgb 100 100 100
graph.bounds=dotNetObject "system.drawing.rectangle" 10 10 300 300
dotNet.addEventHandler graph "paint" paintGraph
fn bezier2D p1 p1t p2t p2 t=
(
Q1 = (p1t - p1) * t + p1
Q2 = (p2t - p1t) * t +p1t
Q3 = (p2 - p2t) * t +p2t
Q4 = (Q2 - Q1) * t + Q1
Q5 = (Q3 - Q2) * t + Q2
Q5 = (Q5 - Q4) * t + Q4
)
-- .DrawLine <System.Drawing.Pen>pen <System.Drawing.Point>pt1 <System.Drawing.Point>pt2
redCol=(dotNetClass "system.drawing.color").orange
blueCol=(dotNetClass "system.drawing.color").blue
col=(dotNetClass "system.drawing.color").blue
redPen=dotNetObject "system.drawing.pen" redCol 2
bluePen=dotNetObject "system.drawing.pen" blueCol 2
fn paintGraph sender arg =
(
g=arg.graphics
-- showMethods g
local p1=sender.controls.item[0].location
local p1t=sender.controls.item[1].location
local p2t=sender.controls.item[2].location
local p2=sender.controls.item[3].location
g.drawLine redPen p1 p1t
g.drawLine redPen p1t p2t
g.drawLine redPen p2t p2
for t = 0 to 1 by .01 do
(
dp=bezier2D [p1.x+5,p1.y+5] [p1t.x+2,p1t.y+2] [p2t.x+2,p2t.y+2] [p2.x+5,p2.y+5] t
drawPoint=dotNetObject "system.drawing.point" dp.x dp.y
if sender.tag!=undefined do
(
g.drawLine bluePen sender.tag drawPoint
)
sender.tag=drawPoint
)
sender.tag=undefined
)
fn mouseMove sender arg=
(
if arg.button==arg.button.left do
(
sender.location=(sender.parent.PointToClient sender.MousePosition)
graph.invalidate()
)
)
lb1=dotNetObject "label"
lb1.size=dotNetObject "system.drawing.size" 11 11
lb1.backColor=(dotNetClass "system.drawing.color").green
lb1.location=dotNetObject "system.drawing.point" 20 280
dotNet.addEventHandler lb1 "mouseMove" mouseMove
lb1t=dotNetObject "label"
lb1t.size=dotNetObject "system.drawing.size" 5 5
lb1t.backColor=(dotNetClass "system.drawing.color").green
lb1t.location=dotNetObject "system.drawing.point" 100 280
dotNet.addEventHandler lb1t "mouseMove" mouseMove
lb2=dotNetObject "label"
lb2.size=dotNetObject "system.drawing.size" 11 11
lb2.backColor=(dotNetClass "system.drawing.color").red
lb2.location=dotNetObject "system.drawing.point" 280 20
dotNet.addEventHandler lb2 "mouseMove" mouseMove
lb2t=dotNetObject "label"
lb2t.size=dotNetObject "system.drawing.size" 5 5
lb2t.backColor=(dotNetClass "system.drawing.color").red
lb2t.location=dotNetObject "system.drawing.point" 200 20
dotNet.addEventHandler lb2t "mouseMove" mouseMove
--Note the order they are added. This is just so I know what order to calc them in.
graph.controls.add lb1
graph.controls.add lb1t
graph.controls.add lb2t
graph.controls.add lb2
form.controls.add graph
form.show()
form.size=dotNetObject "system.drawing.size" 340 360
form.text="Bezier Control Test"
dotNet.setLifeTimeControl graph #dotNet
dotNet.setLifeTimeControl lb1 #dotNet
dotNet.setLifeTimeControl lb1t #dotNet
dotNet.setLifeTimeControl lb2 #dotNet
dotNet.setLifeTimeControl lb2t #dotNet
here is from me:
try(form.close()) catch()
form = dotnetobject "MaxCustomControls.Maxform"
form.Text = "Draw Bezier with denisT"
form.StartPosition = form.StartPosition.Manual
form.Location = dotnetobject "System.Drawing.Point" 600 100
form.ClientSize = dotnetobject "System.Drawing.Size" 640 480
panel = dotnetobject "UserControl"
panel.Backcolor = panel.Backcolor.LightYellow
panel.Dock = panel.Dock.Fill
aPen = dotnetobject "System.Drawing.Pen" (dotnetclass "System.Drawing.Color").Pink 1
bPen = dotnetobject "System.Drawing.Pen" (dotnetclass "System.Drawing.Color").LightGreen 1
cPen = dotnetobject "System.Drawing.Pen" (dotnetclass "System.Drawing.Color").Orange 2
p0 = dotnetobject "UserControl"
p0.Backcolor = p0.Backcolor.Red
p0.Bounds = dotnetobject "System.Drawing.Rectangle" 10 10 9 9
p1 = dotnetobject "UserControl"
p1.Backcolor = p1.Backcolor.Red
p1.Bounds = dotnetobject "System.Drawing.Rectangle" 100 12 5 5
p2 = dotnetobject "UserControl"
p2.Backcolor = p2.Backcolor.Green
p2.Bounds = dotnetobject "System.Drawing.Rectangle" 530 462 5 5
p3 = dotnetobject "UserControl"
p3.Backcolor = p3.Backcolor.Green
p3.Bounds = dotnetobject "System.Drawing.Rectangle" 620 460 9 9
fn onMouseDown s e = if e.Button == e.Button.Left do
(
s.tag = e.Location
)
fn onMouseMove s e = if e.Button == e.Button.Left do
(
s.Location.x += e.x - s.Tag.x
s.Location.y += e.y - s.Tag.y
s.parent.Refresh()
)
fn onMouseMove1 s e = if e.Button == e.Button.Left do
(
c = s.parent.controls.item[1]
c.Location.x += e.x - s.Tag.x
c.Location.y += e.y - s.Tag.y
onMouseMove s e
)
fn onMouseMove2 s e = if e.Button == e.Button.Left do
(
c = s.parent.controls.item[2]
c.Location.x += e.x - s.Tag.x
c.Location.y += e.y - s.Tag.y
onMouseMove s e
)
dotnet.addEventHandler p0 "MouseDown" onMouseDown
dotnet.addEventHandler p0 "MouseMove" onMouseMove1
dotnet.addEventHandler p1 "MouseDown" onMouseDown
dotnet.addEventHandler p1 "MouseMove" onMouseMove
dotnet.addEventHandler p2 "MouseDown" onMouseDown
dotnet.addEventHandler p2 "MouseMove" onMouseMove
dotnet.addEventHandler p3 "MouseDown" onMouseDown
dotnet.addEventHandler p3 "MouseMove" onMouseMove2
panel.Controls.AddRange #(p0,p1,p2,p3)
fn onPaint s e =
(
fn cpoint id s:s =
(
c = s.Controls.Item[id]
dotnetobject "System.Drawing.Point" (c.Location.x + c.Size.width/2) (c.Location.y + c.Size.height/2)
)
g = e.Graphics
g.SmoothingMode = g.SmoothingMode.HighQuality
g.DrawBezier cPen (cpoint 0) (cpoint 1) (cpoint 2) (cpoint 3)
g.DrawLine aPen (cpoint 0) (cpoint 1)
g.DrawLine bPen (cpoint 2) (cpoint 3)
)
dotnet.addEventHandler panel "Paint" onPaint
form.Controls.Add panel
form.showmodeless()
Thanks guys. Denis’ code produces the dotnet bezier – beautiful but how can I use this curve elsewhere to create lookupbtable for another controller? I have been told that there is no method for returning cartesian 2 point values of point along a curve given u parameter in dotnet.
Paul – nice useful result … and I can use the bezier function code elsewhere on a spline controller.
Tell me – why do you use that iterative method for the 2d bezier? Why not explicit cubic math functions like : (1-t) ^ 3 * P0 + 3 * (1-t) ^ 2 * t * P1 + 3 * (1-t) * t ^ 2 * P2 + t ^ 3 * P3 where p1 amd p3 are the tangent point values.
I know mathematically what you do is equivalent but is it faster? Doesnt max ‘prefer’ c complied math functions like t^3?
On your site you go to great lengths to explain bezier curves with ‘find the distance between two points and then…so on and so forth’, but actually I find explicit math expressions far easier to comprehend and take in. I find your ‘explanation’ possibly unnecessary and a little confusing. Have your heuristic methods carried over into the math?
Again thanks a lot guys. I’m just a maxscript hacker, you’re the real deal.
you are mashing two things – math and draw…
to get a value along a bezier curve you don’t have anything to draw. all that you need is 4 points and t(path) param. we have already discussed it on this forum.
to make a preview you can use .net and its methods. i’ve shown how to do it.
but…
i have to repeat it again. the max curve control gives you everything. if you can’t understand how it works this is not a point to make your own .net based control.
let’s go back to the problem. what do you want to do?
I find the iterative method easier to understand I guess. Also I have a function that is designed to work with any number of points. I should do a speed test and see how much faster the other is.
I want to set up a curve control on a Osipa style 4 way spline controller that creates non-linear hook up with morph values. I just need a simple 2d graphical represenation of the spline controller in 2d space showing(graphically) how it’s movement will affect the morph values. I want the user to decide what curve he wants and commit to the function by pressing a button which then creates all the info on a ca on the spline itself. I don’t need anything super elaborate as a UI…
Even Matans little bitmap max floaters are good enough I suppose…nothing needs to be drawn superfast…
The curve control is fine and great but not sure how getvalue() is going to help me much…
ANyway – I mean – if I already have the bezier math to do it and can get a draw curve as well, why do I need the Curve control?
Sure I can copy to track view and create a pos controller from it but that’s not what I want to do…the time slider is irrelevant for my purpose.
At this point I have three solutions- dotnet floaters, maxscript foaters , and the curve control…I’m just trying to decide which one is best right now…
the thing about the CC is that i find it a little cluttered and ugly and generic and I want a clearer image of whats going on with values on both axes…thats all…Sorry if I sound obtuse but I’ve never actually used CC before. Thanks for your time…
ok. the thing is becoming clear. it seems like you don’t need cc.
well… use .net bezier draw method as i showed. mathematically a bezier curve defines by 4 points, having these points you can draw the curve.
Oh – just one thing if you’re still there – what’s the dotnet method for placing a bitmap on background? I know that sounds super lazy of me but it would sort of wrap everything up quickly without me wading thru wads of documentation…thnks again guys…