HoloLens: First cut, optimization of array data communication to sharing server. ResInsight will try and detect changes in its internal arrays, and will only announce changed arrays to the server (through meta data.) Previously, ResInsight would send all array data to the server unconditionally. Now the set of arrays/packets to send is controlled by the sharing server through its response to a post of new meta data.

This commit is contained in:
sigurdp 2018-12-19 12:31:44 +01:00
parent f8a0a0e8bb
commit 928a0628cd
14 changed files with 12836 additions and 129 deletions

View File

@ -15,6 +15,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicHoloLensSessionManager.h
${CMAKE_CURRENT_LIST_DIR}/RicHoloLensCreateDummyFileBackedSessionFeature.h
${CMAKE_CURRENT_LIST_DIR}/VdeArrayDataPacket.h
${CMAKE_CURRENT_LIST_DIR}/VdeCachingHashedIdFactory.h
${CMAKE_CURRENT_LIST_DIR}/VdeExportPart.h
${CMAKE_CURRENT_LIST_DIR}/VdeFileExporter.h
${CMAKE_CURRENT_LIST_DIR}/VdePacketDirectory.h
@ -36,6 +37,7 @@ ${CMAKE_CURRENT_LIST_DIR}/RicHoloLensSessionManager.cpp
${CMAKE_CURRENT_LIST_DIR}/RicHoloLensCreateDummyFileBackedSessionFeature.cpp
${CMAKE_CURRENT_LIST_DIR}/VdeArrayDataPacket.cpp
${CMAKE_CURRENT_LIST_DIR}/VdeCachingHashedIdFactory.cpp
${CMAKE_CURRENT_LIST_DIR}/VdeExportPart.cpp
${CMAKE_CURRENT_LIST_DIR}/VdeFileExporter.cpp
${CMAKE_CURRENT_LIST_DIR}/VdePacketDirectory.cpp

View File

