use of maspack.matrix.RotationMatrix3d in project artisynth_core by artisynth.
the class LineSegment method computeFocalPoint.
/**
* Given a plane expressed in eye coordinates, compute a representative focal
* point (in eye coordinates) for this plane, and return the distance
* per-pixal for this focal point. Returning -1 means that the plane is
* invisible.
*
* <p>
* The method works by finding the centroid of the (clipped) polygon
* associated with the grid boundary, as seen in screen coordinates. This
* centroid is the projected back onto the plane.
*/
private double computeFocalPoint(Point3d focus, RigidTransform3d TGW, Renderer renderer) {
RigidTransform3d XGridToEye = new RigidTransform3d();
RigidTransform3d TWorldToEye = renderer.getViewMatrix();
XGridToEye.mul(TWorldToEye, TGW);
if (focus == null) {
focus = new Point3d();
}
if (renderer.isOrthogonal()) {
Plane plane = new Plane();
plane.set(XGridToEye);
computeFocalPoint(focus, plane, 0, 0, 1);
return renderer.getViewPlaneWidth() / renderer.getScreenWidth();
}
double near = renderer.getViewPlaneDistance();
double far = renderer.getFarPlaneDistance();
double vw = renderer.getViewPlaneWidth();
double vh = renderer.getViewPlaneHeight();
// double fov = renderer.getFieldOfViewY();
int height = renderer.getScreenHeight();
double nearDistPerPixel = renderer.getViewPlaneHeight() / height;
GridCentroidComputer newComp = new GridCentroidComputer(myMinSize, near, far);
Point3d cent = new Point3d();
if (!newComp.computeCentroid(cent, XGridToEye, vw, vh)) {
return -1;
}
double zmax = newComp.getZmax();
double zmin = newComp.getZmin();
RotationMatrix3d R = XGridToEye.R;
Plane plane = new Plane(new Vector3d(R.m02, R.m12, R.m22), new Point3d(XGridToEye.p));
double s = plane.intersectLine(focus, cent, Point3d.ZERO);
if (s == Double.POSITIVE_INFINITY) {
focus.scale(-(zmin + zmax) / (2 * near), cent);
}
double zref = -focus.z;
return zref / near * nearDistPerPixel;
}
use of maspack.matrix.RotationMatrix3d in project artisynth_core by artisynth.
the class LineSegment method drawGrid.
private void drawGrid(Renderer renderer) {
if (myMinSize == 0) {
return;
}
double distPerPixel = computeFocalPoint(null, XGridToWorld, renderer);
if (distPerPixel == -1) {
// grid is invisible
return;
}
if (myAutoSizedP) {
// start by computing the minor spacing, and then compute the major
// spacing assume 10 cell divisions
GLGridResolution res = updateResolution(distPerPixel);
if (!myResolution.equals(res)) {
if (myUseWorldOrigin) {
// May need to change position to accomodate new resolution.
RigidTransform3d TGWnew = new RigidTransform3d(XGridToWorldTarget);
AlignConstrainer aligner = new AlignConstrainer();
aligner.updatePose(TGWnew, XGridToWorldTarget);
double dpp = computeFocalPoint(null, TGWnew, renderer);
GLGridResolution resx = updateResolution(dpp);
if (resx.equals(res)) {
myResolution.set(res);
setGridToWorld(TGWnew);
} else {
// System.out.println ("cycle detected");
}
// Old code without cycle detection
// myResolution.set (res);
// setGridToWorld (XGridToWorldTarget);
} else {
myResolution.set(res);
}
}
}
double majorSize = myResolution.getMajorCellSize();
int numDivisions = myResolution.getNumDivisions();
// minor cell size
double minorSize;
// number of minor cells on each side of the x and y axes
int halfCellCnt;
minorSize = majorSize / numDivisions;
halfCellCnt = (int) Math.ceil(myMinSize / (2 * minorSize));
if (halfCellCnt == 0) {
halfCellCnt = numDivisions;
} else if (halfCellCnt % numDivisions != 0) {
// increase effective size so grid boundary lies on a major divison
halfCellCnt = numDivisions * (halfCellCnt / numDivisions + 1);
}
// Limit total number of cells that are drawn, in case a sideways view
// produces many subdivisions.
int maxCells = 200;
if (halfCellCnt > maxCells) {
halfCellCnt = maxCells;
}
double halfSize = halfCellCnt * minorSize;
// number of x axis cell divisions
int xcnt = 2 * halfCellCnt + 1;
// maximum x value
double xmax = halfSize;
// minimum x value
double xmin = -xmax;
// number of y axis cell divisions
int ycnt = 2 * halfCellCnt + 1;
// maximum y value
double ymax = halfSize;
// minimum y value
double ymin = -ymax;
// y_axis_i and x_axis_j are the cell division indices associated with
// the grid's x and y axes
double xoff = 0;
double yoff = 0;
if (myUseWorldOrigin) {
Point3d center = new Point3d();
// compute offset so the axes correspond to the real world center
center.inverseTransform(XGridToWorld);
xoff = center.x;
yoff = center.y;
}
int y_axis_i = (int) Math.round((xmax + xoff) / minorSize);
int x_axis_j = (int) Math.round((ymax + yoff) / minorSize);
float[] minorRGB = new float[3];
if (myMinorRGB == null) {
// create a default minor RBG
float s = 0.4f;
for (int i = 0; i < 3; i++) {
minorRGB[i] = s * myMajorRGB[i];
}
if (myViewer != null) {
// blend with background color of viewer
float[] backgroundRGB = myViewer.getBackgroundColor().getRGBColorComponents(null);
for (int i = 0; i < 3; i++) {
minorRGB[i] += (1 - s) * backgroundRGB[i];
}
}
} else {
minorRGB = myMinorRGB;
}
float[] xColor = myXAxisRGB;
float[] yColor = myYAxisRGB;
if (myLockAxesToWorld) {
// x and y axis colors are determined from corresponding world axes
RotationMatrix3d R = XGridToWorld.R;
// world x axis extracted from first column of XGridToWorld.R
xColor = getWorldAxisColor(R.m00, R.m10, R.m20);
// world y axis extracted from second column of XGridToWorld.R
yColor = getWorldAxisColor(R.m01, R.m11, R.m21);
}
// *********************************************************
// Old code that adjusted the intensity of the minor axis lines depending
// on how close we were to changing the grid resolution. This gave a
// smooth transition between different resolutions when
// autosizing. Difficult to get right (and not as necessary) with the
// more complex autosizing algorithm.
//
// // minSpc is the minimum possible value for minorSize. Maximum possible
// // value is 10x this, and the difference is used to determine the minor
// // grid color
// double minSpc = myMinCellPixels * distPerPixel;
//
// if (myAutoSizingP) {
// float s = (float)(minorSize / (10 * minSpc));
// for (int i = 0; i < 3; i++) {
// myMinorRGB[i] = (0.2 + 0.8 * s)*myDivisionRGB[i]
// }
// }
// *********************************************************
// maybe update info
rcacheInfo.update(numDivisions, (float) minorSize, xcnt, ycnt, x_axis_j, y_axis_i, (float) xmin, (float) xmax, (float) ymin, (float) ymax, xColor, yColor, myMajorRGB, minorRGB);
Shading savedShading = renderer.setShading(Shading.NONE);
renderer.setLineWidth(myLineWidth);
renderer.pushModelMatrix();
renderer.mulModelMatrix(XGridToWorld);
renderer.drawLines(rcacheInfo.getRenderObject());
renderer.setDepthOffset(1);
if (myXAxisLabeling != AxisLabeling.OFF || myYAxisLabeling != AxisLabeling.OFF) {
drawAxisLabels(renderer, xcnt, ycnt, majorSize, numDivisions, distPerPixel);
}
renderer.popModelMatrix();
renderer.setLineWidth(1);
renderer.setShading(savedShading);
}
use of maspack.matrix.RotationMatrix3d in project artisynth_core by artisynth.
the class GLViewer method rotateContinuous.
// /**
// * Distance of pixel from center (Euchlidean)
// * @param x
// * @param y
// * @return
// */
// private double centerDistance (int x, int y) {
// int dx = x - width / 2;
// int dy = y - height / 2;
// return Math.sqrt (dx * dx + dy * dy);
// }
/**
* Rotate the eye coordinate frame about the center point, independent
* of the default up vector.
*
* @param xang
* amount of horizontal rotation (in radians)
* @param yang
* amount of vertical rotation (in radians)
*/
protected void rotateContinuous(double xang, double yang) {
Vector3d reye = new Vector3d();
reye.sub(getEye(), myViewState.myCenter);
// up-facing vector
Vector3d yCam = new Vector3d();
// right-facing vector
Vector3d xCam = new Vector3d();
synchronized (viewMatrix) {
viewMatrix.R.getRow(1, yCam);
viewMatrix.R.getRow(0, xCam);
}
// System.out.println("Transform: " + XEyeToWorld.R);
if (yang != 0) {
RotationMatrix3d R = new RotationMatrix3d(new AxisAngle(xCam, yang));
reye.transform(R);
yCam.transform(R);
}
if (xang != 0) {
reye.transform(new RotationMatrix3d(new AxisAngle(yCam, xang)));
}
Point3d eye = new Point3d();
eye.add(reye, myViewState.myCenter);
setEyeToWorld(eye, myViewState.myCenter, yCam);
repaint();
}
use of maspack.matrix.RotationMatrix3d in project artisynth_core by artisynth.
the class RotatableScaler3d method updateRotation.
protected void updateRotation(RotationMatrix3d Rot, boolean constrained, boolean repositioning) {
RotationMatrix3d R = new RotationMatrix3d();
R.mulInverseLeft(myRot0, Rot);
if (constrained) {
AxisAngle axisAng = new AxisAngle();
R.getAxisAngle(axisAng);
double deg = Math.toDegrees(axisAng.angle);
axisAng.angle = Math.toRadians(5 * Math.round(deg / 5));
R.setAxisAngle(axisAng);
myRotPnt.transform(R, myPnt0);
}
RotationMatrix3d Rinc = new RotationMatrix3d();
Rinc.mulInverseLeft(myLastR, R);
myLastR.set(R);
if (repositioning) {
myXDraggerToWorld.R.mul(Rinc);
}
}
use of maspack.matrix.RotationMatrix3d in project artisynth_core by artisynth.
the class Transrotator3d method mouseDragged.
public boolean mouseDragged(MouseRayEvent e) {
if (mySelectedComponent != NONE) {
// boolean constrained = dragIsConstrained (e);
boolean constrained = dragIsConstrained();
if (mySelectedComponent == X_ROTATE || mySelectedComponent == Y_ROTATE || mySelectedComponent == Z_ROTATE) {
RotationMatrix3d R = new RotationMatrix3d();
findRotation(R, myRotPnt, e.getRay());
updateRotation(R, constrained);
} else {
Point3d pnt = new Point3d();
intersectRayAndFixture(pnt, e.getRay());
updatePosition(myPnt0, pnt, constrained);
}
// if (!dragIsRepositioning(e)) {
if (!dragIsRepositioning()) {
fireDraggerMoveListeners(myTransform, myIncrementalTransform, e.getModifiersEx());
}
return true;
}
return false;
}
Aggregations