Hello,
We are trying to replicate the view from Forge Viewer into a perspective view within Revit 2023.
To achieve this, we followed this article: Map Forge Viewer Camera back to Revit.
In Revit, when the internal origin is located at the center of the model, the views matched perfectly.
However, we have encountered an issue when the internal origin is not positioned at the center of the model. We couldn't find the same view.
This discrepancy in camera positioning appears to be the root of the problem.
If you have any insights or suggestions on resolving this issue, we would greatly appreciate your assistance.
Solved! Go to Solution.
Solved by jeremy_tammik. Go to Solution.
Solved by eason.kangEDLV4. Go to Solution.
Solved by eason.kangEDLV4. Go to Solution.
Maybe Eason can help you, being the author of the post you refer to, so I sent him a message informing him of your question here.
Could you elaborate on what "internal origin is not positioned at the center of the model" means? Is it in viewer or in Revit?
Thanks for your reply.
In Revit, I am testing on a first model, where the Internal origin is at the center of the model as shown in the photo below:
This works fine.
On another model, I noticed that the model is a bit far from the Internal origin point, and there I don't have the same view as on Forge.
Thank you for getting back to me. If I understand correctly, this issue happens when mapping APS/Forge viewer's camera back to Revit, right? But that should be irrelevant to Revit's internal origin but related to how we map points in the viewer's coordinate space to Revit's internal coordinate space.
If so, please try to re-map the position and target from viewer's coordinate space to Revit one by multiplying the transform we get from `model.getInverseModelToViewerTransform()` in the viewer.
const state = viewer.getState({ viewport: true });
const model = viewer.getAllModels()[0];
const invTransform = model.getInverseModelToViewerTransform();
const currentTarget = new THREE.Vector3().fromArray( state.viewport.target );
// {x: -14.770469665527344, y: 36.571967124938965, z: -1.212925910949707}
const currentPosition = new THREE.Vector3().fromArray( state.viewport.eye );
// {x: -14.870469093322754, y: 36.57156276702881, z: -1.212925910949707}
const originTarget = currentTarget.clone().applyMatrix4( invTransform );
// {x: -15.02436066552734, y: -8.984211875061035, z: 4.921260089050291}
const originPosition = currentPosition.clone().applyMatrix4( invTransform );
// {x: -15.12436009332275, y: -8.984616232971192, z: 4.921260089050291}
And then in Revit,
public void SyncCamera() {
using(var trans = new Transaction(dbDocument, "Map viewer Camera")) {
try {
if (trans.Start() == TransactionStatus.Started) {
var view3D = activeDbView as View3D;
// By default, the 3D view uses a default orientation.
// Change the orientation by creating and setting a ViewOrientation3D
var position = new XYZ(-15.02436066552734, -8.984211875061035, 4.921260089050291); ///!<<< viewer camera's position or state.viewport.eye
var target = new XYZ(12.322365033072593, -154.95122627204464, -37.64853761076602); ///!<<< viewer camera's target or state.viewport.target
var up = new XYZ(0, 0, 1); ///!<<< viewer camera's up or state.viewport.up
var fov = 90.68087674208; ///!<<< viewer state.viewport.fov
var aspectRatio = 0.10000024532334; ///!<<< viewer state.viewport.aspectRatio
var sightDir = target.Subtract(position).Normalize();
var right = sightDir.CrossProduct(up);
var adjustedUp = right.CrossProduct(sightDir);
var orientation = new ViewOrientation3D(position, adjustedUp, sightDir);
view3D.SetOrientation(orientation);
var zoomCorners = this.CalculateZoomCorners(view3D, position, target, fov, aspectRatio);
var uiView = activeUIDocument.GetOpenUIViews().FirstOrDefault(v => v.ViewId == view3D.Id);
uiView.ZoomAndCenterRectangle(zoomCorners[0], zoomCorners[1]);
activeUIDocument.RefreshActiveView();
activeUIDocument.UpdateAllOpenViews();
trans.Commit();
}
} catch (Exception ex) {
trans.RollBack();
TaskDialog.Show("Revit", ex.Message);
}
}
}
private XYZ[] CalculateZoomCorners(View3D view, XYZ position, XYZ target, double fov, double aspectRatio) {
var sightVec = position - target;
var halfHeight = Math.Tan((fov / 2) * Math.PI / 180) * sightVec.GetLength();
var halfWidth = halfHeight * aspectRatio;
var upDirectionVec = sightVec.CrossProduct(view.RightDirection).Normalize() * halfHeight;
var rightDirectionVecOnNearPlane = sightVec.CrossProduct(upDirectionVec).Normalize() * halfWidth;
var diagonalVec = upDirectionVec.Add(rightDirectionVecOnNearPlane);
var corner1 = target.Add(diagonalVec);
var corner2 = target.Add(diagonalVec.Negate());
return new XYZ[] {
corner1,
corner2
};
}
Cheers,
Hi @ahmedabid933,
I haven't had the luck to hear back from you yet. But I updated my sample here. Maybe you can try to see if it works for you.
https://github.com/yiskang/aps-viewer-revit-camera-sync
Cheers,
Eason explored further to resolve this and many other aspects and published his results in two blog posts:
The solution looks very exhaustive indeed. Thank you very much for that, Eason!
Hi @eason.kangEDLV4 and @jeremy_tammik ,
I want to express my gratitude for your invaluable assistance and support.
I tried the solution and it worked fine. It's really exhaustive.
Thanks to your expertise and willingness to help, I was able to understand the problem and resolve it.
Thank you very much for your valuable assistance.
Best regards,
It's our great honor to help you with the topic. Thank you very much for your kind testing and good news!
I'm also glad to hear my sample and blog posts work for you. 🙂
Cheers,
Can't find what you're looking for? Ask the community or share your knowledge.