/*********************************************************************************************************************** * * Copyright (c) 2010 - 2022 by Tech Soft 3D, Inc. * The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret * as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event * of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized * employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the * scope and manner of such use. * ***********************************************************************************************************************/ /** \file UserDefinedViews.cpp This file demonstrates how to programmatically read a model, create customized views and populate buttons in a template to activate the views. ***********************************************************************************************************************/ #define INITIALIZE_A3D_API #define HOOPS_PRODUCT_PUBLISH_STANDARD #include #include "../common.hpp" #include "../CommonInit.h" #define _USE_MATH_DEFINES #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif // default sample arguments: // in visual c++: the current directory is set through properties to $OutDir, which is $(Platform)\$(Configuration) // in linux: the current directory is supposed to be the same as this cpp file #ifdef _MSC_VER # define IN_3DFILE SAMPLES_DATA_DIRECTORY"\\u3d\\BusinessPark.u3d" # define IN_PDFFILE SAMPLES_PUBLISH_QUICKSTARTS_DIRECTORY"\\Templates\\MultiViews\\MultiViews_Letter_P.pdf" # define IN_LOGOIMAGE SAMPLES_DATA_DIRECTORY"\\images\\logo_e_large.jpg" # define OUT_FILE SAMPLES_PUBLISH_GALLERY_DIRECTORY"\\sample_UserDefinedViews.pdf" # define IMAGE_PATH SAMPLES_PUBLISH_GALLERY_DIRECTORY"\\tmpImage.jpg" #else # define IN_3DFILE SAMPLES_DATA_DIRECTORY"/u3d/BusinessPark.u3d" # define IN_PDFFILE SAMPLES_PUBLISH_QUICKSTARTS_DIRECTORY"/Templates/MultiViews/MultiViews_Letter_P.pdf" # define IN_LOGOIMAGE SAMPLES_DATA_DIRECTORY"/images/logo_e_large.jpg" # define OUT_FILE SAMPLES_PUBLISH_GALLERY_DIRECTORY"/sample_UserDefinedViews.pdf" # define IMAGE_PATH SAMPLES_PUBLISH_GALLERY_DIRECTORY"/tmpImage.jpg" #endif //###################################################################################################################### static A3DVector3dData crossProduct(const A3DVector3dData a, const A3DVector3dData b) { A3DVector3dData res; A3D_INITIALIZE_DATA(A3DVector3dData, res); res.m_dX = a.m_dY * b.m_dZ - a.m_dZ * b.m_dY; res.m_dY = a.m_dZ * b.m_dX - a.m_dX * b.m_dZ; res.m_dZ = a.m_dX * b.m_dY - a.m_dY * b.m_dX; return res; } static A3DVector3dData normalize(const A3DVector3dData a) { A3DVector3dData res; A3D_INITIALIZE_DATA(A3DVector3dData, res); double norm = sqrt(a.m_dX * a.m_dX + a.m_dY * a.m_dY + a.m_dZ * a.m_dZ); res.m_dX = a.m_dX / norm; res.m_dY = a.m_dY / norm; res.m_dZ = a.m_dZ / norm; return res; } static void computeUpVector(const A3DVector3dData& sPosition, const A3DVector3dData& sTarget, double dRoll, A3DVector3dData& sUp) { sUp.m_dX = 0; sUp.m_dY = 0; sUp.m_dZ = 1; double dRollRadian = dRoll * M_PI / 180; A3DVector3dData sPlaneNormal, sY; A3D_INITIALIZE_DATA(A3DVector3dData, sPlaneNormal); A3D_INITIALIZE_DATA(A3DVector3dData, sY); sPlaneNormal.m_dX = sTarget.m_dX - sPosition.m_dX; sPlaneNormal.m_dY = sTarget.m_dY - sPosition.m_dY; sPlaneNormal.m_dZ = sTarget.m_dZ - sPosition.m_dZ; A3DVector3dData planeNormalNormalized = normalize(sPlaneNormal); double dot = (planeNormalNormalized.m_dX * sUp.m_dX + planeNormalNormalized.m_dY * sUp.m_dY + planeNormalNormalized.m_dZ * sUp.m_dZ); if (abs(dot) >= 0.9999 && abs(dot) <= 1.0001) { sUp.m_dY = 1; sUp.m_dZ = 0; } sY = crossProduct(sPlaneNormal, sUp); sUp = crossProduct(sY, sPlaneNormal); sUp = normalize(sUp); sY = normalize(sY); double cosroll = cos(dRollRadian), sinroll = sin(dRollRadian); sUp.m_dX = sUp.m_dX * cosroll + sinroll * sY.m_dX; sUp.m_dY = sUp.m_dY * cosroll + sinroll * sY.m_dY; sUp.m_dZ = sUp.m_dZ * cosroll + sinroll * sY.m_dZ; } //###################################################################################################################### // creates a view A3DStatus CreateView(A3DPDFDocument* pDoc, A3DPDF3DArtwork* p3DArtwork, A3DDouble dPosX, A3DDouble dPosY, A3DDouble dPosZ, A3DDouble dTargetX, A3DDouble dTargetY, A3DDouble dTargetZ, A3DDouble dUpX, A3DDouble dUpY, A3DDouble dUpZ, // use vector Up or Roll A3DDouble dRoll,// use vector Up or Roll A3DPDFEProjectionMode eProjectionMode, A3DDouble dZoomFactor, A3DDouble dFieldOfView, A3DBool bIsDefault, const A3DUTF8Char* pcViewName, A3DPDFView** ppView) { A3DStatus iRet = A3D_SUCCESS; A3DPDFViewData sViewData; A3D_INITIALIZE_DATA(A3DPDFViewData, sViewData); sViewData.m_sViewBackgroundColor.m_dBlue = 1.0; sViewData.m_sViewBackgroundColor.m_dGreen = 1.0; sViewData.m_sViewBackgroundColor.m_dRed = 1.0; sViewData.m_eViewLighting = kA3DPDFLightCADOptimized; sViewData.m_eViewRenderingStyle = kA3DPDFRenderingSolid; sViewData.m_sPosition.m_dX = dPosX; sViewData.m_sPosition.m_dY = dPosY; sViewData.m_sPosition.m_dZ = dPosZ; sViewData.m_sTarget.m_dX = dTargetX; sViewData.m_sTarget.m_dY = dTargetY; sViewData.m_sTarget.m_dZ = dTargetZ; if (dRoll!=-1) { // To adjust the camera orientation, Adobe Acrobat is using a roll parameter and HOOPS Publish is using an up vector. // If you want to convert the roll to the up vector, you will need to use the following code or a similar algorithm. computeUpVector(sViewData.m_sPosition, sViewData.m_sTarget, dRoll, sViewData.m_sUpVector); } else { sViewData.m_sUpVector.m_dX = dUpX; sViewData.m_sUpVector.m_dY = dUpY; sViewData.m_sUpVector.m_dZ = dUpZ; } sViewData.m_eProjectionMode = eProjectionMode; sViewData.m_dZoomFactor = dZoomFactor; // only valid for orthographic projection sViewData.m_dFieldOfView = dFieldOfView; // only valid for perspective projection sViewData.m_bIsDefault = bIsDefault; size_t iLen = strlen(pcViewName); sViewData.m_pcExternalName = new A3DUTF8Char[iLen+1]; strcpy(sViewData.m_pcExternalName, pcViewName); CHECK_RET(A3DPDFViewCreate(pDoc, &sViewData, ppView)); delete []sViewData.m_pcExternalName; CHECK_RET(A3DPDF3DArtworkAddView(p3DArtwork, *ppView)); return iRet; } //###################################################################################################################### // creates an image from the given view A3DStatus CreateImageFromView(A3DPDFDocument* pDoc, A3DAsmModelFile* pModelFile, A3DPDFView* pView, A3DInt32 width, A3DInt32 height, const A3DUTF8Char* pcFileName, A3DPDFImage** ppImage) { A3DStatus iRet = A3D_SUCCESS; A3DPDFSnapshotOptionsData sOptionData; A3D_INITIALIZE_DATA(A3DPDFSnapshotOptionsData, sOptionData); sOptionData.m_iWidth = width; sOptionData.m_iHeight = height; sOptionData.m_pView = pView; CHECK_RET (A3DPDFMakeSnapshotFromModelFile(pModelFile, &sOptionData, pcFileName)); CHECK_RET(A3DPDFImageCreateFromFile(pDoc, pcFileName, kA3DPDFImageFormatUnknown, ppImage)); return iRet; } A3DStatus BuildPDFDocument() { A3DStatus iRet = A3D_SUCCESS; // create empty document A3DPDFDocument* pDoc = NULL; CHECK_RET(A3DPDFDocumentCreateEmpty(&pDoc)); if(pDoc != NULL) { // insert page from a template file A3DPDFPage* pPage = NULL; // the false booelan keeps the same field names CHECK_RET(A3DPDFDocumentAppendPageFromPDFFileEx(pDoc, IN_PDFFILE, false, &pPage)); if(pPage != NULL) { // reading the U3D file; the file can be disposed of afterwards. A3DPDF3DStream* pStream; A3DAsmModelFile* pModelFile; A3DRWParamsLoadData sReadParam; A3D_INITIALIZE_DATA(A3DRWParamsLoadData, sReadParam); sReadParam.m_sGeneral.m_bReadSolids = true; sReadParam.m_sGeneral.m_bReadSurfaces = true; sReadParam.m_sGeneral.m_bReadWireframes = true; sReadParam.m_sGeneral.m_bReadPmis = true; sReadParam.m_sGeneral.m_bReadAttributes = true; sReadParam.m_sGeneral.m_bReadHiddenObjects = false; sReadParam.m_sGeneral.m_bReadConstructionAndReferences = false; sReadParam.m_sGeneral.m_bReadActiveFilter = true; sReadParam.m_sGeneral.m_eReadingMode2D3D = kA3DRead_3D; sReadParam.m_sGeneral.m_eReadGeomTessMode = kA3DReadGeomAndTess; sReadParam.m_sGeneral.m_eDefaultUnit = kA3DUnitUnknown; sReadParam.m_sPmi.m_bAlwaysSubstituteFont = false; sReadParam.m_sPmi.m_pcSubstitutionFont = const_cast("Myriad CAD"); sReadParam.m_sTessellation.m_eTessellationLevelOfDetail = kA3DTessLODMedium; sReadParam.m_sMultiEntries.m_bLoadDefault = true; sReadParam.m_sAssembly.m_bUseRootDirectory = true; CHECK_RET(A3DAsmModelFileLoadFromFile(IN_3DFILE, &sReadParam, &pModelFile)); if(pModelFile) { // creating the PRC stream from the model file that is going to be inserted into the PDF file A3DRWParamsExportPrcData sParamsExportData; A3D_INITIALIZE_DATA(A3DRWParamsExportPrcData, sParamsExportData); CHECK_RET(A3DPDF3DStreamCreateFromModelFileAsPRC(pDoc, pModelFile, &sParamsExportData, &pStream, NULL)); // creating the 3D artwork A3DPDF3DArtwork* p3DArtwork; A3DPDF3DArtworkData2 s3DArtworkData; A3D_INITIALIZE_DATA(A3DPDF3DArtworkData2, s3DArtworkData); s3DArtworkData.m_pStream = pStream; s3DArtworkData.m_sDisplaySectionData.m_bAddSectionCaps = true; CHECK_RET(A3DPDF3DArtworkCreate2(pDoc, &s3DArtworkData, &p3DArtwork)); // creating the views A3DPDFView* pViewDef; A3DPDFView* pViews[4]; memset(pViews,0,4*sizeof(A3DPDFView*)); A3DUTF8Char viewnameDef[] = "Default"; const A3DUTF8Char* viewnames[4] = { "CentralPlaza", "MainConcourse","AtriumEntrances", "AtriumSuites" }; // Default view: no button for this default view CHECK_RET(CreateView(pDoc, p3DArtwork, 124477.98, -312144.59, 165563.81, // camera position -941.98, -41635.68, 21990.5, // target position 0,0,0, // up vector unused - roll is used instead 0.45, // roll kA3DPDFPerspectiveMode, 0, 30, true, viewnameDef, &pViewDef)); // Central Plaza View: CHECK_RET(CreateView(pDoc, p3DArtwork, 36694.61, 107771.03, 26664.91, // camera position -15212.11, 18814.32, 248.49, // target position 0,0,0, // up vector unused - roll is used instead 0.09, // roll kA3DPDFPerspectiveMode, 0, 30, false, viewnames[0], &pViews[0])); // Main Concourse View: CHECK_RET(CreateView(pDoc, p3DArtwork, -96399.6, 83192.08, 24110.6, // camera position -15211.6, 18813.98, 248.48, // target position 0,0,0, // up vector unused - roll is used instead -0.08, // roll kA3DPDFPerspectiveMode, 0, 30, false, viewnames[1], &pViews[1])); // Atrium Entrances View: CHECK_RET(CreateView(pDoc, p3DArtwork, -79315.65, -57782.11, 36705.41, // camera position -15211.91, 18814.48, 248.53, // target position 0,0,0, // up vector unused - roll is used instead -0.01, // roll kA3DPDFPerspectiveMode, 0, 30, false, viewnames[2], &pViews[2])); // Atrium Suites View: CHECK_RET(CreateView(pDoc, p3DArtwork, -67051.41, -41219.01, 9748.84, // camera position -15211.92, 18814.26, 248.62, // target position 0,0,0, // up vector unused - roll is used instead 0.02, // roll kA3DPDFPerspectiveMode, 0, 30, false, viewnames[3], &pViews[3])); // creating the 3D annotation A3DPDF3DAnnotData sAnnotData; A3D_INITIALIZE_DATA(A3DPDF3DAnnotData, sAnnotData); sAnnotData.m_bOpenModelTree = false; sAnnotData.m_bShowToolbar = false; // In this example, the default view is a Publish view and defines all the display settings. // This makes the following display settings not active: //sAnnotData.m_eLighting = kA3DPDFLightHeadlamp; //sAnnotData.m_eRenderingStyle = kA3DPDFRenderingSolid; //sAnnotData.m_sBackgroundColor.m_dRed = 0.5; //sAnnotData.m_sBackgroundColor.m_dGreen = 0.5; //sAnnotData.m_sBackgroundColor.m_dBlue = 0.5; sAnnotData.m_bTransparentBackground = false; sAnnotData.m_eActivateWhen = kA3DPDFActivPageOpened; sAnnotData.m_eDesactivateWhen = kA3DPDFActivPageClosed; sAnnotData.m_iAppearanceBorderWidth = 1; sAnnotData.m_pPosterImage = NULL; // default poster automatically generated from the default view sAnnotData.m_p3DArtwork = p3DArtwork; A3DPDF3DAnnot* p3DAnnot = NULL; CHECK_RET(A3DPDF3DAnnotCreate(pDoc, &sAnnotData, &p3DAnnot)); if(p3DAnnot != NULL) { // populating the field with the 3D annotation CHECK_RET(A3DPDFPageFieldSet3DAnnot(pPage, "My3DWindow", p3DAnnot)); // populating the buttons with images and actions to set views // buttons name in template PDF file A3DPDFButton* pButtons[4]; memset(pButtons,0,4*sizeof(A3DPDFButton*)); const A3DUTF8Char* buttons[4] = { "Button1", "Button2", "Button3", "Button4" }; // To set actions on buttons // this is common to all SetView actions A3DPDFAction* pAction = NULL; A3DPDFActionSetViewData sActionData; A3D_INITIALIZE_DATA(A3DPDFActionSetViewData, sActionData); sActionData.m_p3DAnnot = p3DAnnot; sActionData.m_bAnimate = false; for (int i=0; i<4; i++) { A3DPDFPageGetField(pPage, buttons[i], &pButtons[i]); if (pButtons[i]) { // To create the views thumbnails A3DPDFImage* pImageView = NULL; const A3DUTF8Char* tmpImage = IMAGE_PATH; unsigned int thumbnail_w = 522, thumbnail_h = 361; // create and set icon on button iRet = CreateImageFromView(pDoc, pModelFile, pViews[i], thumbnail_w, thumbnail_h, tmpImage, &pImageView); if (iRet == A3D_SUCCESS) { CHECK_RET(A3DPDFButtonSetIcon(pButtons[i], pImageView)); remove(tmpImage); } // set action on button sActionData.m_iViewIndex = 0; sActionData.m_pcViewName = const_cast(viewnames[i]); CHECK_RET(A3DPDFActionSetViewCreate(&sActionData, &pAction)); CHECK_RET(A3DPDFButtonAddAction(pButtons[i], pAction)); } } // populating the logo box A3DPDFButton* pButLogo = NULL; A3DPDFPageGetField(pPage, "Thumbnail", &pButLogo); if (pButLogo) { A3DPDFImage* pImage = NULL; CHECK_RET(A3DPDFImageCreateFromFile(pDoc, IN_LOGOIMAGE, kA3DPDFImageFormatUnknown, &pImage)); CHECK_RET(A3DPDFButtonSetIcon(pButLogo, pImage)); } // populating the DocumentTitle text A3DPDFTextField* pTextDocumentTitle = NULL; A3DPDFPageGetField(pPage, "DocumentTitle", &pTextDocumentTitle); if (pTextDocumentTitle) CHECK_RET(A3DPDFTextFieldSetValue(pTextDocumentTitle, "Slattery Business Park")); // populating the DocumentSubHead text A3DPDFTextField* pTextDocumentSubHead = NULL; A3DPDFPageGetField(pPage, "DocumentSubHead", &pTextDocumentSubHead); if (pTextDocumentSubHead) CHECK_RET(A3DPDFTextFieldSetValue(pTextDocumentSubHead, "Dublin, Ireland")); // populating the summary text A3DPDFTextField* pTextSummary = NULL; A3DPDFPageGetField(pPage, "SummaryText", &pTextSummary); if (pTextSummary) CHECK_RET(A3DPDFTextFieldSetValue(pTextSummary, "Suspendisse potenti. " "Suspendisse fringilla lobortis volutpat. " "Etiam venenatis risus lobortis lorem mollis nec cursus diam dictum. " "Aenean mollis tempor massa id sollicitudin. Phasellus laoreet posuere leo eu rhoncus. " "Etiam sit amet elit leo, hendrerit bibendum magna. " "Aenean lacinia ligula sed mi fermentum consectetur. Morbi arcu metus, " "tempus adipiscing condimentum nec, vestibulum eu lectus. " "Fusce eget elit in eros eleifend iaculis. Duis neque lacus, adipiscing vel porta eget, " "congue vel urna. Aenean malesuada lacus in odio interdum aliquam. " "Aliquam aliquet lectus eget ligula luctus vitae porta neque commodo.")); // populating the AdditionalText A3DPDFTextField* pTextAdditionalText = NULL; A3DPDFPageGetField(pPage, "AdditionalText", &pTextAdditionalText); if (pTextAdditionalText) CHECK_RET(A3DPDFTextFieldSetValue(pTextAdditionalText, "Vestibulum vitae eros lorem. " "Curabitur pharetra magna quis diam interdum consectetur. " "Ut cursus pulvinar massa, nec accumsan ipsum gravida vitae.")); } // cleaning up -- WARNING: DO NOT CALL THIS BEFORE A3DPDF3DArtworkCreate! CHECK_RET(A3DAsmModelFileDelete(pModelFile)); // saving the document CHECK_RET(A3DPDFDocumentSaveEx(pDoc, kA3DPDFSaveFull|kA3DPDFSaveOptimized, OUT_FILE)); CHECK_RET(A3DPDFDocumentClose(pDoc)); } } } return iRet; } //###################################################################################################################### // Main function #ifdef _MSC_VER int wmain(A3DInt32, A3DUniChar**) #else int main(int, A3DUTF8Char**) #endif { #ifndef _MSC_VER setenv("LC_NUMERIC", "en_US.UTF-8", 1); // Locally force locale #endif // init A3DLIB library - automatically handled init/terminate A3DSDKHOOPSPublishLoader sHoopsPublishLoader(_T(HOOPS_BINARY_DIRECTORY)); CHECK_RET(sHoopsPublishLoader.m_eSDKStatus); A3DDllSetCallbacksMemory(CheckMalloc, CheckFree); // init HOOPS Publish related PDF library - automatically handled init/terminate // do it only only once during the life of the application CHECK_RET(sHoopsPublishLoader.InitPDFLib()); // launch PDF treatment A3DStatus iRet = BuildPDFDocument(); if (iRet != A3D_SUCCESS) return iRet; // Check memory allocations return (int)ListLeaks(); }