@ -28,9 +28,12 @@
#include "VdeArrayDataPacket.h"
#include "cvfAssert.h"
#include "cvfTimer.h"
#include <QDir>
#include <algorithm>
//==================================================================================================
//
@ -129,18 +132,23 @@ void RicHoloLensSession::updateSessionDataFromView(const RimGridView& activeView
{
RiaLogging::info("HoloLens: Updating visualization data");
// Note
// Currently we clear the packet directory each time we update the visualization data
// This means we do no caching of actual packet data and we assume that the server will ask for data
// packets/arrays right after having received updated meta data
m_packetDirectory.clear();
// Grab the current max ID as an easy way to detect if new IDs have been added for debugging purposes
const int dbgMaxAssignedIdBeforeExtraction = m_cachingIdFactory.lastAssignedId();
VdeVizDataExtractor extractor(activeView);
// Note that we pass the caching ID factory on the constructor which will try and detect data payloads that
// are equal, and will then "recycle" the array IDs for these
VdeVizDataExtractor extractor(activeView, &m_cachingIdFactory);
QString modelMetaJsonStr;
std::vector<int> allReferencedPacketIds;
extractor.extractViewContents(&modelMetaJsonStr, &allReferencedPacketIds, &m_packetDirectory);
// Note!
// The packet directory should now contain all the packets that are being actively referenced.
// We now prune out any packets that are no longer being referenced. This means we do no caching of actual packet
// data over time and that we assume that the server will ask for data packets/arrays right after having received updated meta data
m_packetDirectory.pruneUnreferencedPackets(allReferencedPacketIds);
m_lastExtractionMetaDataSequenceNumber++;
m_lastExtractionAllReferencedPacketIdsArr = allReferencedPacketIds;
@ -171,9 +179,23 @@ void RicHoloLensSession::updateSessionDataFromView(const RimGridView& activeView
return;
}
RiaLogging::info(QString("HoloLens: Doing debug export of data to folder: %1").arg(absOutputFolder));
// For debugging, write only the new packets to file
// Determine which packets are new by comparing the IDs to the max known ID before extraction
std::vector<int> packetIdsToWrite;
for (int packetId : allReferencedPacketIds)
{
if (packetId > dbgMaxAssignedIdBeforeExtraction)
{
packetIdsToWrite.push_back(packetId);
}
}
// This will write all packets seen in this extraction to file
//packetIdsToWrite = allReferencedPacketIds;
RiaLogging::info(QString("HoloLens: Doing debug export of data (%1 packets) to folder: %2").arg(packetIdsToWrite.size()).arg(absOutputFolder));
VdeFileExporter fileExporter(absOutputFolder);
if (!fileExporter.exportToFile(modelMetaJsonStr, m_packetDirectory, allReferencedPacketIds))
if (!fileExporter.exportToFile(modelMetaJsonStr, m_packetDirectory, packetIdsToWrite))
{
RiaLogging::error("HoloLens: Error exporting debug data to folder");
}
@ -207,29 +229,135 @@ void RicHoloLensSession::handleFailedCreateSession()
//--------------------------------------------------------------------------------------------------
/// Handle the server response we receive after sending new meta data
//--------------------------------------------------------------------------------------------------
void RicHoloLensSession::handleSuccessfulSendMetaData(int metaDataSequenceNumber, const QByteArray& /*jsonServerResponseString*/)
void RicHoloLensSession::handleSuccessfulSendMetaData(int metaDataSequenceNumber, const QByteArray& jsonServerResponseString)
{
RiaLogging::info(QString("HoloLens: Processing server response to meta data (sequenceNumber=%1)").arg(metaDataSequenceNumber));
cvf::Timer tim;
RiaLogging::info(QString("HoloLens: Processing server response (meta data sequenceNumber=%1)").arg(metaDataSequenceNumber));
if (m_lastExtractionMetaDataSequenceNumber != metaDataSequenceNumber)
{
RiaLogging::warning(QString("HoloLens: Ignoring server response, the sequenceNumber(%1) has been superseded").arg(metaDataSequenceNumber));
RiaLogging::warning(QString("HoloLens: Ignoring server response, the meta data sequenceNumber(%1) has been superseded").arg(metaDataSequenceNumber));
return;
}
if (m_lastExtractionAllReferencedPacketIdsArr.size() > 0)
std::vector<int> arrayIdsToSend;
//cvf::Trace::show("Raw JSON response from server: '%s'", jsonServerResponseString.data());
QByteArray trimmedServerResponseString = jsonServerResponseString.trimmed();
if (trimmedServerResponseString.size() > 0)
{
if (!parseJsonIntegerArray(trimmedServerResponseString, &arrayIdsToSend))
{
RiaLogging::error("HoloLens: Error parsing array server response with array Ids, no data will be sent to server");
return;
}
}
else
{
// An empty server response means we should send all array referenced by the last sent meta data
if (m_lastExtractionAllReferencedPacketIdsArr.size() > 0)
{
arrayIdsToSend = m_lastExtractionAllReferencedPacketIdsArr;
RiaLogging::info("HoloLens: Empty server response, sending all arrays referenced by last meta data");
}
}
if (arrayIdsToSend.size() ==0)
{
RiaLogging::info("HoloLens: Nothing to do, no data requested by server");
return;
}
RiaLogging::info(QString("HoloLens: Start sending data to server, %1 data arrays have been requested").arg(arrayIdsToSend.size()));
size_t totalBytesSent = 0;
size_t totalNumArraysSent = 0;
const bool sendAsIndividualPackets = false;
// Sending data packets one by one
if (sendAsIndividualPackets)
{
for (size_t i = 0; i < arrayIdsToSend.size(); i++)
{
const int arrayId = arrayIdsToSend[i];
const VdeArrayDataPacket* packet = m_packetDirectory.lookupPacket(arrayId);
if (!packet)
{
RiaLogging::warning(QString("HoloLens: Could not get the requested data from cache, array id: %1 ").arg(arrayId));
continue;
}
QByteArray packetByteArr(packet->fullPacketRawPtr(), static_cast<int>(packet->fullPacketSize()));
RiaLogging::info(QString("HoloLens: sending array id: %1, %2KB (%3 bytes)").arg(arrayId).arg(packetByteArr.size()/1024.0, 0, 'f', 2).arg(packetByteArr.size()));
m_restClient->sendBinaryData(packetByteArr);
totalNumArraysSent++;
totalBytesSent += packetByteArr.size();
}
}
// Sending all requested arrays/packets in one combined packet
else
{
QByteArray combinedPacketArr;
if (!m_packetDirectory.getPacketsAsCombinedBuffer(m_lastExtractionAllReferencedPacketIdsArr, &combinedPacketArr))
if (!m_packetDirectory.getPacketsAsCombinedBuffer(arrayIdsToSend, &combinedPacketArr))
{
RiaLogging::warning("HoloLens: Error gathering the requested packets, no data will be sent");
RiaLogging::warning("HoloLens: Error gathering the requested arrays, no data will be sent");
return;
}
RiaLogging::info(QString("HoloLens: Sending new data to sharing server (%1 packets)").arg(m_lastExtractionAllReferencedPacketIdsArr.size()));
totalNumArraysSent = arrayIdsToSend.size();
totalBytesSent = combinedPacketArr.size();
RiaLogging::info(QString("HoloLens: Sending data to server (%1 arrays combined), %2KB (%3 bytes)").arg(totalNumArraysSent).arg(totalBytesSent/1024.0, 0, 'f', 2).arg(totalBytesSent));
m_restClient->sendBinaryData(combinedPacketArr);
}
const double totalMb = totalBytesSent/(1024.0*1024.0);
RiaLogging::info(QString("HoloLens: Finished sending data to server, %1 arrays, total %2MB (%3 bytes) in %4ms").arg(totalNumArraysSent).arg(totalMb, 0, 'f', 2).arg(totalBytesSent).arg(static_cast<int>(tim.time()*1000)));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool RicHoloLensSession::parseJsonIntegerArray(const QByteArray& jsonString, std::vector<int>* integerArr)
{
//cvf::Trace::show("jsonString: '%s'", jsonString.data());
const int openBraceIdx = jsonString.indexOf('[');
const int closeBraceIdx = jsonString.lastIndexOf(']');
if (openBraceIdx < 0 || closeBraceIdx < 0)
{
RiaLogging::debug("Error parsing JSON array, could not find opening or closing braces");
return false;
}
if (closeBraceIdx <= openBraceIdx)
{
RiaLogging::debug("Error parsing JSON array, wrong placement of braces");
return false;
}
QByteArray arrayContents = jsonString.mid(openBraceIdx + 1, closeBraceIdx - openBraceIdx - 1).trimmed();
//cvf::Trace::show("arrayContents: '%s'", arrayContents.data());
QList<QByteArray> stringList = arrayContents.split(',');
for (const QByteArray& entry : stringList)
{
bool convertOk = false;
const int intVal = entry.toInt(&convertOk);
if (convertOk)
{
integerArr->push_back(intVal);
}
}
return true;
}
//--------------------------------------------------------------------------------------------------

View File

@ -22,6 +22,7 @@
#include "RicHoloLensRestClient.h"
#include "VdePacketDirectory.h"
#include "VdeCachingHashedIdFactory.h"
#include <QString>
#include <QPointer>
@ -57,6 +58,8 @@ private:
virtual void handleSuccessfulSendMetaData(int metaDataSequenceNumber, const QByteArray& jsonServerResponseString) override;
virtual void handleError(const QString& errMsg, const QString& url, const QString& serverData) override;
static bool parseJsonIntegerArray(const QByteArray& jsonString, std::vector<int>* integerArr);
void notifyObserver(RicHoloLensSessionObserver::Notification notification);
private:
@ -65,6 +68,7 @@ private:
int m_lastExtractionMetaDataSequenceNumber;
std::vector<int> m_lastExtractionAllReferencedPacketIdsArr;
VdeCachingHashedIdFactory m_cachingIdFactory;
VdePacketDirectory m_packetDirectory;
RicHoloLensSessionObserver* m_sessionObserver;

View File

@ -178,40 +178,40 @@ unsigned char VdeArrayDataPacket::imageComponentCount() const
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
VdeArrayDataPacket VdeArrayDataPacket::fromFloat32Arr(int arrayId, const float* srcArr, size_t srcArrElementCount)
std::unique_ptr<VdeArrayDataPacket> VdeArrayDataPacket::fromFloat32Arr(int arrayId, const float* srcArr, size_t srcArrElementCount)
{
size_t payloadByteCount = srcArrElementCount*sizeof(float);
const char* rawSrcPtr = reinterpret_cast<const char*>(srcArr);
VdeArrayDataPacket packet;
packet.assign(arrayId, Float32, srcArrElementCount, 0, 0, 0, rawSrcPtr, payloadByteCount);
std::unique_ptr<VdeArrayDataPacket> packet(new VdeArrayDataPacket);
packet->assign(arrayId, Float32, srcArrElementCount, 0, 0, 0, rawSrcPtr, payloadByteCount);
return packet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
VdeArrayDataPacket VdeArrayDataPacket::fromUint32Arr(int arrayId, const unsigned int* srcArr, size_t srcArrElementCount)
std::unique_ptr<VdeArrayDataPacket> VdeArrayDataPacket::fromUint32Arr(int arrayId, const unsigned int* srcArr, size_t srcArrElementCount)
{
size_t payloadByteCount = srcArrElementCount*sizeof(unsigned int);
const char* rawSrcPtr = reinterpret_cast<const char*>(srcArr);
VdeArrayDataPacket packet;
packet.assign(arrayId, Uint32, srcArrElementCount, 0, 0, 0, rawSrcPtr, payloadByteCount);
std::unique_ptr<VdeArrayDataPacket> packet(new VdeArrayDataPacket);
packet->assign(arrayId, Uint32, srcArrElementCount, 0, 0, 0, rawSrcPtr, payloadByteCount);
return packet;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
VdeArrayDataPacket VdeArrayDataPacket::fromUint8ImageRGBArr(int arrayId, unsigned short imageWidth, unsigned short imageHeight, const unsigned char* srcArr, size_t srcArrElementCount)
std::unique_ptr<VdeArrayDataPacket> VdeArrayDataPacket::fromUint8ImageRGBArr(int arrayId, unsigned short imageWidth, unsigned short imageHeight, const unsigned char* srcArr, size_t srcArrElementCount)
{
const char* rawSrcPtr = reinterpret_cast<const char*>(srcArr);
assert(3*imageWidth*imageHeight == srcArrElementCount);
VdeArrayDataPacket packet;
packet.assign(arrayId, Uint8, srcArrElementCount, imageWidth, imageHeight, 3, rawSrcPtr, srcArrElementCount);
std::unique_ptr<VdeArrayDataPacket> packet(new VdeArrayDataPacket);
packet->assign(arrayId, Uint8, srcArrElementCount, imageWidth, imageHeight, 3, rawSrcPtr, srcArrElementCount);
return packet;
}

View File

@ -21,6 +21,7 @@
#include <cstddef>
#include <vector>
#include <string>
#include <memory>
//==================================================================================================
@ -42,26 +43,26 @@ public:
public:
VdeArrayDataPacket();
bool isValid() const;
int arrayId() const;
bool isValid() const;
int arrayId() const;
ElementType elementType() const;
size_t elementSize() const;
size_t elementCount() const;
const char* arrayData() const;
ElementType elementType() const;
size_t elementSize() const;
size_t elementCount() const;
const char* arrayData() const;
unsigned short imageWidth() const;
unsigned short imageHeight() const;
unsigned char imageComponentCount() const;
unsigned short imageWidth() const;
unsigned short imageHeight() const;
unsigned char imageComponentCount() const;
size_t fullPacketSize() const;
const char* fullPacketRawPtr() const;
size_t fullPacketSize() const;
const char* fullPacketRawPtr() const;
static VdeArrayDataPacket fromFloat32Arr(int arrayId, const float* srcArr, size_t srcArrElementCount);
static VdeArrayDataPacket fromUint32Arr(int arrayId, const unsigned int* srcArr, size_t srcArrElementCount);
static VdeArrayDataPacket fromUint8ImageRGBArr(int arrayId, unsigned short imageWidth, unsigned short imageHeight, const unsigned char* srcArr, size_t srcArrElementCount);
static std::unique_ptr<VdeArrayDataPacket> fromFloat32Arr(int arrayId, const float* srcArr, size_t srcArrElementCount);
static std::unique_ptr<VdeArrayDataPacket> fromUint32Arr(int arrayId, const unsigned int* srcArr, size_t srcArrElementCount);
static std::unique_ptr<VdeArrayDataPacket> fromUint8ImageRGBArr(int arrayId, unsigned short imageWidth, unsigned short imageHeight, const unsigned char* srcArr, size_t srcArrElementCount);
static VdeArrayDataPacket fromRawPacketBuffer(const char* rawPacketBuffer, size_t bufferSize, std::string* errString);
static VdeArrayDataPacket fromRawPacketBuffer(const char* rawPacketBuffer, size_t bufferSize, std::string* errString);
private:
bool assign(int arrayId, ElementType elementType, size_t elementCount, unsigned short imageWidth, unsigned short imageHeight, unsigned char imageCompCount, const char* arrayDataPtr, size_t arrayDataSizeInBytes);

View File

@ -0,0 +1,257 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018 Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#include "VdeCachingHashedIdFactory.h"
#define FARMHASH_NO_BUILTIN_EXPECT
#define NAMESPACE_FOR_HASH_FUNCTIONS farmhash
#include "farmhash/farmhash.h"
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 4267 4307 4319 4244)
#endif
#include "farmhash/farmhash.cc"
#ifdef _MSC_VER
#pragma warning (pop)
#endif
//==================================================================================================
//
//
//
//==================================================================================================
class Checksum
{
public:
static unsigned int crc(const void* data, size_t numBytes);
};
//==================================================================================================
//
//
//
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool VdeCachingHashedIdFactory::Key::operator<(const Key& other) const
{
if (hashVal != other.hashVal)
{
return hashVal < other.hashVal;
}
else if (role != other.role)
{
return role < other.role;
}
else if (elementType != other.elementType)
{
return elementType < other.elementType;
}
else
{
return elementCount < other.elementCount;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
VdeCachingHashedIdFactory::VdeCachingHashedIdFactory()
: m_lastUsedId(-1)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int VdeCachingHashedIdFactory::getOrCreateIdForFloatArr(ArrayRole arrayRole, const void* floatArr, size_t elementCount)
{
return getOrCreateIdForArrOfType(arrayRole, Float32, sizeof(float), floatArr, elementCount);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int VdeCachingHashedIdFactory::getOrCreateIdForUint32Arr(ArrayRole arrayRole, const unsigned int* uint32Arr, size_t elementCount)
{
return getOrCreateIdForArrOfType(arrayRole, Uint32, sizeof(unsigned int), uint32Arr, elementCount);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int VdeCachingHashedIdFactory::getOrCreateIdForUint8Arr(ArrayRole arrayRole, const unsigned char* uint8Arr, size_t elementCount)
{
return getOrCreateIdForArrOfType(arrayRole, Uint8, sizeof(unsigned char), uint8Arr, elementCount);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int VdeCachingHashedIdFactory::lastAssignedId() const
{
return m_lastUsedId;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int VdeCachingHashedIdFactory::getOrCreateIdForArrOfType(ArrayRole arrayRole, ElementType elementType, size_t elementSizeInBytes, const void* data, size_t elementCount)
{
Key key;
key.elementType = elementType;
key.role = arrayRole;
key.elementCount = elementCount;
const size_t arraySizeInBytes = elementCount*elementSizeInBytes;
//key.hashVal = Checksum::crc(data, arraySizeInBytes);
//key.hashVal = farmhash::Hash32(static_cast<const char*>(data), arraySizeInBytes);
//key.hashVal = farmhash::Hash64(static_cast<const char*>(data), arraySizeInBytes);
//key.hashVal = farmhash::Hash128to64(farmhash::Hash128(static_cast<const char*>(data), arraySizeInBytes));
key.hashVal = farmhash::Hash128(static_cast<const char*>(data), arraySizeInBytes);
std::map<Key, int>::iterator it = m_keyToIdMap.find(key);
if (it != m_keyToIdMap.end())
{
return it->second;
}
const int newId = ++m_lastUsedId;
m_keyToIdMap[key] = newId;
return newId;
//const int newId = ++m_lastUsedId;
//return newId;
}
//==================================================================================================
//
// CRC Stuff
//
//==================================================================================================
static const unsigned int crc_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
unsigned int Checksum::crc(const void* data, size_t numBytes)
{
unsigned int sum = 0xffffffff;
const unsigned char* p = reinterpret_cast<const unsigned char*>(data);
// Compute crc
{
unsigned int tbl_idx;
while (numBytes--) {
tbl_idx = (sum ^ *p) & 0xff;
sum = (crc_table[tbl_idx] ^ (sum >> 8)) & 0xffffffff;
p++;
}
sum = sum & 0xffffffff;
}
return sum ^ 0xffffffff;
}

View File

@ -0,0 +1,73 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2018 Statoil ASA
//
// ResInsight is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <map>
//==================================================================================================
//
//
//
//==================================================================================================
class VdeCachingHashedIdFactory
{
public:
enum ArrayRole
{
VertexArr,
ConnArr,
TexImage,
TexCoordsArr
};
public:
VdeCachingHashedIdFactory();
int getOrCreateIdForFloatArr(ArrayRole arrayRole, const void* floatArr, size_t elementCount);
int getOrCreateIdForUint32Arr(ArrayRole arrayRole, const unsigned int* uint32Arr, size_t elementCount);
int getOrCreateIdForUint8Arr(ArrayRole arrayRole, const unsigned char* uint8Arr, size_t elementCount);
int lastAssignedId() const;
private:
enum ElementType
{
Float32,
Uint32,
Uint8,
};
struct Key
{
std::pair<uint64_t, uint64_t> hashVal;
ArrayRole role;
ElementType elementType;
size_t elementCount;
bool operator<(const Key& other) const;
};
private:
int getOrCreateIdForArrOfType(ArrayRole arrayRole, ElementType elementType, size_t elementSizeInBytes, const void* data, size_t elementCount);
private:
std::map<Key, int> m_keyToIdMap;
int m_lastUsedId;
};

View File

@ -19,6 +19,7 @@
#include "VdeFileExporter.h"
#include "VdeArrayDataPacket.h"
#include "VdePacketDirectory.h"
#include "VdeCachingHashedIdFactory.h"
#include "cvfTrace.h"
@ -72,7 +73,7 @@ bool VdeFileExporter::exportToFile(const QString& modelMetaJsonStr, const VdePac
}
}
cvf::Trace::show("Data exported to folder: %s", m_absOutputFolder.toLatin1().constData());
cvf::Trace::show("Data exported (%d packets) to folder: %s", packetIdsToExport.size(), m_absOutputFolder.toLatin1().constData());
return true;
}
@ -82,11 +83,12 @@ bool VdeFileExporter::exportToFile(const QString& modelMetaJsonStr, const VdePac
//--------------------------------------------------------------------------------------------------
bool VdeFileExporter::exportViewContents(const RimGridView& view)
{
VdeCachingHashedIdFactory localIdFactory;
VdeVizDataExtractor extractor(view, &localIdFactory);
QString modelMetaJsonStr;
std::vector<int> allReferencedArrayIds;
VdePacketDirectory packetDirectory;
VdeVizDataExtractor extractor(view);
extractor.extractViewContents(&modelMetaJsonStr, &allReferencedArrayIds, &packetDirectory);
if (!exportToFile(modelMetaJsonStr, packetDirectory, allReferencedArrayIds))

View File

@ -18,6 +18,7 @@
#include "VdePacketDirectory.h"
#include <algorithm>
//==================================================================================================
@ -36,10 +37,10 @@ VdePacketDirectory::VdePacketDirectory()
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void VdePacketDirectory::addPacket(const VdeArrayDataPacket& packet)
void VdePacketDirectory::addPacket(std::unique_ptr<VdeArrayDataPacket> packet)
{
const int id = packet.arrayId();
m_idToPacketMap[id] = std::unique_ptr<VdeArrayDataPacket>(new VdeArrayDataPacket(packet));
const int id = packet->arrayId();
m_idToPacketMap[id] = std::move(packet);
}
//--------------------------------------------------------------------------------------------------
@ -64,6 +65,29 @@ void VdePacketDirectory::clear()
m_idToPacketMap.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void VdePacketDirectory::pruneUnreferencedPackets(const std::vector<int>& packetIdsInUseArr)
{
std::vector<int> sortedPacketsIdsInUse(packetIdsInUseArr);
std::sort(sortedPacketsIdsInUse.begin(), sortedPacketsIdsInUse.end());
IdToPacketMap_T::const_iterator it = m_idToPacketMap.cbegin();
while (it != m_idToPacketMap.cend())
{
const int packetId = it->first;
if (!std::binary_search(sortedPacketsIdsInUse.begin(), sortedPacketsIdsInUse.end(), packetId))
{
it = m_idToPacketMap.erase(it);
}
else
{
++it;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -36,9 +36,11 @@ class VdePacketDirectory
public:
VdePacketDirectory();
void addPacket(const VdeArrayDataPacket& packet);
void addPacket(std::unique_ptr<VdeArrayDataPacket> packet);
const VdeArrayDataPacket* lookupPacket(int arrayId) const;
void clear();
void pruneUnreferencedPackets(const std::vector<int>& packetIdsInUseArr);
bool getPacketsAsCombinedBuffer(const std::vector<int>& packetIdsToGet, QByteArray* combinedPacketArr) const;

View File

@ -19,6 +19,7 @@
#include "VdeVizDataExtractor.h"
#include "VdeArrayDataPacket.h"
#include "VdePacketDirectory.h"
#include "VdeCachingHashedIdFactory.h"
#include "RicHoloLensExportImpl.h"
@ -29,6 +30,8 @@
#include "cvfDrawableGeo.h"
#include "cvfPrimitiveSet.h"
#include "cvfTransform.h"
#include "cvfAssert.h"
#include "cvfTimer.h"
#include "cvfTrace.h"
@ -43,9 +46,11 @@
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
VdeVizDataExtractor::VdeVizDataExtractor(const RimGridView& view)
: m_view(view)
VdeVizDataExtractor::VdeVizDataExtractor(const RimGridView& view, VdeCachingHashedIdFactory* cachingIdFactory)
: m_view(view),
m_cachingIdFactory(cachingIdFactory)
{
CVF_ASSERT(m_cachingIdFactory);
}
//--------------------------------------------------------------------------------------------------
@ -53,84 +58,110 @@ VdeVizDataExtractor::VdeVizDataExtractor(const RimGridView& view)
//--------------------------------------------------------------------------------------------------
void VdeVizDataExtractor::extractViewContents(QString* modelMetaJsonStr, std::vector<int>* allReferencedArrayIds, VdePacketDirectory* packetDirectory)
{
cvf::Timer tim;
// First extract the parts (cvfPart + info) to be exported from from the ResInsight view
const std::vector<VdeExportPart> exportPartsArr = RicHoloLensExportImpl::partsForExport(m_view);
// Convert this to an array of export ready meshes
const std::vector<VdeMesh> meshArr = buildMeshArray(exportPartsArr);
const std::vector<std::unique_ptr<VdeMesh> > meshArr = buildMeshArray(exportPartsArr);
const int buildMeshes_ms = static_cast<int>(tim.lapTime()*1000);
const size_t meshCount = meshArr.size();
cvf::Trace::show("Extracting %d meshes", meshCount);
std::vector<VdeMeshArrayIds> meshArrayIdsArr;
cvf::Trace::show("Analyzing and generating array packet data for %d meshes", meshCount);
std::vector<VdeMeshArrayIds> allMeshesArrayIdsArr;
size_t totNumPrimitives = 0;
int nextArrayId = 0;
for (size_t i = 0; i < meshCount; i++)
{
const VdeMesh& mesh = meshArr[i];
const VdeMesh* mesh = meshArr[i].get();
const size_t primCount = mesh.connArr.size()/mesh.verticesPerPrimitive;
const size_t primCount = mesh->connArr.size()/mesh->verticesPerPrimitive;
totNumPrimitives += primCount;
cvf::Trace::show(" %2d: primCount=%d meshSourceObjName='%s'", i, primCount, mesh.meshSourceObjName.toLatin1().constData());
cvf::Trace::show(" mesh %2d: primCount=%d vertsPerPrim=%d meshSourceObjName='%s' meshSourceObjType='%s'", i, primCount, mesh->verticesPerPrimitive, mesh->meshSourceObjName.toLatin1().constData(), mesh->meshSourceObjTypeStr.toLatin1().constData());
VdeMeshArrayIds meshArrayIds;
VdeMeshArrayIds arrayIdsThisMesh;
{
cvf::Trace::show(" exporting vertices");
meshArrayIds.vertexArrId = nextArrayId++;
const float* floatArr = reinterpret_cast<const float*>(mesh.vertexArr->ptr());
VdeArrayDataPacket dataPacket = VdeArrayDataPacket::fromFloat32Arr(meshArrayIds.vertexArrId, floatArr, 3*mesh.vertexArr->size());
packetDirectory->addPacket(dataPacket);
const float* floatArr = reinterpret_cast<const float*>(mesh->vertexArr->ptr());
const size_t arrElementCount = 3*mesh->vertexArr->size();
arrayIdsThisMesh.vertexArrId = m_cachingIdFactory->getOrCreateIdForFloatArr(VdeCachingHashedIdFactory::VertexArr, floatArr, arrElementCount);
// Debug testing of decoding
debugComparePackets(dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket.fullPacketRawPtr(), dataPacket.fullPacketSize(), nullptr));
}
{
cvf::Trace::show(" exporting connectivities");
meshArrayIds.connArrId = nextArrayId++;
const unsigned int* uintArr = mesh.connArr.data();
VdeArrayDataPacket dataPacket = VdeArrayDataPacket::fromUint32Arr(meshArrayIds.connArrId, uintArr, mesh.connArr.size());
packetDirectory->addPacket(dataPacket);
// Debug testing of decoding
debugComparePackets(dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket.fullPacketRawPtr(), dataPacket.fullPacketSize(), nullptr));
}
if (mesh.texCoordArr.notNull() && mesh.texImage.notNull())
{
if (!packetDirectory->lookupPacket(arrayIdsThisMesh.vertexArrId))
{
cvf::Trace::show(" exporting texture coords");
meshArrayIds.texCoordsArrId = nextArrayId++;
const float* floatArr = reinterpret_cast<const float*>(mesh.texCoordArr->ptr());
VdeArrayDataPacket dataPacket = VdeArrayDataPacket::fromFloat32Arr(meshArrayIds.texCoordsArrId, floatArr, 2*mesh.texCoordArr->size());
packetDirectory->addPacket(dataPacket);
cvf::Trace::show(" generating vertices, arrayId=%d", arrayIdsThisMesh.vertexArrId);
std::unique_ptr<VdeArrayDataPacket> dataPacket = VdeArrayDataPacket::fromFloat32Arr(arrayIdsThisMesh.vertexArrId, floatArr, arrElementCount);
// Debug testing of decoding
debugComparePackets(dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket.fullPacketRawPtr(), dataPacket.fullPacketSize(), nullptr));
//debugComparePackets(*dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket->fullPacketRawPtr(), dataPacket->fullPacketSize(), nullptr));
packetDirectory->addPacket(std::move(dataPacket));
}
}
{
const unsigned int* uintArr = mesh->connArr.data();
const size_t arrElementCount = mesh->connArr.size();
arrayIdsThisMesh.connArrId = m_cachingIdFactory->getOrCreateIdForUint32Arr(VdeCachingHashedIdFactory::ConnArr, uintArr, arrElementCount);
if (!packetDirectory->lookupPacket(arrayIdsThisMesh.connArrId))
{
cvf::Trace::show(" exporting texture image");
meshArrayIds.texImageArrId = nextArrayId++;
cvf::ref<cvf::UByteArray> byteArr = mesh.texImage->toRgb();
VdeArrayDataPacket dataPacket = VdeArrayDataPacket::fromUint8ImageRGBArr(meshArrayIds.texImageArrId, mesh.texImage->width(), mesh.texImage->height(), byteArr->ptr(), byteArr->size());
packetDirectory->addPacket(dataPacket);
cvf::Trace::show(" generating connectivities, arrayId=%d", arrayIdsThisMesh.connArrId);
std::unique_ptr<VdeArrayDataPacket> dataPacket = VdeArrayDataPacket::fromUint32Arr(arrayIdsThisMesh.connArrId, uintArr, arrElementCount);
// Debug testing of decoding
debugComparePackets(dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket.fullPacketRawPtr(), dataPacket.fullPacketSize(), nullptr));
//debugComparePackets(*dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket->fullPacketRawPtr(), dataPacket->fullPacketSize(), nullptr));
packetDirectory->addPacket(std::move(dataPacket));
}
}
meshArrayIdsArr.push_back(meshArrayIds);
if (mesh->texCoordArr.notNull() && mesh->texImage.notNull())
{
{
const float* floatArr = reinterpret_cast<const float*>(mesh->texCoordArr->ptr());
const size_t arrElementCount = 2*mesh->texCoordArr->size();
arrayIdsThisMesh.texCoordsArrId = m_cachingIdFactory->getOrCreateIdForFloatArr(VdeCachingHashedIdFactory::TexCoordsArr, floatArr, arrElementCount);
if (!packetDirectory->lookupPacket(arrayIdsThisMesh.texCoordsArrId))
{
cvf::Trace::show(" generating texture coords, arrayId=%d", arrayIdsThisMesh.texCoordsArrId);
std::unique_ptr<VdeArrayDataPacket> dataPacket = VdeArrayDataPacket::fromFloat32Arr(arrayIdsThisMesh.texCoordsArrId, floatArr, arrElementCount);
// Debug testing of decoding
//debugComparePackets(*dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket->fullPacketRawPtr(), dataPacket->fullPacketSize(), nullptr));
packetDirectory->addPacket(std::move(dataPacket));
}
}
{
cvf::ref<cvf::UByteArray> byteArr = mesh->texImage->toRgb();
arrayIdsThisMesh.texImageArrId = m_cachingIdFactory->getOrCreateIdForUint8Arr(VdeCachingHashedIdFactory::TexImage, byteArr->ptr(), byteArr->size());
if (!packetDirectory->lookupPacket(arrayIdsThisMesh.texImageArrId))
{
cvf::Trace::show(" generating texture image, arrayId=%d", arrayIdsThisMesh.texImageArrId);
std::unique_ptr<VdeArrayDataPacket> dataPacket = VdeArrayDataPacket::fromUint8ImageRGBArr(arrayIdsThisMesh.texImageArrId, mesh->texImage->width(), mesh->texImage->height(), byteArr->ptr(), byteArr->size());
// Debug testing of decoding
//debugComparePackets(*dataPacket, VdeArrayDataPacket::fromRawPacketBuffer(dataPacket->fullPacketRawPtr(), dataPacket->fullPacketSize(), nullptr));
packetDirectory->addPacket(std::move(dataPacket));
}
}
}
allMeshesArrayIdsArr.push_back(arrayIdsThisMesh);
}
cvf::Trace::show("Total number of primitives extracted: %d", totNumPrimitives);
const int fillPacketDir_ms = static_cast<int>(tim.lapTime()*1000);
*modelMetaJsonStr = createModelMetaJsonString(meshArr, meshArrayIdsArr);
*modelMetaJsonStr = createModelMetaJsonString(meshArr, allMeshesArrayIdsArr);
// Find all unique packet array IDs referenced
std::set<int> referencedIdsSet;
for (const VdeMeshArrayIds& meshArrayIds : meshArrayIdsArr)
for (const VdeMeshArrayIds& meshArrayIds : allMeshesArrayIdsArr)
{
if (meshArrayIds.vertexArrId != -1) referencedIdsSet.insert(meshArrayIds.vertexArrId);
if (meshArrayIds.connArrId != -1) referencedIdsSet.insert(meshArrayIds.connArrId);
@ -139,20 +170,24 @@ void VdeVizDataExtractor::extractViewContents(QString* modelMetaJsonStr, std::ve
}
allReferencedArrayIds->assign(referencedIdsSet.begin(), referencedIdsSet.end());
RiaLogging::debug(QString("HoloLens: Extracted %1 meshes (total of %2 primitives) in %3ms (buildMeshes=%4ms, fillPacketDir=%5ms)").arg(meshCount).arg(totNumPrimitives).arg(static_cast<int>(tim.time()*1000)).arg(buildMeshes_ms).arg(fillPacketDir_ms));
//cvf::Trace::show("Total number of primitives extracted: %d in %dms", totNumPrimitives, static_cast<int>(tim.time()*1000));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<VdeMesh> VdeVizDataExtractor::buildMeshArray(const std::vector<VdeExportPart>& exportPartsArr)
std::vector<std::unique_ptr<VdeMesh> > VdeVizDataExtractor::buildMeshArray(const std::vector<VdeExportPart>& exportPartsArr)
{
std::vector<VdeMesh> meshArr;
std::vector<std::unique_ptr<VdeMesh> > meshArr;
for (const VdeExportPart& exportPart : exportPartsArr)
{
VdeMesh mesh;
if (extractMeshFromExportPart(exportPart, &mesh))
std::unique_ptr<VdeMesh> mesh = createMeshFromExportPart(exportPart);
if (mesh)
{
meshArr.push_back(mesh);
meshArr.push_back(std::move(mesh));
}
}
@ -162,26 +197,28 @@ std::vector<VdeMesh> VdeVizDataExtractor::buildMeshArray(const std::vector<VdeEx
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool VdeVizDataExtractor::extractMeshFromExportPart(const VdeExportPart& exportPart, VdeMesh* mesh)
std::unique_ptr<VdeMesh> VdeVizDataExtractor::createMeshFromExportPart(const VdeExportPart& exportPart)
{
//cvf::Timer tim;
const cvf::Part* cvfPart = exportPart.part();
const cvf::DrawableGeo* geo = dynamic_cast<const cvf::DrawableGeo*>(cvfPart ? cvfPart->drawable() : nullptr);
if (!geo)
{
return false;
return nullptr;
}
if (geo->primitiveSetCount() != 1)
{
RiaLogging::debug("Only geometries with exactly one primitive set is supported");
return false;
return nullptr;
}
const cvf::Vec3fArray* vertexArr = geo->vertexArray();
const cvf::PrimitiveSet* primSet = geo->primitiveSet(0);
if (!vertexArr || !primSet || primSet->faceCount() == 0)
{
return false;
return nullptr;
}
@ -190,23 +227,24 @@ bool VdeVizDataExtractor::extractMeshFromExportPart(const VdeExportPart& exportP
if (primType != cvf::PT_TRIANGLES && primType != cvf::PT_LINES)
{
RiaLogging::debug(QString("Currently only triangle and line primitive sets are supported (saw primitive type: %1)").arg(primType));
return false;
return nullptr;
}
const int vertsPerPrimitive = (primType == cvf::PT_TRIANGLES) ? 3 : 2;
std::unique_ptr<VdeMesh> mesh(new VdeMesh);
mesh->verticesPerPrimitive = vertsPerPrimitive;
// Possibly transform the vertices
if (cvfPart->transform())
{
const size_t vertexCount = vertexArr->size();
cvf::ref<cvf::Vec3fArray> transVertexArr = new cvf::Vec3fArray(vertexArr->size());
const cvf::Mat4f m = cvf::Mat4f(cvfPart->transform()->worldTransform());
cvf::Mat4f m = cvf::Mat4f(cvfPart->transform()->worldTransform());
cvf::ref<cvf::Vec3fArray> transVertexArr = new cvf::Vec3fArray(*vertexArr);
const size_t vertexCount = transVertexArr->size();
for (size_t i = 0; i < vertexCount; i++)
{
transVertexArr->set(i, vertexArr->get(i).getTransformedPoint(m));
transVertexArr->ptr(i)->transformPoint(m);
}
mesh->vertexArr = transVertexArr.p();
@ -216,12 +254,15 @@ bool VdeVizDataExtractor::extractMeshFromExportPart(const VdeExportPart& exportP
mesh->vertexArr = vertexArr;
}
// Fetch connectivities
// Using getFaceIndices() allows us to access strips and fans in the same way as triangles
// Note that HoloLens visualization wants triangles in clockwise order so we try and fix the winding
// This point might be moot if the HoloLens visualization always has to use two-sideded lighting to get good results
cvf::UIntArray faceConn;
// This point might be moot if the HoloLens visualization always has to use two-sided lighting to get good results
const size_t faceCount = primSet->faceCount();
mesh->connArr.reserve(faceCount*vertsPerPrimitive);
cvf::UIntArray faceConn;
for (size_t iface = 0; iface < faceCount; iface++)
{
primSet->getFaceIndices(iface, &faceConn);
@ -259,26 +300,28 @@ bool VdeVizDataExtractor::extractMeshFromExportPart(const VdeExportPart& exportP
mesh->color = exportPart.color();
mesh->opacity = exportPart.opacity();
return true;
//cvf::Trace::show("createMeshFromExportPart(): numFaces=%d, time=%dms", faceCount, static_cast<int>(tim.time()*1000));
return mesh;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString VdeVizDataExtractor::createModelMetaJsonString(const std::vector<VdeMesh>& meshArr, const std::vector<VdeMeshArrayIds>& meshContentIdsArr)
QString VdeVizDataExtractor::createModelMetaJsonString(const std::vector<std::unique_ptr<VdeMesh> >& meshArr, const std::vector<VdeMeshArrayIds>& meshContentIdsArr)
{
QVariantList jsonMeshMetaList;
for (size_t i = 0; i < meshArr.size(); i++)
{
const VdeMesh& mesh = meshArr[i];
const VdeMesh* mesh = meshArr[i].get();
const VdeMeshArrayIds& meshIds = meshContentIdsArr[i];
QMap<QString, QVariant> jsonMeshMeta;
jsonMeshMeta["meshSourceObjType"] = mesh.meshSourceObjTypeStr;
jsonMeshMeta["meshSourceObjName"] = mesh.meshSourceObjName;
jsonMeshMeta["meshSourceObjType"] = mesh->meshSourceObjTypeStr;
jsonMeshMeta["meshSourceObjName"] = mesh->meshSourceObjName;
jsonMeshMeta["verticesPerPrimitive"] = mesh.verticesPerPrimitive;
jsonMeshMeta["verticesPerPrimitive"] = mesh->verticesPerPrimitive;
jsonMeshMeta["vertexArrId"] = meshIds.vertexArrId;
jsonMeshMeta["connArrId"] = meshIds.connArrId;
@ -290,14 +333,14 @@ QString VdeVizDataExtractor::createModelMetaJsonString(const std::vector<VdeMesh
else
{
QMap<QString, QVariant> jsonColor;
jsonColor["r"] = mesh.color.r();
jsonColor["g"] = mesh.color.g();
jsonColor["b"] = mesh.color.b();
jsonColor["r"] = mesh->color.r();
jsonColor["g"] = mesh->color.g();
jsonColor["b"] = mesh->color.b();
jsonMeshMeta["color"] = jsonColor;
}
jsonMeshMeta["opacity"] = mesh.opacity;
jsonMeshMeta["opacity"] = mesh->opacity;
jsonMeshMetaList.push_back(jsonMeshMeta);
}

View File

@ -25,9 +25,12 @@
#include <QString>
#include <memory>
class VdeArrayDataPacket;
class VdePacketDirectory;
class VdeExportPart;
class VdeCachingHashedIdFactory;
class RimGridView;
@ -62,7 +65,7 @@ struct VdeMesh
//==================================================================================================
//
//
// The set of array IDs that are needed for a mesh
//
//==================================================================================================
struct VdeMeshArrayIds
@ -89,17 +92,17 @@ struct VdeMeshArrayIds
class VdeVizDataExtractor
{
public:
VdeVizDataExtractor(const RimGridView& view);
VdeVizDataExtractor(const RimGridView& view, VdeCachingHashedIdFactory* cachingIdFactory);
void extractViewContents(QString* modelMetaJsonStr, std::vector<int>* allReferencedArrayIds, VdePacketDirectory* packetDirectory);
private:
static std::vector<VdeMesh> buildMeshArray(const std::vector<VdeExportPart>& exportPartsArr);
static bool extractMeshFromExportPart(const VdeExportPart& exportPart, VdeMesh* mesh);
static QString createModelMetaJsonString(const std::vector<VdeMesh>& meshArr, const std::vector<VdeMeshArrayIds>& meshContentIdsArr);
static void debugComparePackets(const VdeArrayDataPacket& packetA, const VdeArrayDataPacket& packetB);
static std::vector<std::unique_ptr<VdeMesh> > buildMeshArray(const std::vector<VdeExportPart>& exportPartsArr);
static std::unique_ptr<VdeMesh> createMeshFromExportPart(const VdeExportPart& exportPart);
static QString createModelMetaJsonString(const std::vector<std::unique_ptr<VdeMesh> >& meshArr, const std::vector<VdeMeshArrayIds>& meshContentIdsArr);
static void debugComparePackets(const VdeArrayDataPacket& packetA, const VdeArrayDataPacket& packetB);
private:
const RimGridView& m_view;
const RimGridView& m_view;
VdeCachingHashedIdFactory* m_cachingIdFactory;
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,328 @@
// Copyright (c) 2014 Google, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// FarmHash, by Geoff Pike
//
// http://code.google.com/p/farmhash/
//
// This file provides a few functions for hashing strings and other
// data. All of them are high-quality functions in the sense that
// they do well on standard tests such as Austin Appleby's SMHasher.
// They're also fast. FarmHash is the successor to CityHash.
//
// Functions in the FarmHash family are not suitable for cryptography.
//
// WARNING: This code has been only lightly tested on big-endian platforms!
// It is known to work well on little-endian platforms that have a small penalty
// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
// It should work on all 32-bit and 64-bit platforms that allow unaligned reads;
// bug reports are welcome.
//
// By the way, for some hash functions, given strings a and b, the hash
// of a+b is easily derived from the hashes of a and b. This property
// doesn't hold for any hash functions in this file.
#ifndef FARM_HASH_H_
#define FARM_HASH_H_
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h> // for memcpy and memset
#include <utility>
#ifndef NAMESPACE_FOR_HASH_FUNCTIONS
#define NAMESPACE_FOR_HASH_FUNCTIONS util
#endif
namespace NAMESPACE_FOR_HASH_FUNCTIONS {
#if defined(FARMHASH_UINT128_T_DEFINED)
#if defined(__clang__)
#if !defined(uint128_t)
#define uint128_t __uint128_t
#endif
#endif
inline uint64_t Uint128Low64(const uint128_t x) {
return static_cast<uint64_t>(x);
}
inline uint64_t Uint128High64(const uint128_t x) {
return static_cast<uint64_t>(x >> 64);
}
inline uint128_t Uint128(uint64_t lo, uint64_t hi) {
return lo + (((uint128_t)hi) << 64);
}
#else
typedef std::pair<uint64_t, uint64_t> uint128_t;
inline uint64_t Uint128Low64(const uint128_t x) { return x.first; }
inline uint64_t Uint128High64(const uint128_t x) { return x.second; }
inline uint128_t Uint128(uint64_t lo, uint64_t hi) { return uint128_t(lo, hi); }
#endif
// BASIC STRING HASHING
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
size_t Hash(const char* s, size_t len);
// Hash function for a byte array. Most useful in 32-bit binaries.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint32_t Hash32(const char* s, size_t len);
// Hash function for a byte array. For convenience, a 32-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint32_t Hash32WithSeed(const char* s, size_t len, uint32_t seed);
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint64_t Hash64(const char* s, size_t len);
// Hash function for a byte array. For convenience, a 64-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint64_t Hash64WithSeed(const char* s, size_t len, uint64_t seed);
// Hash function for a byte array. For convenience, two seeds are also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint64_t Hash64WithSeeds(const char* s, size_t len,
uint64_t seed0, uint64_t seed1);
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint128_t Hash128(const char* s, size_t len);
// Hash function for a byte array. For convenience, a 128-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
uint128_t Hash128WithSeed(const char* s, size_t len, uint128_t seed);
// BASIC NON-STRING HASHING
// Hash 128 input bits down to 64 bits of output.
// This is intended to be a reasonably good hash function.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
inline uint64_t Hash128to64(uint128_t x) {
// Murmur-inspired hashing.
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
a ^= (a >> 47);
uint64_t b = (Uint128High64(x) ^ a) * kMul;
b ^= (b >> 47);
b *= kMul;
return b;
}
// FINGERPRINTING (i.e., good, portable, forever-fixed hash functions)
// Fingerprint function for a byte array. Most useful in 32-bit binaries.
uint32_t Fingerprint32(const char* s, size_t len);
// Fingerprint function for a byte array.
uint64_t Fingerprint64(const char* s, size_t len);
// Fingerprint function for a byte array.
uint128_t Fingerprint128(const char* s, size_t len);
// This is intended to be a good fingerprinting primitive.
// See below for more overloads.
inline uint64_t Fingerprint(uint128_t x) {
// Murmur-inspired hashing.
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
a ^= (a >> 47);
uint64_t b = (Uint128High64(x) ^ a) * kMul;
b ^= (b >> 44);
b *= kMul;
b ^= (b >> 41);
b *= kMul;
return b;
}
// This is intended to be a good fingerprinting primitive.
inline uint64_t Fingerprint(uint64_t x) {
// Murmur-inspired hashing.
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
uint64_t b = x * kMul;
b ^= (b >> 44);
b *= kMul;
b ^= (b >> 41);
b *= kMul;
return b;
}
#ifndef FARMHASH_NO_CXX_STRING
// Convenience functions to hash or fingerprint C++ strings.
// These require that Str::data() return a pointer to the first char
// (as a const char*) and that Str::length() return the string's length;
// they work with std::string, for example.
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline size_t Hash(const Str& s) {
assert(sizeof(s[0]) == 1);
return Hash(s.data(), s.length());
}
// Hash function for a byte array. Most useful in 32-bit binaries.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint32_t Hash32(const Str& s) {
assert(sizeof(s[0]) == 1);
return Hash32(s.data(), s.length());
}
// Hash function for a byte array. For convenience, a 32-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint32_t Hash32WithSeed(const Str& s, uint32_t seed) {
assert(sizeof(s[0]) == 1);
return Hash32WithSeed(s.data(), s.length(), seed);
}
// Hash 128 input bits down to 64 bits of output.
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint64_t Hash64(const Str& s) {
assert(sizeof(s[0]) == 1);
return Hash64(s.data(), s.length());
}
// Hash function for a byte array. For convenience, a 64-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint64_t Hash64WithSeed(const Str& s, uint64_t seed) {
assert(sizeof(s[0]) == 1);
return Hash64WithSeed(s.data(), s.length(), seed);
}
// Hash function for a byte array. For convenience, two seeds are also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint64_t Hash64WithSeeds(const Str& s, uint64_t seed0, uint64_t seed1) {
assert(sizeof(s[0]) == 1);
return Hash64WithSeeds(s.data(), s.length(), seed0, seed1);
}
// Hash function for a byte array.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint128_t Hash128(const Str& s) {
assert(sizeof(s[0]) == 1);
return Hash128(s.data(), s.length());
}
// Hash function for a byte array. For convenience, a 128-bit seed is also
// hashed into the result.
// May change from time to time, may differ on different platforms, may differ
// depending on NDEBUG.
template <typename Str>
inline uint128_t Hash128WithSeed(const Str& s, uint128_t seed) {
assert(sizeof(s[0]) == 1);
return Hash128(s.data(), s.length(), seed);
}
// FINGERPRINTING (i.e., good, portable, forever-fixed hash functions)
// Fingerprint function for a byte array. Most useful in 32-bit binaries.
template <typename Str>
inline uint32_t Fingerprint32(const Str& s) {
assert(sizeof(s[0]) == 1);
return Fingerprint32(s.data(), s.length());
}
// Fingerprint 128 input bits down to 64 bits of output.
// Fingerprint function for a byte array.
template <typename Str>
inline uint64_t Fingerprint64(const Str& s) {
assert(sizeof(s[0]) == 1);
return Fingerprint64(s.data(), s.length());
}
// Fingerprint function for a byte array.
template <typename Str>
inline uint128_t Fingerprint128(const Str& s) {
assert(sizeof(s[0]) == 1);
return Fingerprint128(s.data(), s.length());
}
#endif
} // namespace NAMESPACE_FOR_HASH_FUNCTIONS
/* gently define FARMHASH_BIG_ENDIAN when detected big-endian machine */
#if defined(__BIG_ENDIAN__)
#if !defined(FARMHASH_BIG_ENDIAN)
#define FARMHASH_BIG_ENDIAN
#endif
#elif defined(__LITTLE_ENDIAN__)
// nothing for little-endian
#elif defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER == __ORDER_LITTLE_ENDIAN__)
// nothing for little-endian
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER == __ORDER_BIG_ENDIAN__)
#if !defined(FARMHASH_BIG_ENDIAN)
#define FARMHASH_BIG_ENDIAN
#endif
#elif defined(__linux__) || defined(__CYGWIN__) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
#include <endian.h> // libc6-dev, GLIBC
#if BYTE_ORDER == BIG_ENDIAN
#if !defined(FARMHASH_BIG_ENDIAN)
#define FARMHASH_BIG_ENDIAN
#endif
#endif
#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__s390x__)
#include <sys/endian.h>
#if BYTE_ORDER == BIG_ENDIAN
#if !defined(FARMHASH_BIG_ENDIAN)
#define FARMHASH_BIG_ENDIAN
#endif
#endif
#elif defined(_WIN32)
// Windows is (currently) little-endian
#else
#error "Unable to determine endianness!"
#endif /* __BIG_ENDIAN__ */
#endif // FARM_HASH_H_