目录
1、编写代码
Viewer.h
Viewer.cpp
ViewerInteractor.h
ViewerInteractor.cpp
helloworld.cpp
2、配置
3、编译运行
1、编写代码
Viewer.h
#pragma once
#ifdef _WIN32
#include <Windows.h>
#endif
// Local includes
#include "ViewerInteractor.h"
// OpenCascade includes
#include <TopoDS_Shape.hxx>
#include <WNT_Window.hxx>
// Standard includes
#include <vector>
class V3d_Viewer;
class V3d_View;
class AIS_InteractiveContext;
class AIS_ViewController;
//-----------------------------------------------------------------------------
//! Simple 3D viewer.
class Viewer
{
public:
Viewer(const int left,const int top,const int width,const int height);
public:
Viewer& operator<<(const TopoDS_Shape& shape){this->AddShape(shape);return *this;}
void AddShape(const TopoDS_Shape& shape);
void StartMessageLoop();
private:
static LRESULT WINAPIwndProcProxy(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam);
LRESULT CALLBACKwndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam);
void init(const HANDLE& windowHandle);
/* API-related things */
private:
std::vector<TopoDS_Shape> m_shapes; //!< Shapes to visualize.
/* OpenCascade's things */
private:
Handle(V3d_Viewer) m_viewer;Handle(V3d_View) m_view;Handle(AIS_InteractiveContext) m_context;Handle(WNT_Window) m_wntWindow;Handle(ViewerInteractor) m_evtMgr;
/* Lower-level things */
private:
HINSTANCE m_hInstance; //!< Handle to the instance of the module.HWND m_hWnd; //!< Handle to the instance of the window.bool m_bQuit; //!< Indicates whether user want to quit from window.
};
Viewer.cpp
// Own include
#include "Viewer.h"
// OpenCascade includes
#include <AIS_InteractiveContext.hxx>
#include <AIS_Shape.hxx>
#include <Aspect_DisplayConnection.hxx>
#include <Aspect_Handle.hxx>
#include <OpenGl_GraphicDriver.hxx>
#include <V3d_AmbientLight.hxx>
#include <V3d_DirectionalLight.hxx>
#include <V3d_View.hxx>
#include <V3d_Viewer.hxx>
namespace {//! Adjust the style of local selection.//! \param[in] context the AIS context.void AdjustSelectionStyle(const Handle(AIS_InteractiveContext)& context)
{// Initialize style for sub-shape selection.Handle(Prs3d_Drawer) selDrawer = new Prs3d_Drawer;//selDrawer->SetLink(context->DefaultDrawer());selDrawer->SetFaceBoundaryDraw(true);selDrawer->SetDisplayMode(1); // ShadedselDrawer->SetTransparency(0.5f);selDrawer->SetZLayer(Graphic3d_ZLayerId_Topmost);selDrawer->SetColor(Quantity_NOC_GOLD);selDrawer->SetBasicFillAreaAspect(new Graphic3d_AspectFillArea3d());
// Adjust fill area aspect.const Handle(Graphic3d_AspectFillArea3d)&fillArea = selDrawer->BasicFillAreaAspect();//fillArea->SetInteriorColor(Quantity_NOC_GOLD);fillArea->SetBackInteriorColor(Quantity_NOC_GOLD);//fillArea->ChangeFrontMaterial().SetMaterialName(Graphic3d_NOM_NEON_GNC);fillArea->ChangeFrontMaterial().SetTransparency(0.4f);fillArea->ChangeBackMaterial().SetMaterialName(Graphic3d_NOM_NEON_GNC);fillArea->ChangeBackMaterial().SetTransparency(0.4f);
selDrawer->UnFreeBoundaryAspect()->SetWidth(1.0);
// Update AIS context.context->SetHighlightStyle(Prs3d_TypeOfHighlight_LocalSelected, selDrawer);}
}
//-----------------------------------------------------------------------------
Viewer::Viewer(const int left,const int top,const int width,const int height): m_hWnd(NULL),m_bQuit(false)
{// Register the window class oncestatic HINSTANCE APP_INSTANCE = NULL;if (APP_INSTANCE == NULL){APP_INSTANCE = GetModuleHandleW(NULL);m_hInstance = APP_INSTANCE;
WNDCLASSW WC;WC.cbClsExtra = 0;WC.cbWndExtra = 0;WC.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);WC.hCursor = LoadCursor(NULL, IDC_ARROW);WC.hIcon = LoadIcon(NULL, IDI_APPLICATION);WC.hInstance = APP_INSTANCE;WC.lpfnWndProc = (WNDPROC)wndProcProxy;WC.lpszClassName = L"OpenGLClass";WC.lpszMenuName = 0;WC.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
if (!RegisterClassW(&WC)){return;}}
// Set coordinates for window's area rectangle.RECT Rect;SetRect(&Rect,left, top,left + width, top + height);
// Adjust window rectangle.AdjustWindowRect(&Rect, WS_OVERLAPPEDWINDOW, false);
// Create window.m_hWnd = CreateWindow(L"OpenGLClass",L"Quaoar >>> 3D",WS_OVERLAPPEDWINDOW,Rect.left, Rect.top, // Adjusted x, y positionsRect.right - Rect.left, Rect.bottom - Rect.top, // Adjusted width and heightNULL, NULL,m_hInstance,this);
// Check if window has been created successfully.if (m_hWnd == NULL){return;}
// Show window finally.ShowWindow(m_hWnd, TRUE);
HANDLE windowHandle = (HANDLE)m_hWnd;
this->init(windowHandle);
}
//-----------------------------------------------------------------------------
void Viewer::AddShape(const TopoDS_Shape& shape)
{m_shapes.push_back(shape);
}
//-----------------------------------------------------------------------------
//! Starts message loop.
void Viewer::StartMessageLoop()
{for (auto sh : m_shapes){Handle(AIS_Shape) shape = new AIS_Shape(sh);m_context->Display(shape, true);m_context->SetDisplayMode(shape, AIS_Shaded, true);
// Adjust selection style.::AdjustSelectionStyle(m_context);
// Activate selection modes.m_context->Activate(4, true); // facesm_context->Activate(2, true); // edges}
MSG Msg;while (!m_bQuit){switch (::MsgWaitForMultipleObjectsEx(0, NULL, 12, QS_ALLINPUT, 0)){case WAIT_OBJECT_0:{while (::PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)){if (Msg.message == WM_QUIT)m_bQuit = true;// return;
::TranslateMessage(&Msg);::DispatchMessage(&Msg);}}}}
}
//-----------------------------------------------------------------------------
void Viewer::init(const HANDLE& windowHandle)
{static Handle(Aspect_DisplayConnection) displayConnection;//if (displayConnection.IsNull())displayConnection = new Aspect_DisplayConnection();
HWND winHandle = (HWND)windowHandle;//if (winHandle == NULL)return;
// Create OCCT viewer.Handle(OpenGl_GraphicDriver)graphicDriver = new OpenGl_GraphicDriver(displayConnection, false);
m_viewer = new V3d_Viewer(graphicDriver);
// Lightning.Handle(V3d_DirectionalLight) LightDir = new V3d_DirectionalLight(V3d_Zneg, Quantity_Color(Quantity_NOC_GRAY97), 1);Handle(V3d_AmbientLight) LightAmb = new V3d_AmbientLight();//LightDir->SetDirection(1.0, -2.0, -10.0);//m_viewer->AddLight(LightDir);m_viewer->AddLight(LightAmb);m_viewer->SetLightOn(LightDir);m_viewer->SetLightOn(LightAmb);
// AIS context.m_context = new AIS_InteractiveContext(m_viewer);
// Configure some global props.const Handle(Prs3d_Drawer)& contextDrawer = m_context->DefaultDrawer();//if (!contextDrawer.IsNull()){const Handle(Prs3d_ShadingAspect)& SA = contextDrawer->ShadingAspect();const Handle(Graphic3d_AspectFillArea3d)& FA = SA->Aspect();contextDrawer->SetFaceBoundaryDraw(true); // Draw edges.FA->SetEdgeOff();
// Fix for inifinite lines has been reduced to 1000 from its default value 500000.contextDrawer->SetMaximalParameterValue(1000);}
// Main view creation.m_view = m_viewer->CreateView();m_view->SetImmediateUpdate(false);
// Event manager is constructed when both contex and view become available.m_evtMgr = new ViewerInteractor(m_view, m_context);
// Aspect window creationm_wntWindow = new WNT_Window(winHandle);m_view->SetWindow(m_wntWindow, nullptr);//if (!m_wntWindow->IsMapped()){m_wntWindow->Map();}m_view->MustBeResized();
// View settings.m_view->SetShadingModel(V3d_PHONG);
// Configure rendering parametersGraphic3d_RenderingParams& RenderParams = m_view->ChangeRenderingParams();RenderParams.IsAntialiasingEnabled = true;RenderParams.NbMsaaSamples = 8; // Anti-aliasing by multi-samplingRenderParams.IsShadowEnabled = false;RenderParams.CollectedStats = Graphic3d_RenderingParams::PerfCounters_NONE;
}
//-----------------------------------------------------------------------------
LRESULT WINAPI Viewer::wndProcProxy(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{if (message == WM_CREATE){// Save pointer to our class instance (sent on window create) to window storage.CREATESTRUCTW* pCreateStruct = (CREATESTRUCTW*)lparam;SetWindowLongPtr(hwnd, int(GWLP_USERDATA), (LONG_PTR)pCreateStruct->lpCreateParams);}
// Get pointer to our class instance.Viewer* pThis = (Viewer*)GetWindowLongPtr(hwnd, int(GWLP_USERDATA));return (pThis != NULL) ? pThis->wndProc(hwnd, message, wparam, lparam): DefWindowProcW(hwnd, message, wparam, lparam);
}
//-----------------------------------------------------------------------------
//! Window procedure.
LRESULT Viewer::wndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{if (m_view.IsNull())return DefWindowProc(hwnd, message, wparam, lparam);
switch (message){case WM_PAINT:{PAINTSTRUCT aPaint;BeginPaint(m_hWnd, &aPaint);EndPaint(m_hWnd, &aPaint);m_evtMgr->ProcessExpose();break;}case WM_SIZE:{m_evtMgr->ProcessConfigure();break;}case WM_MOVE:case WM_MOVING:case WM_SIZING:{switch (m_view->RenderingParams().StereoMode){case Graphic3d_StereoMode_RowInterlaced:case Graphic3d_StereoMode_ColumnInterlaced:case Graphic3d_StereoMode_ChessBoard:{// track window moves to reverse stereo pairm_view->MustBeResized();m_view->Update();break;}default:break;}break;}case WM_KEYUP:case WM_KEYDOWN:{const Aspect_VKey vkey = WNT_Window::VirtualKeyFromNative((int)wparam);//if (vkey != Aspect_VKey_UNKNOWN){const double timeStamp = m_evtMgr->EventTime();if (message == WM_KEYDOWN){m_evtMgr->KeyDown(vkey, timeStamp);}else{m_evtMgr->KeyUp(vkey, timeStamp);}}break;}case WM_LBUTTONUP:case WM_MBUTTONUP:case WM_RBUTTONUP:case WM_LBUTTONDOWN:case WM_MBUTTONDOWN:case WM_RBUTTONDOWN:{const Graphic3d_Vec2i pos(LOWORD(lparam), HIWORD(lparam));const Aspect_VKeyFlags flags = WNT_Window::MouseKeyFlagsFromEvent(wparam);Aspect_VKeyMouse button = Aspect_VKeyMouse_NONE;//switch (message){case WM_LBUTTONUP:case WM_LBUTTONDOWN:button = Aspect_VKeyMouse_LeftButton;break;case WM_MBUTTONUP:case WM_MBUTTONDOWN:button = Aspect_VKeyMouse_MiddleButton;break;case WM_RBUTTONUP:case WM_RBUTTONDOWN:button = Aspect_VKeyMouse_RightButton;break;}if (message == WM_LBUTTONDOWN|| message == WM_MBUTTONDOWN|| message == WM_RBUTTONDOWN){SetFocus(hwnd);SetCapture(hwnd);
if (!m_evtMgr.IsNull())m_evtMgr->PressMouseButton(pos, button, flags, false);}else{ReleaseCapture();
if (!m_evtMgr.IsNull())m_evtMgr->ReleaseMouseButton(pos, button, flags, false);}
m_evtMgr->FlushViewEvents(m_context, m_view, true);break;}case WM_MOUSEWHEEL:{const int delta = GET_WHEEL_DELTA_WPARAM(wparam);const double deltaF = double(delta) / double(WHEEL_DELTA);//const Aspect_VKeyFlags flags = WNT_Window::MouseKeyFlagsFromEvent(wparam);//Graphic3d_Vec2i pos(int(short(LOWORD(lparam))), int(short(HIWORD(lparam))));POINT cursorPnt = { pos.x(), pos.y() };if (ScreenToClient(hwnd, &cursorPnt)){pos.SetValues(cursorPnt.x, cursorPnt.y);}
if (!m_evtMgr.IsNull()){m_evtMgr->UpdateMouseScroll(Aspect_ScrollDelta(pos, deltaF, flags));m_evtMgr->FlushViewEvents(m_context, m_view, true);}break;}case WM_MOUSEMOVE:{Graphic3d_Vec2i pos(LOWORD(lparam), HIWORD(lparam));Aspect_VKeyMouse buttons = WNT_Window::MouseButtonsFromEvent(wparam);Aspect_VKeyFlags flags = WNT_Window::MouseKeyFlagsFromEvent(wparam);
// don't make a slide-show from input events - fetch the actual mouse cursor positionCURSORINFO cursor;cursor.cbSize = sizeof(cursor);if (::GetCursorInfo(&cursor) != FALSE){POINT cursorPnt = { cursor.ptScreenPos.x, cursor.ptScreenPos.y };if (ScreenToClient(hwnd, &cursorPnt)){// as we override mouse position, we need overriding also mouse statepos.SetValues(cursorPnt.x, cursorPnt.y);buttons = WNT_Window::MouseButtonsAsync();flags = WNT_Window::MouseKeyFlagsAsync();}}
if (m_wntWindow.IsNull() || (HWND)m_wntWindow->HWindow() != hwnd){// mouse move events come also for inactive windowsbreak;}
if (!m_evtMgr.IsNull()){m_evtMgr->UpdateMousePosition(pos, buttons, flags, false);m_evtMgr->FlushViewEvents(m_context, m_view, true);}break;}default:{break;}
case WM_DESTROY:m_bQuit = true;}return DefWindowProc(hwnd, message, wparam, lparam);
}
ViewerInteractor.h
#pragma once
// OpenCascade includes
#include <AIS_ViewController.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TCollection_AsciiString.hxx>
class AIS_InteractiveContext;
class V3d_View;
//! Manages input events.
class ViewerInteractor : public Standard_Transient, public AIS_ViewController
{
public:
// OCCT RTTIDEFINE_STANDARD_RTTI_INLINE(ViewerInteractor, Standard_Transient)
public:
//! Ctor.//! \param[in] view the V3d view instance.//! \param[in] ctx the interactive context.ViewerInteractor(const Handle(V3d_View)& view,const Handle(AIS_InteractiveContext)& ctx);
//! Dtor.virtual ~ViewerInteractor();
public:
//! Return interactive context.const Handle(AIS_InteractiveContext)&GetContext() const { return m_ctx; }
//! Handle mouse button press/release event.virtual bool UpdateMouseButtons(const Graphic3d_Vec2i& thePoint,Aspect_VKeyMouse theButtons,Aspect_VKeyFlags theModifiers,bool theIsEmulated) Standard_OVERRIDE;
//! Release key.virtual void KeyDown(Aspect_VKey theKey,double theTime,double thePressure = 1.0) Standard_OVERRIDE;
//! Release key.virtual void KeyUp(Aspect_VKey theKey,double theTime) Standard_OVERRIDE;
//! Redraw the View on an Expose Eventvirtual void ProcessExpose();
//! Handle redraw.virtual void handleViewRedraw(const Handle(AIS_InteractiveContext)& theCtx,const Handle(V3d_View)& theView) Standard_OVERRIDE;
//! Resize View.virtual void ProcessConfigure();
//! Handle KeyPress event.void ProcessKeyPress(Aspect_VKey theKey);
private:
Handle(V3d_View) m_view; //!< 3D view.Handle(AIS_InteractiveContext) m_ctx; //!< Interactive context.
};
ViewerInteractor.cpp
// Own include
#include "ViewerInteractor.h"
// OpenCascade includes
#include <Aspect_Grid.hxx>
#include <AIS_AnimationCamera.hxx>
#include <AIS_InteractiveContext.hxx>
#include <AIS_Shape.hxx>
#include <V3d_View.hxx>
//-----------------------------------------------------------------------------
ViewerInteractor::ViewerInteractor(const Handle(V3d_View)& view,const Handle(AIS_InteractiveContext)& ctx): m_view(view),m_ctx(ctx)
{}
//-----------------------------------------------------------------------------
ViewerInteractor::~ViewerInteractor()
{}
//-----------------------------------------------------------------------------
bool ViewerInteractor::UpdateMouseButtons(const Graphic3d_Vec2i& point,Aspect_VKeyMouse buttons,Aspect_VKeyFlags modifiers,bool isEmulated)
{return AIS_ViewController::UpdateMouseButtons(point, buttons, modifiers, isEmulated);
}
//-----------------------------------------------------------------------------
void ViewerInteractor::ProcessExpose()
{if (!m_view.IsNull()){m_view->Invalidate();FlushViewEvents(m_ctx, m_view, true);}
}
//-----------------------------------------------------------------------------
void ViewerInteractor::handleViewRedraw(const Handle(AIS_InteractiveContext)& ctx,const Handle(V3d_View)& view)
{AIS_ViewController::handleViewRedraw(ctx, view);
}
//-----------------------------------------------------------------------------
void ViewerInteractor::ProcessConfigure()
{if (!m_view.IsNull()){m_view->MustBeResized();FlushViewEvents(m_ctx, m_view, true);}
}
//-----------------------------------------------------------------------------
void ViewerInteractor::KeyDown(Aspect_VKey key,double time,double pressure)
{AIS_ViewController::KeyDown(key, time, pressure);
}
//-----------------------------------------------------------------------------
void ViewerInteractor::KeyUp(Aspect_VKey key,double time)
{const unsigned int modifOld = myKeys.Modifiers();//AIS_ViewController::KeyUp(key, time);//const unsigned int modifNew = myKeys.Modifiers();
ProcessKeyPress(key | modifNew);
}
//-----------------------------------------------------------------------------
void ViewerInteractor::ProcessKeyPress(Aspect_VKey key)
{if (m_ctx.IsNull() || m_view.IsNull()){return;}
switch (key){case Aspect_VKey_F:{if (m_ctx->NbSelected() > 0){m_ctx->FitSelected(m_view);}else{m_view->FitAll();}break;}case Aspect_VKey_S:case Aspect_VKey_W:{const int dm = (key == Aspect_VKey_S) ? AIS_Shaded : AIS_WireFrame;
if (m_ctx->NbSelected() == 0){m_ctx->SetDisplayMode(dm, false);m_ctx->UpdateCurrentViewer();}else{for (m_ctx->InitSelected(); m_ctx->MoreSelected(); m_ctx->NextSelected()){m_ctx->SetDisplayMode(m_ctx->SelectedInteractive(), dm, false);}m_ctx->UpdateCurrentViewer();}break;}case Aspect_VKey_Backspace: // Axonometry.{m_view->SetProj(V3d_XposYnegZpos);m_view->Redraw();break;}case Aspect_VKey_T:{m_view->SetProj(V3d_TypeOfOrientation_Zup_Top);m_view->Redraw();break;}case Aspect_VKey_B:{m_view->SetProj(V3d_TypeOfOrientation_Zup_Bottom);m_view->Redraw();break;}case Aspect_VKey_L:{m_view->SetProj(V3d_TypeOfOrientation_Zup_Left);m_view->Redraw();break;}case Aspect_VKey_R:{m_view->SetProj(V3d_TypeOfOrientation_Zup_Right);m_view->Redraw();break;}default: break;}
}
helloworld.cpp
#include "Viewer.h"
#include <BRepTools.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
int main(int argc, char** argv)
{Viewer vout(50, 50, 500, 500);
vout << BRepPrimAPI_MakeBox(10, 10, 20)<< BRepPrimAPI_MakeBox(20, 30, 10);
if (argc > 1){BRep_Builder bb;TopoDS_Shape fromFile;//if (!BRepTools::Read(fromFile, argv[1], bb)){std::cout << "Failed to read BREP shape from file " << argv[1] << std::endl;return 1;}
vout << fromFile;}
vout.StartMessageLoop();
return 0;
}
2、配置
库文件和头文件同以前
附加依赖项添加以下:
TKernel.lib
TKMath.lib
TKTopAlgo.lib
TKBRep.lib
TKPrim.lib
TKOpenGl.lib
TKService.lib
TKV3d.lib
kernel32.lib
user32.lib
gdi32.lib
winspool.lib
把freetype.lib和freetype.dll拷贝到源码编译后的库文件目录
D:\vs pj\opencascade\3rdparty\freetype-2.5.5-vc14-64
D:\vs pj\opencascade\install\win64\vc14