three.js Unproject camera within group - camera

I have a camera as child within a Group object and I need to get the origin/direction:
var cameraRig = new THREE.Group();
cameraRig.add( cameraPerspective );
cameraRig.add( cameraOrtho );
scene.add( cameraRig );
function relativeMousePosition () {
var canvasBoundingBox = renderer.domElement.getBoundingClientRect();
var mouse3D = new THREE.Vector3(0, 0, 0.5);
mouse3D.x = ((mouseX - 0) / canvasBoundingBox.width) * 2 - 1;
mouse3D.y = -((mouseY - 0) / canvasBoundingBox.height) * 2 + 1;
return mouse3D;
}
cameraRig.position.set(89,34,91);
cameraRig.lookAt(something.position);
cameraPerspective.position.set(123,345,123);
var dir = relativeMousePosition().unproject(camera).sub(cameraPerspective.position).normalize();
var origin = cameraPerspective.position;
The above code gives a origin + direction with the context of the cameraRig. When I exclude the camera out, having the scene as direct parent, it gives me the world origin/direction which I want. So how to incorporate the cameraRig to get world origin/direction, so I can do picking or whatever?
FIDDLE: https://jsfiddle.net/647qzhab/1/
UPDATE:
As mentioned in the comment by Falk:
var dir = relativeMousePosition().unproject(camera).sub(cameraPerspective.getWorldPosition()).normalize();
var origin = cameraPerspective.getWorldPosition();
The result is better, but not yet fully satisfiing, as the camera rotation seems not applied yet.

I need to update matrixWorld for the cameraRig:
cameraRig.position.set(89,34,91);
cameraRig.lookAt(something.position);
cameraPerspective.position.set(123,345,123);
cameraRig.updateMatrixWorld(true);
cameraPerspective.updateMatrixWorld(true);

Related

Revit: Cannot create dimensions when ViewSection is rotated

I'm trying to set dimension to the elements in a AssemblyInstance. The code operates with coordinates from the first element.
AssemblyInstance ass; //is found and is not null
ViewSection vsec = RevitAuxilaries.CreateAssemblyViewSection(uiapp, ass,
AssemblyDetailViewOrientation.ElevationFront, ElementId.InvalidElementId, 25);
//UIApplication,
AssemblyInstance, AssemblyDetailViewOrientation, TemplateId, scale // created
BoundingBoxXYZ bbox1 = ass.get_BoundingBox(uiapp.ActiveUIDocument.ActiveView);
XYZ ptmid = (bbox1.Max + bbox1.Min) * 0.5;
Element cropboxelm = RevitAuxilaries.GetViewCropBox(uiapp, vsec); //finds CropBox element,
//found
BoundingBoxXYZ bcropbox = vsec.CropBox;
XYZ center = new XYZ(ptmid.X, ptmid.Y, 0.5 * (bcropbox.Max.Z + bcropbox.Min.Z));
Line axis = Line.CreateBound(center, center + XYZ.BasisZ);
RevitAuxilaries.RotateElement2(uiapp, cropboxelm, axis, 0.6981); // UIApplication,, Element,
Line, angle// created
double dw = RevitAuxilaries.GetDimensionFromElement(uiapp, fi, Dimensions.enWidth); //found dw
// = 3.937
ptleft = new XYZ(31.501, -23.3878, 32.4803);
ptrght = new XYZ(31.501 + dw * Math.Cos(0.6981), -23.3878 + dw * Math.Sin(0.6981), 32.4803);
Line ln = RevitAuxilaries.CreateLineFromPoints(uiapp, ptleft, ptrght); //created
ReferenceArray refarr = new ReferenceArray();
refarr.Append(ln.GetEndPointReference(0));
refarr.Append(ln.GetEndPointReference(1));
Dimension dim = null;
using (Transaction trans = new Transaction(uiapp.ActiveUIDocument.Document, "CreADim"))
{
trans.Start();
dim = uiapp.ActiveUIDocument.Document.Create.NewDimension(viewsec, line, refarr);
if (!issame)
{
try
{ dim.ValueOverride = Convert.ToInt32(UnitUtils.Convert(dim.Value.Value,
UnitTypeId.Feet, UnitTypeId.Millimeters)).ToString(); }
catch { }
}
trans.Commit();
uiapp.ActiveUIDocument.RefreshActiveView();
}
ERROR: The direction of dimension is invalid
Error in function checkDir, line 939
What is here wrong?
Have you tried to create the exact same dimension in the exact same context manually through the end user interface? Does that complete as expected? If not, what error message does that generate? If yes, you can analyse the resulting model, its elements and their properties using RevitLookup and possibly discover some required settings that can be added to your API approach.

