I have a hitResult relative to a detected plane:
arFragment.setOnTapArPlaneListener(
(HitResult hitResult, Plane plane, MotionEvent motionEvent) -> {...})
I want to anchor a model to the plane and have it always face up (the ceiling):
Anchor anchor = plane.createAnchor(plane.getCenterPose());
AnchorNode anchorNode = new AnchorNode(anchor);
anchorNode.setRenderable(model);
The problem is that the model is sometimes randomly rotated. Sometimes, it does not point the ceiling: it is rotated 180 degrees, 90 degrees, or random.
(At least, all this in the emulator).
You can use something like
boolean isVerticalPlane = plane.getType() == Plane.Type.VERTICAL;
inside your setOnTapArPlaneListener from your ArFragment.
Final code will be:
ArFragment arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment);
arFragment.setOnTapArPlaneListener(new BaseArFragment.OnTapArPlaneListener() {
#Override
public void onTapPlane(HitResult hitResult, Plane plane, MotionEvent motionEvent) {
boolean isVerticalPlane = plane.getType() == Plane.Type.VERTICAL;
}
});
Related
I'm working on a game in LibGDX. Right now, I am working on drawing a line from a moving entity's body current position in the direction that it is moving. Maybe I didn't word that correctly, so here's my very artistic representation of what I'm talking about.
The problem that I'm having is that vertical lines are always much longer than diagonal lines, and diagonal lines are always much longer than horizontal lines. What I'm wanting is for the line being projected from the entity to always be the same length regardless of the direction.
Below is the code used for drawing lines from the center of an entity's body. As you can see, I am scaling the line (e.g., by 25.0f). Maybe there's a formula that I could use to dynamically change this scalar depending on the direction?
public class BodyMovementProjection implements Updatable {
public final Body body;
public final ShapeRenderer shapeRenderer;
public boolean debugProjection = false;
public float scalar = 25.0f;
private final Vector2 posThisFrame = new Vector2();
private final Vector2 posLastFrame = new Vector2();
private final Vector2 projection = new Vector2();
private float[] debugColorVals = new float[4];
public BodyMovementProjection(Body body) {
this.body = body;
this.shapeRenderer = body.entity.gameScreen.shapeRenderer;
} // BodyMovementProjection constructor
#Override
public void update() {
body.aabb.getCenter(posThisFrame);
posLastFrame.set(posThisFrame).sub(body.bodyMovementTracker.getSpritePosDelta());
projection.set(posThisFrame).sub(posLastFrame).scl(scalar).add(posLastFrame);
if (debugProjection) {
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
shapeRenderer.setColor(debugColorVals[0], debugColorVals[1], debugColorVals[2], debugColorVals[3]);
shapeRenderer.line(posLastFrame, projection);
shapeRenderer.end();
} // if
} // update
public void setDebugColorVals(float r, float g, float b, float a) {
debugColorVals[0] = r;
debugColorVals[1] = g;
debugColorVals[2] = b;
debugColorVals[3] = a;
} // setDebugColorVals
} // BodyMovementProjection
Normalize before you scale.
By normalizing you are making the directional vector 1 unit in length, and by scaling it after by 25 you get a vector that is 25 units every time, regardless of how far apart thw current and previous positions are.
I'm making an animation in which I need to keep track of explored/unexplored pixels on the screen.Initially the screen is black colored,then as the node(a circle) moves(over defined path) the explored pixels are set to white.For doing this task(color change) I'm using Canvas class of JavaFX as background and painting the path using an object of GraphicsContext class(see the createPathAnimation method),now I want to update the int 2D matrix as 0-unexplored,1-explored.
How can I use the changed() function inside createPathAnimation to update my matrix as that function is updating the pixel color to white and I need to update the same set of explored pixels to 1 in my matrix?
sample translation
I'm trying to use the inbuilt function because even if I know the initial and final pixel coordinates,its not easy to determine which all pixels will be set while the circle moves between them(for ex along one of the diagonals),since circle is a like a blob of tiny squares on a pixel level.
My motive is to find the number of white colored pixels after a diagonal translation.
public void start(Stage primaryStage)throws Exception{
Pane root=new Pane();
Path path1=createPath();
canvas=new Canvas(800,600);
root.getChildren().addAll(path1,canvas);
primaryStage.setScene(new Scene(root,800,600,Color.BLACK));
primaryStage.show();
Animation animation1=createPathAnimation(path1,Duration.seconds(10));
pt.getChildren().addAll(animation1);
pt.play();
}
private Path createPath(){
Path path=new Path();
path.setStroke(Color.BLACK);
path.setStrokeWidth(10);
path.getElements().add(new MoveTo(400,300));
path.getElements().add(new LineTo(600,500));
return path;
}
public int a,b;
private Animation createPathAnimation(Path path,Duration duration){
GraphicsContext gc=canvas.getGraphicsContext2D();
Circle pen=new Circle(0,0,10);
PathTransition pathTransition=new PathTransition(duration,path,pen);
pathTransition.currentTimeProperty().addListener(new ChangeListener<Duration>(){
Location oldLocation = null;
/**
* Draw a line from the old location to the new location
*/
#Override
public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
if( oldValue == Duration.ZERO)
return;
// get current location
double x = pen.getTranslateX();
double y = pen.getTranslateY();
// initialize the location
if( oldLocation == null) {
oldLocation = new Location();
oldLocation.x = x;
oldLocation.y = y;
return;
}
// draw line
gc.setStroke(Color.WHITE);
gc.setLineWidth(30);
gc.strokeLine(oldLocation.x, oldLocation.y, x, y);
// update old location with current one
oldLocation.x = x;
oldLocation.y = y;
}
});
return pathTransition;
}
public static class Location {
double x;
double y;
Libgdx uses a Matrix4 to express the world space position, rotation and scaleing of objects.
As I am animating these objects a lot in my code I wish to convert them to a format that keeps Position, Rotation and Scale Separate.
This makes it easier to interpolate correctly in order to animate them.
I am storing the Scale and Position both as Vector3s.
And the rotation as a Quaternion.
Here is my class that stores these 3 and converts two and from a Matrix4;
public class PosRotScale {
private static String logstag="ME.PosRotScale";
Vector3 position = new Vector3();
Quaternion rotation = new Quaternion();
Vector3 scale = new Vector3(1f,1f,1f);
public PosRotScale(Vector3 position, Quaternion rotation, Vector3 scale) {
super();
this.position = position;
this.rotation = rotation;
this.scale = scale;
}
public PosRotScale(Matrix4 setToThis) {
this.setToMatrix(setToThis);
}
#Override
public String toString(){
Vector3 axis = new Vector3();
float angle = rotation.getAxisAngle(axis);
String stateAsString = "["+position.x+","+position.y+","+position.z+"]"
+ "["+axis.x+","+axis.y+","+axis.z+","+angle+"]"
+ "["+scale.x+","+scale.y+","+scale.z+"]";
return stateAsString;
}
public void setToMatrix(Matrix4 lastLocation) {
lastLocation.getTranslation(position);
lastLocation.getRotation(rotation);
lastLocation.getScale(scale);
}
public PosRotScale setToRotation(float i, float j, float k, float angleInDeg) {
rotation.set(new Vector3(i,j,k), angleInDeg);
return this;
}
public PosRotScale setToPosition(Vector3 newposition) {
position = newposition.cpy();
return this;
}
public PosRotScale setToScaling(Vector3 newscale) {
scale = newscale.cpy();
return this;
}
public Matrix4 createMatrix() {
return new Matrix4(position,rotation.nor(),scale);
}
}
(I apologise for the snippet above having a "run as" and being interpreted as javascript - I didn't see a option in the code snippet box for Java)
Anyway, in order to test if this was working I created a test state and converted to and from it.
Unfortunately the values clearly didn't match.
I expected the rotation to be off a bit (seems to be the nature of rotations) but scale is clearly wayyyy of. Any pointers as to what I am doing wrong?
Test code;
PosRotScale startScaleAndRotation = new PosRotScale();
startScaleAndRotation.setToPosition(new Vector3(30f, 40f, 50f));
startScaleAndRotation.setToRotation(0f, 0f, 1f, 45);
startScaleAndRotation.setToScaling(new Vector3(0.5f, 2.5f,0.5f));
Gdx.app.log(logstag, " setting to: "+startScaleAndRotation.toString());
Matrix4 test = startScaleAndRotation.createMatrix();
PosRotScale test2 = new PosRotScale(test);
Gdx.app.log(logstag, " check after conversion: "+test2.toString());
Results in:
setting to: [30.0,40.0,50.0][0.0,0.0,0.99999994,45.000004][0.5,2.5,0.5]
check after conversion: [30.0,40.0,50.0][0.0,0.0,1.811493,35.83953][1.8027757,1.8027754,0.5]
This is a simplified code from what I'm trying to do:
var angle = 1.57;
if ( this.transform.rotation.y > angle ){
this.transform.rotation.y--;
} else if ( this.transform.rotation.y < angle ){
this.transform.rotation.y++;
}
I'm used to code in AS3, and if I do that in flash, it works perfectly, though in Unity3D it doesn't, and I'm having a hard time figuring out why, or how could I get that effect.
Can anybody help me? Thanks!
edit:
my object is a rigidbody car with 2 capsule colliders driving in a "bumpy" floor, and at some point he just loses direction precision, and I think its because of it's heirarchical rotation system.
(thanks to kay for the transform.eulerAngles tip)
transform.rotation retrieves a Quaternion. Try transform.rotation.eulerAngles.y instead.
Transform Rotation is used for setting an angle, not turning an object, so you would need to get the rotation, add your change, and then set the new rotation.
Try using transform.rotate instead.
Check the Unity3d scripting reference here:
http://unity3d.com/support/documentation/ScriptReference/Transform.Rotate.html
I see two problems so far. First the hierarchical rotation of Unity. Based on what you are trying to achieve you should manipulate either
transform.localEulerAngles
or
transform.eulerAngles
The second thing is, you can't modify the euler angles this way, as the Vectors are all passed by value:
transform.localEulerAngles.y--;
You have to do it this way:
Vector3 rotation = transform.localEulerAngles;
rotation.y--;
transform.localEulerAngles = rotation;
You need to create a new Quaternion Object
transform.rotation = Quaternion.Euler ( transform.rotation.x, transform.rotation.y++, transform.rotation.z );
You can also use transform.Rotate function.
The above suggestion to use transform.Rotate( ) is probably what you're going to need to do to actually make it rotate, BUT the variables of transform.Rotate( ) are velocity/speed rather than direction, so transform.Rotate( ) will have to use more than one axis if you want an angled rotation. Ex:
class Unity // Example is in C#
{
void Update( )
{
gameObject.transform.Rotate(0, 1, 0);
}
}
This will rotate the object around its y-axis at a speed of 1.
Let me know if this helps - and if it hinders I can explain it differently.
You should try multiplyng your rotation factor with Time.deltaTime
Hope that helps
Peace
Here is my script for GameObject rotation with touch
//
// RotateController.cs
//
// Created by Ramdhan Choudhary on 12/05/13.
//
using UnityEngine;
using System;
public class RotateController
{
private float RotationSpeed = 9.5f;
private const float mFingerDistanceEpsilon = 1.0f;
public float MinDist = 2.0f;
public float MaxDist = 50.0f;
private Transform mMoveObject = null;
private bool isEnabledMoving = false;
//************** Rotation Controller Constructor **************//
public RotateController (Transform goMove)
{
isEnabledMoving = true;
mMoveObject = goMove;
if (mMoveObject == null) {
Debug.LogWarning ("Error! Cannot find object!");
return;
}
}
//************** Handle Object Rotation **************//
public void Update ()
{
if (!isEnabledMoving && mMoveObject != null) {
return;
}
Vector3 camDir = Camera.main.transform.forward;
Vector3 camLeft = Vector3.Cross (camDir, Vector3.down);
// rotate
if (Input.touchCount == 1) {
mMoveObject.Rotate (camLeft, Input.touches [0].deltaPosition.y * RotationSpeed * Time.deltaTime, Space.World);
mMoveObject.Rotate (Vector3.down, Input.touches [0].deltaPosition.x * RotationSpeed * Time.deltaTime, Space.Self);
}
}
}
I am using JUNG to make a network diagram. I want to shape the vertices depending upon its type. The vertices are pickable and colored. The code for vertices so far is as under:
class VertexColors extends PickableVertexPaintTransformer<Number> {
VertexColors(PickedInfo<Number> pi) {
super(pi, Color.blue, Color.yellow);
}
public Paint transform(Number v) {
if (pi.isPicked(v.intValue())) return picked_paint;
return v.intValue()%2==1 ? Color.blue : Color.green;
}
}
I am using the following statement for each vertex:
vv.getRenderContext().setVertexFillPaintTransformer(new VertexColors(vv.getPickedVertexState()));
Now, I cannot find a way to shape the vertices while keeping them pickable and to wrap the vertices around their labels.
All you need is to add another Transformer that provides the vertex shape when it is selected. The Transformer should choose the shape based on the whether the vertex is "picked" or not. To get the picked state, you need to obtain a PickedState object from the visualization. When the selection is changed, the transformer will be asked for the shape and the vertices will be updated with the returned shape. Here is an example of how to do this:
final VisualizationViewer<Integer, String> vv = new
VisualizationViewer<Integer, String>(layout);
// Transformer for cycling the vertices between three unique shapes.
Transformer<Integer, Shape> vertexShape = new
Transformer<Integer, Shape>() {
private final Shape[] styles = {
new Ellipse2D.Double(-25, -10, 50, 20),
new Arc2D.Double(-15, -15, 30, 30, 30, 150, Arc2D.PIE) };
#Override
public Shape transform(Integer i) {
// Choose a shape according to the "picked" state.
PickedState<Integer> pickedState = vv.getPickedVertexState();
int shapeIndex = 0;
if (pickedState.isPicked(i)) {
shapeIndex = 1;
}
return styles[shapeIndex];
}
};
vv.getRenderContext().setVertexShapeTransformer(vertexShape);