Goodbye to All That (2014)
9 years ago
function pointNormalIntersect2D
oA --Origin A
oB --Origin B
vA --Vector #1.
vB --Vector #2.
&P --position output
=(
nA = normalize(vA);
nB = normalize(vB);
--oA --origin A
--nA --normal A
--sA --scalar A
--oB --origin B
--nB --normal B
--sB --scalar B
--oA+(nA*sA)==oB+(nB*sB);
--oA.x+(nA.x*sA)==oB.x+(nB.x*sB); //MULTIPLY BY nB.y
--oA.y+(nA.y*sA)==oB.y+(nB.y*sB); //MULTIPLY BY nB.x
--
--(nB.y*oA.x)+(nB.y*nA.x*sA)==(nB.y*oB.x)+(nB.y*nB.x*sB);
--(nB.x*oA.y)+(nB.x*nA.y*sA)==(nB.x*oB.y)+(nB.x*nB.y*sB);
--[ c1 ] [ c2 ] [ c3 ] [ c4 ]
--
--MINUS THEM: c4 cancels out.
c1 = (nB.y*oA.x)- (nB.x*oA.y);
--c2 = (nB.y*nA.x*sA)-(nB.x*nA.y*sA);
c3 = (nB.y*oB.x)- (nB.x*oB.y);
--New Equation is:
--c2 = c3 - c1;
c3c1 = c3 - c1; --c3 minus c1;
--Figure out how many sA's you have by combining like terms;
sAcount = (nB.y*nA.x)-(nB.x*nA.y);
--New Equation is:
--sAcount*sA = c3c1;
--calculate sA:
sA = c3c1/sAcount;
--once scalar sA is found, plug it into point normal form to find intersection.
P=[0,0,0];
P.x = oA.x+(nA.x*sA);
P.y = oA.y+(nA.y*sA);
)--[FN:pointNormalIntersect]
oA = $v1A.pos;
oB = $v2A.pos;
vA = $v1A.pos - $v1B.pos;
vB = $v2A.pos - $v2B.pos;
P = [0,0,0];
pointNormalIntersect2D oA oB vA vB &P;
$intPos.pos = P;
UVWrella
UNFoLD3D
RoadKill
UVlayout
myObject = $;
srchID=Skin.ClassID; --Search for skin modifier in MyObject.
For m = 1 to myObject.modifiers.count do(
cmID = myObject.modifiers[m].ClassID;
modFound=False;
if(cmID[1]==srchID[1])then(
if(cmID[2]==srchID[2])then(
modFound=True;
)--[x]
)--[x]
if(modFound)then(
Print("Your Modifier is index#" + m as string);
)else(
print(cmID as string + "!=" + Skin.ClassID as string);
)--[x]
)--[Next m]
Iterate through objects in scene with these object sets:
[1] objects -- all the objects
[2] geometry -- the standard 3ds Max categories...
[3] lights
[4] cameras
[5] helpers
[6] shapes
[7] systems
[8] spacewarps
[9] selection -- the current selection
Use these to iterate through all of one type of object in maxscript:
Example:
For geo in geometry do(
geo.pos = [0,0,0];
)--[x]
Summary of video coverage:
[1]: Globals in MacroScripts are not quite what they seem.
[2]: GlobalVars.Remove is potentially hazardous.
[3]: Checking to see if an object exists by using:
if(theObj==Undefined)then(.....)
IS NOT THE COMPLETE SOLUTION.
V1 = [1,1,1]; ----------Vector #1
V2 = [-1,-1,-1]; -------Vector #2
nV1 = normalize(V1); ----Normalized Vector #1.
nV2 = normalize(V2); ----Normalized Vector #2.
dir = dot nV1 nV2; ------Dot product of normalized vectors.
print("dot ==" + dir as string);
--Negative 1 = Anti-Parallel.
--ZERO = Perpendicular/Orthagonal
--Positive 1 = Parallel.
--Does anyone know if there is a word for "Non-Integer" besides "Float"?
V1 = [1,2,3]; ----------Vector #1
V2 = [-1,-2,-3]; -------Vector #2
dir = cross V1 V2 -------Cross of both.
print("cross==" + dir as string);
--If cross==[0,0,0] then you have
--parallel or anti-parallel vectors
--or one or more vectors has a length of zero
--Only vector with length of zero: [0,0,0];
Say we want to align the Z-axis of an object GEOM
to a line between objects cp1 and cp2.
Step1: Create a normalized vector:
P01 = cp1.pos; --Original Start Point.
P02 = cp2.pos; --Original End Point.
PVEC = P02-P01; --Point from start point to end point.
PLEN = length(PVEC); --Length of vector.
NPV = PVEC / PLEN; --Normalized PVEC
Step2: Lets say that the orientation of cp1 is also going to be used for
twist control. Specifically that, the twist of the objects aligned to the
line will be controlled by the X-Axis of cp1.
--The initial X-Axis may not be perpendicular to the line cp1-cp2.
--Take the cross between the bent X and the Z-Axis (NPV) to get Yaxis.
bentX = (Normalize cp1.transform.row1);
Yaxis = Normalize(cross NPV bentX);
--Use the good Y-axis and Z-Axis (NPV) to get a perpendicular Xaxis.
Xaxis = Normalize(cross NPV Yaxis);
GEOM.Transform = Matrix3 Xaxis Yaxis NPV P01 --Objects new transform.
-- x y z position
Take it Further:
To take this further, you could slide the object up and down the line
by using point-normal form.
Example: Put aligned object in MIDDLE of the line:
midPosition = cp1 + NPV*(PLEN/2)
Example: slide aligned object from start of line to end of line:
for i = 0 to 1 do( --0 to 1 as in Zero to 100%.
istr = i as string;
midPosition = cp1 + NPV*(PLEN*istr)
)--[x]
-- 1 2 3 4 5 6 7 8 9 10
--34567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
--
--********************************************************************
--********************************************************************
--MORE FREE SCRIPTS AT: http://www.youtube.com/user/PolygonRunner ****
--********************************************************************
--********************************************************************
--
--What it does:
--[1]: Registers callback when you open the file and move the time slider.
--[2]: UnRegisters when you open a different max file.
--
--How to use:
--[1]: Put code into a script controller of a dummy object.
--[2]: Make sure last line of script controller is:
-- : [0,0,0], or other valid point3 if position script.
-- : quat 0 0 0 1, or other quaternion if rotation script.
-- : ect...
--[3]: If you want, you can also edit this code to handle
-- "when constructs" and "change handlers".
--
--My personal application:
--[1]: Use to force update script controllers that are not
-- Executing in the correct order.
--
Global MFP_586_214_3958; --MFP = "Max File Path";
Global BFN_586_214_3958; --BFN = "Bound Function";
if (MFP_586_214_3958 != maxFilePath)then(
MFP_586_214_3958 = maxFilePath;
Function BindThisFunction
=(
--Need code to un-register itself when the maxFilePath changes.
if(MFP_586_214_3958 != maxFilePath)then(
--Must remove globals so that will re-register
--If you re-open this file or another file with this
--script in it.
unRegisterRedrawViewsCallback BFN_586_214_3958;
MFP_586_214_3958 = undefined;
globalVars.remove "MFP_586_214_3958";
globalVars.remove "BFN_586_214_3958";
print("Unregistering Callback");
)else(
print("Callback executed on frame" + currentTime as string);
--**********YOUR CALLBACK CODE HERE***********
--**********YOUR CALLBACK CODE HERE***********
--**********YOUR CALLBACK CODE HERE***********
)--[x]
)--[FN:BindThisFunction]
--Bind function to global variable, else the function will
--Not be capable of unRegistering itself.
BFN_586_214_3958 = BindThisFunction;
--Register the function as a callback.
registerRedrawViewsCallback BFN_586_214_3958;
print("CallBack has been registered");
)--[END]
-- 1 2 3 4 5 6 7 8 9 10
--34567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
-- 1 2 3 4 5 6 7 8 9 10
--34567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
--This code will demo how to use my multi-pick-button.
--Works like normal pick button, but allows you to select multiple objects.
--
-- ***************************************************************************
-- ***************************************************************************
-- Want more free scripts?: http://www.youtube.com/user/PolygonRunner ******
-- ***************************************************************************
-- ***************************************************************************
rollout MainRollout "Multi-PickButton Demo"(
local RV_ArrayNodes = #(); --Array of nodes selected by button ArrayPick
button ArrayPick "Select Objects, THEN click me.";
--The list box displays what you currently have selected by the ArrayPick button.
listbox LB01 "Influencing Objs"
height:5; --5 lines tall.
ReadOnly:True; --Read Only List.
--Control for MULTI-OBJECT PICK BUTTON
on ArrayPick Pressed do(
if selection.count == 0 then(
if(LB01.items.count==0)then(
ArrayPick.Caption = "LIST EMPTY";
)else(
ArrayPick.Caption = "List Unchanged";
)--[x]
)else(
MSTAT = #no; --Do not append;
if (LB01.items.count > 0)then(
mstatText = "";
mstatText = mstatText + "[YES]: Append to previous selection." + "\n";
mstatText = mstatText + "[NO]: Replace old selection." + "\n";
mstatText = mstatText + "[CANCEL]: Don't do anything." + "\n";
MSTAT = yesNoCancelBox mstatText \
title:"Append or Replace?" beep:False;
print(MSTAT);
)--[x]
if (MSTAT!=#cancel)then(
nodeNameArray = #();
--If #no: Create New Selection.
if(MSTAT==#no)then(
RV_ArrayNodes = #();
for i = 1 to selection.count do(
nodeNameArray[i] = selection[i].name;
RV_ArrayNodes[i] = selection[i];
)--[X]
ArrayPick.Caption = "List Populated";
LB01.items = nodeNameArray;
print("Rv array nodes===" + RV_ArrayNodes as string);
)--[#no]
--If #yes: Append to Original selection.
if(MSTAT==#yes)then(
nodeNameArray = LB01.items;
for i = 1 to selection.count do(
APN = appendIfUnique RV_ArrayNodes selection[i];
if(APN)then(append nodeNameArray selection[i].name);
)--[X]
ArrayPick.Caption = "List Appended To";
LB01.items = nodeNameArray;
print("Rv array nodes===" + RV_ArrayNodes as string);
)--[#yes]
)--[MSTAT!=#cancel]
)--[Selection.count]
)--[ArrayPick Pressed]
)--[End Rollout]
CreateDialog MainRollout;
-- 1 2 3 4 5 6 7 8 9 10
--34567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890