Photoshop script to duplicate and rename layer

While creating a script that would automate all the different tasks I do when I start working on a new picture on Photoshop, I encountered the following problem.
I want to create different groups and different layers inside these groups. Everything goes perfectly fine until this :
#target photoshop
app.bringToFront();
var doc = app.activeDocument;
newCurve();
var clippingHelpLayerLight = doc.activeLayer;
clippingHelpLayerLight.blendMode = BlendMode.SCREEN;
clippingHelpLayerLight.name = "Clipping Help Layer - Light";
clippingHelpLayerLight.visible = false;
clippingHelpLayerLight.duplicate();
var clippingHelpLayerLighter = doc.activeLayer;
clippingHelpLayerLighter.name = "Clipping Help Layer - Lighter";
clippingHelpLayerLighter.visible = false;
function newCurve() {
var c_ADJ_LAYER = charIDToTypeID("AdjL");
var c_ADJUSTMENT = charIDToTypeID("Adjs");
var c_CHANNEL = charIDToTypeID("Chnl");
var c_COMPOSITE = charIDToTypeID("Cmps");
var c_CURVE = charIDToTypeID("Crv ");
var c_CURVE_A = charIDToTypeID("CrvA");
var c_CURVES = charIDToTypeID("Crvs");
var c_HORIZONTAL = charIDToTypeID("Hrzn");
var c_MAKE = charIDToTypeID("Mk ");
var c_NULL = charIDToTypeID("null");
var c_POINT = charIDToTypeID("Pnt ");
var c_TYPE = charIDToTypeID("Type");
var c_USING = charIDToTypeID("Usng");
var c_VERTICAL = charIDToTypeID("Vrtc");
var d_CURVES_LAYER = new ActionDescriptor();
// Contains all the information necessary to perform the "MAKE" action
var r_CLASS = new ActionReference();
r_CLASS.putClass(c_ADJ_LAYER);
d_CURVES_LAYER.putReference(c_NULL, r_CLASS);
// Class of make action is of an ajdustment layer
var d_TYPE_CURVES = new ActionDescriptor();
// Contains all the information about all the curves
var d_CHANNEL_CURVES = new ActionDescriptor();
var l_CHANNEL_CURVES = new ActionList();
// Contains a list of channel curves
var d_CHANNEL_CURVE = new ActionDescriptor();
// Information for 1 channel curve
var r_CHANNEL = new ActionReference();
r_CHANNEL.putEnumerated(c_CHANNEL, c_CHANNEL, c_COMPOSITE);
// This curve is for the composite channel - VARIES
d_CHANNEL_CURVE.putReference(c_CHANNEL, r_CHANNEL);
// Contains the point list
var l_POINTS = new ActionList();
// List of points for this channel - LENGTH VARIES
var d_POINT = new ActionDescriptor();
// One point on the curve, has INPUT and OUTPUT value
d_POINT.putDouble(c_HORIZONTAL, 0.000000);
d_POINT.putDouble(c_VERTICAL, 0.000000);
l_POINTS.putObject(c_POINT, d_POINT);
//var d_POINT3 = new ActionDescriptor();
d_POINT.putDouble(c_HORIZONTAL, 255.000000);
d_POINT.putDouble(c_VERTICAL, 255.000000);
l_POINTS.putObject(c_POINT, d_POINT);
// Made the list of points
d_CHANNEL_CURVE.putList(c_CURVE, l_POINTS);
// Now have a list of points for a specific channel
l_CHANNEL_CURVES.putObject(c_CURVE_A, d_CHANNEL_CURVE);
// Add to the list of channel curves
d_CHANNEL_CURVES.putList(c_ADJUSTMENT, l_CHANNEL_CURVES);
// All the channel curves are inside here
d_TYPE_CURVES.putObject(c_TYPE, c_CURVES, d_CHANNEL_CURVES);
// .....
d_CURVES_LAYER.putObject(c_USING, c_ADJ_LAYER, d_TYPE_CURVES);
// package the curves and definition of the adjustment layer type
executeAction(c_MAKE, d_CURVES_LAYER, DialogModes.NO);
}
I actually want to create a first layer called "Clipping Help Layer - Light", blend mode : screen and turn it off. Then duplicate it, change the name of the new layer as "Clipping Help Layer - Lighter" and turn it off too.
Like this : Screenshot of what I would like to do
It does create the 2 layers, but the first one has " copy" at the end of its name and it stays turned on.
Screenshot of the actual result
Why ?
I can't understand why it doesn't work as expected and can't manage to fix it.
Any help would be greatly appreciated !
I believe the problem you are encountering has to do with doc.activeLayer. After you duplicate "Clipping Help Layer - Light," the script does not seem to change what doc.activeLayer is pointing to so when you then try to assign it to clippingHelpLayerLighter, you are then pointing at an undefined layer. While I don't know exactly what is happening behind the scenes when you do that, I do believe this will fix your problem:
#target photoshop
app.bringToFront();
var doc = app.documents.add( 4, 4 );
doc = app.activeDocument;
var clippingHelpLayerLight = doc.activeLayer;
clippingHelpLayerLight.blendMode = BlendMode.SCREEN;
clippingHelpLayerLight.name = "Clipping Help Layer - Light";
clippingHelpLayerLight.visible = false;
clippingHelpLayerLight.duplicate();
doc.activeLayer = doc.layers[ "Clipping Help Layer - Light copy" ];
doc.activeLayer.name = "Clipping Help Layer - Lighter";
doc.activeLayer.visible = false;
//I am not sure if you need this pointer to be called upon later in your
//code. If you do not, just leave this line out.
var clippingHelpLayerLighter = doc.activeLayer;
Hope this helps! Let me know if you have any questions, I'm by no means an expert but I use scripts fairly often.

