Creating a subwindow to show a plan view

In our page about sectioning floors, we saw that in addition to the main view, there was also a plan view displayed in the lower left corner of the screen. This section describes how to implement that view using a subwindow.

There are three steps to showing this view:

  1. Defining a subwindow where we want to display something

  2. Defining what we want to display

  3. Defining how we want to display it

../../_images/plan_view.png

Creating a subwindow

Up to this point in our tutorial, we have been talking about the CAD scene graph as a hierarchy of components. In reality, the component hierarchy representing the model is part of a larger scene graph which more generally represents the entire scene. This larger scene graph includes things like the window, views, navigation aides (if any), geometry, and other general information about the scene as a whole. In HOOPS, the nodes of the scene graph are called segments.

Each segment has attributes which define how it and its descendents behave in the scene. For example, the root segment would contain attributes which define the driver used for rendering, while other segments may contain attributes defining color, lighting, and other rendering information.

More information on segments can be found here.

The components that make up the component hierachy are no different - each component is a special type of segment configured to hold CAD model data.

A subwindow can be thought of as a window which displays a different view of the model. Subwindows are often used in a nested fashion inside of a larger view, but they can also be used to divide the main window into sections. A potentially confusing point about working with subwindows is that unlike normal windows, we’re not working with a specific object called a subwindow. Its just a regular segment with a subwindow attribute. You never get an explicit handle to a subwindow.

Subwindows are described in detail in the HOOPS Visualize Programming Guide section on subwindows.

You can think of it as just defining which part of the screen should be drawn into with respect to the normal window. The code to create the subwindow is shown below:

	_planviewKey = viewKey.Subsegment("planView", true);
	_locationKey = _planviewKey.Subsegment("cameraLocation", true);
 
	 _contentKey = _planviewKey.Subsegment("content", true);
	_contentKey.IncludeSegment(modelKey);
 
	HPS::SubwindowKit subwindowKit;
	subwindowKit.SetSubwindow(HPS::Rectangle(-1, -0.5f, -1, -0.25), HPS::Subwindow::Type::Standard);
	subwindowKit.SetBorder(HPS::Subwindow::Border::None);
	subwindowKit.SetBackground(HPS::Subwindow::Background::Transparent);
	_planviewKey.SetSubwindow(subwindowKit);
	_planviewKey.InsertDistantLight(HPS::Vector(0.5f, 0.5f, 0.5f));

There are two types of subwindows: standard and lightweight. We’re using a standard subwindow as there is more control over the scene. The subwindow is located using normalized coordinates. The entire window would run from -1 to + 1 in x and y, so our coordinates will locate it in the bottom left quadrant. The segment holding the subwindow is attached to the view. As shown in the previous code snippet, we define a camera from above in our _planView segment.

Scene contents

We want to view the entire model, and therefore, we will attach (or include) the model segment to our subwindow’s segment. To get the model segment, we get the HPS::Model associated with the CADModel and then the SegmentKey associated with the HPS::Model.

Since we are working with two views of the same model, any cutting plane defined on the model will also apply to the plan view.

Display

Finally, we define a camera looking at the scene from above. To create the camera we want, the following steps are used:

  1. To get a tight fit, we get a bound on the scene using a HPS::KeyPath.

  2. The camera view is set to “orthographic”.

  3. Using the bounds, we set up a camera looking straight down above the center of the model.

    New users are often confused about the KeyPath object and its purpose. In short, a KeyPath represents an unambiguous path in the scene graph from a leaf node to the root. Since each node (or segment) in the scene graph has a unique key, a building collection of these keys forms a “path” - thus the HPS::KeyPath object. From this information, a HOOPS Visualize can calculate a bounding geometry. For more, see this page.

	HPS::KeyPath keyPath;
	keyPath.PushBack(modelKey);
	HPS::BoundingKit bound;
	keyPath.ShowNetBounding(bound);
	HPS::SimpleSphere boundingSphere;
	HPS::SimpleCuboid boundingCuboid;
 
	bound.ShowVolume(boundingSphere, boundingCuboid);
 
	float cx = (boundingCuboid.min.x + boundingCuboid.max.x) / 2;
	float cy = (boundingCuboid.min.y + boundingCuboid.max.y) / 2;
	float cz = (boundingCuboid.min.z + boundingCuboid.max.z) / 2;
 
	float scale = 1.05;
	float dx = (boundingCuboid.max.x - boundingCuboid.min.x)  * scale;
	float dy = (boundingCuboid.max.y - boundingCuboid.min.y) *  scale;
	float dz = (boundingCuboid.max.z - boundingCuboid.min.z) *  scale;
 
	float delta = fmax(dx, dy); // we want a square 
 
	HPS::Point camCenter(cx, cy, cz);
	HPS::Point camPos(cx, cy, cz + 1);
 
	HPS::CameraKit camKit;
	camKit.SetTarget(camCenter);
	camKit.SetPosition(camPos);
	camKit.SetField(delta, delta);
	camKit.SetUpVector(HPS::Vector(0, 1, 0));
	camKit.SetProjection(HPS::Camera::Projection::Orthographic);
	_planviewKey.SetCamera(camKit);