TweenJS rect command "grow from center"

new to createjs here:
Created this fiddle: example. I would like the rect to grow from the center and not from the top left corner. I couldn't find any help, I don't know what to search for.
Code:
const PAGE_WIDTH = 150,
PAGE_HEIGHT = 75;
var stage = new createjs.Stage("canvas");
createjs.Ticker.setFPS(60);
createjs.Ticker.on("tick", tick);
var page = new createjs.Shape();
page.regX = PAGE_WIDTH/2;
page.regY = PAGE_HEIGHT/2;
page.x = 50;
page.y = 50;
stage.addChild(page);
var pageCommand = page.graphics
.beginFill('red')
.drawRect(0, 0, 1, 1).command;
createjs.Tween.get(pageCommand)
.to({w:PAGE_WIDTH, h: PAGE_HEIGHT}, 700, createjs.Ease.elasticOut)
function tick() {
stage.update();
}
Thanks.
The best way is to change the registration point of your graphics so it grows from the center.
Your code:
.drawRect(0, 0, 1, 1).command;
.to({w:PAGE_WIDTH, h: PAGE_HEIGHT})
Instead:
.drawRect(-1.-1, 2, 2);
.to({x:-PAGE_WIDTH/2, y:-PAGE_WIDTH/2, w:PAGE_WIDTH, h: PAGE_HEIGHT})
Fiddle: http://jsfiddle.net/1kjkqo2v/
[edit: I said 2 options initially, but the second (using regX and regY) wouldn't work well, since you have to tween that value as well as your size changes.]

Is there a better way to fix my AS2 preloader?

I have a game with a preloader in scene 1, with the following code on the time line.
stop();
loadingBar._xscale = 1;
var loadingCall:Number = setInterval(preloadSite, 50);
function preloadSite():Void {
var siteLoaded:Number = _root.getBytesLoaded();
var siteTotal:Number = _root.getBytesTotal();
var percentage:Number = Math.round(siteLoaded/siteTotal*100);
loadingBar._xscale = percentage;
bytesDisplay.text = percentage + "%";
if (siteLoaded >= siteTotal) {
clearInterval(loadingCall);
gotoAndPlay("StartMenu", 1);
}
}
The code works fine when there are no music files linked to frame 1. If there are music files linked, then everything loads before the preloader shows up.
I found this great webpage about preloaders, which speaks about the linkage issue, and suggests I put all the big files on frame 2, after the preloader, then skip them. I put my large files on frame 2 as suggested and the preloader worked again.
My question is, is there a better way to do this. This solution seems like a hack.
The only better option I can think of, is to NOT store the MP3 file in your Flash file, but rather load it in your preloader with your flash file's content. This is provided that you're storing your MP3 file somewhere else online (like on a server).
stop();
loadingBar._xscale = 1;
var sound:Sound = new Sound();
sound.loadSound("http://www.example.com/sound.mp3", false);
var loadingCall:Number = setInterval(preloadSite, 50);
function preloadSite():Void {
var siteLoaded:Number = _root.getBytesLoaded()+sound.getBytesLoaded();
var siteTotal:Number = _root.getBytesTotal()+sound.getBytesTotal();
var percentage:Number = Math.round(siteLoaded / siteTotal * 100);
loadingBar._xscale = percentage;
bytesDisplay.text = percentage + "%";
if (siteLoaded >= siteTotal) {
clearInterval(loadingCall);
gotoAndPlay("StartMenu", 1);
sound.start();
}
}

Flex 3 - Enable context menu for text object under a transparent PNG

Here is the situation. In my app I have an overlay layer that is composed of a transparent PNG. I have replaced the hitarea for the png with a 1x1 image using the following code:
[Bindable]
[Embed(source = "/assets/1x1image.png")]
private var onexonebitmapClass:Class;
private function loadCompleteHandler(event:Event):void
{
// Create the bitmap
var onexonebitmap:BitmapData = new onexonebitmapClass().bitmapData;
var bitmap:Bitmap;
bitmap = event.target.content as Bitmap;
bitmap.smoothing = true;
var _hitarea:Sprite = createHitArea(onexonebitmap, 1);
var rect:flash.geom.Rectangle = _box.toFlexRectangle(sprite.width, sprite.height);
var drawnBox:Sprite = new FlexSprite();
bitmap.width = rect.width;
bitmap.height = rect.height;
bitmap.x = -loader.width / 2;
bitmap.y = -loader.height / 2;
bitmap.alpha = _alpha;
_hitarea.alpha = 0;
drawnBox.x = rect.x + rect.width / 2;
drawnBox.y = rect.y + rect.height / 2;
// Add the bitmap as a child to the drawnBox
drawnBox.addChild(bitmap);
// Rotate the object.
drawnBox.rotation = _rotation;
// Add the drawnBox to the sprite
sprite.addChild(drawnBox);
// Set the hitarea to drawnBox
drawnBox.hitArea = _hitarea;
}
private function createHitArea(bitmapData:BitmapData, grainSize:uint = 1):Sprite
{
var _hitarea:Sprite = new Sprite();
_hitarea.graphics.beginFill(0x900000, 1.0);
for (var x:uint = 0; x < bitmapData.width; x += grainSize)
{
for (var y:uint = grainSize; y < bitmapData.height; y += grainSize)
{
if (x <= bitmapData.width && y <= bitmapData.height && bitmapData.getPixel(x, y) != 0)
{
_hitarea.graphics.drawRect(x, y, grainSize, grainSize);
}
}
}
_hitarea.graphics.endFill();
return _hitarea;
}
This is based off the work done here: Creating a hitarea for PNG Image with transparent (alpha) regions in Flex
Using the above code I am able to basically ignore the overlay layer for all mouse events (click, double click, move, etc.) However, I am unable to capture the right click (context menu) event for items that are beneath the overlay.
For instance I have a spell check component that checks the spelling on any textitem and like most other spell checkers if the word is incorrect or not in the dictionary underlines the word in red and if you right click on it would give you a list of suggestions in the contextmenu. This is working great when the text box is not under the overlay, but if the text box is under the overlay I get nothing back.
If anyone can give me some pointers on how to capture the right click event on a textItem that is under a transparent png that would be great.