Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e4c445990 | ||
|
|
e433f9c813 | ||
|
|
eed3824da3 | ||
|
|
a4825a42a4 | ||
|
|
2dad082dea | ||
|
|
5b69f1dda0 | ||
|
|
fbf50e1856 | ||
|
|
b2b969911c | ||
|
|
ba87641d27 | ||
|
|
ee88483336 |
@@ -890,6 +890,10 @@ mark_as_advanced(P2T_SHARED)
|
||||
mark_as_advanced(P2T_STATIC)
|
||||
mark_as_advanced(P2T_TESTS)
|
||||
|
||||
# GCT is a collection of algorithms for geometry processing and conversion
|
||||
add_subdirectory(gct)
|
||||
CMAKEFILES(gct)
|
||||
|
||||
# TCLAP is used for option parsing - consists entirely of headers
|
||||
# and does not need to be installed, but does need to generate a
|
||||
# config file
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
set(AUX_SRCS
|
||||
cc.c
|
||||
cpuinfo.c
|
||||
mmatomic.c
|
||||
mmbinsort.c
|
||||
mmbitmap.c
|
||||
mm.c
|
||||
mmhash.c
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_library(AUX SHARED ${AUX_SRCS})
|
||||
set_target_properties(AUX PROPERTIES VERSION 1.1.0 SOVERSION 1)
|
||||
|
||||
install(TARGETS AUX
|
||||
RUNTIME DESTINATION ${BIN_DIR}
|
||||
LIBRARY DESTINATION ${LIB_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_DIR})
|
||||
|
||||
if(MSVC)
|
||||
set_property(TARGET AUX APPEND PROPERTY COMPILE_DEFINITIONS "AUX_DLL_EXPORTS")
|
||||
endif(MSVC)
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 8
|
||||
# mode: cmake
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
# ex: shiftwidth=2 tabstop=8
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,215 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Templates C style!
|
||||
|
||||
#include this whole file with the following definitions set:
|
||||
|
||||
#define MSORT_MAIN MyInlinedSortFunction
|
||||
#define MSORT_CMP MyComparisonFunction
|
||||
#define MSORT_TYPE int
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CC_MSORT_INLINE
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *src;
|
||||
void *dst;
|
||||
int count;
|
||||
int mergeflag;
|
||||
int depthbit;
|
||||
} ccMergeSortStack;
|
||||
|
||||
#define CC_MSORT_INLINE
|
||||
#define CC_MSORT_STACK_DEPTH (512)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MSORT_COPY
|
||||
#define MSORT_COPY(d,s) (*(d)=*(s))
|
||||
#define CC_MSORT_COPY
|
||||
#endif
|
||||
|
||||
|
||||
static MSORT_TYPE *MSORT_MAIN( MSORT_TYPE *src, MSORT_TYPE *tmp, int count )
|
||||
{
|
||||
int swapflag, depthbit, maxdepthbit;
|
||||
ssize_t leftcount, rightcount;
|
||||
MSORT_TYPE *dst, *sl, *sr, *dstend, *dstbase, *swap, temp;
|
||||
ccMergeSortStack stack[CC_MSORT_STACK_DEPTH];
|
||||
ccMergeSortStack *sp;
|
||||
|
||||
dst = tmp;
|
||||
sp = stack;
|
||||
swapflag = 0;
|
||||
depthbit = 0;
|
||||
|
||||
if( count <= 1 )
|
||||
return src;
|
||||
|
||||
leftcount = count;
|
||||
for( maxdepthbit = 1 ; ; maxdepthbit ^= 1 )
|
||||
{
|
||||
leftcount = leftcount - ( leftcount >> 1 );
|
||||
if( leftcount <= 4 )
|
||||
break;
|
||||
}
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
if( count <= 4 )
|
||||
{
|
||||
if( !( depthbit ^ maxdepthbit ) )
|
||||
{
|
||||
if( ( count == 4 ) && MSORT_CMP( &src[2], &src[3] ) )
|
||||
{
|
||||
MSORT_COPY( &temp, &src[2] );
|
||||
MSORT_COPY( &src[2], &src[3] );
|
||||
MSORT_COPY( &src[3], &temp );
|
||||
}
|
||||
if( MSORT_CMP( &src[0], &src[1] ) )
|
||||
{
|
||||
MSORT_COPY( &temp, &src[0] );
|
||||
MSORT_COPY( &src[0], &src[1] );
|
||||
MSORT_COPY( &src[1], &temp );
|
||||
}
|
||||
swapflag = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( count == 4 )
|
||||
{
|
||||
if( MSORT_CMP( &src[2], &src[3] ) )
|
||||
{
|
||||
MSORT_COPY( &dst[2], &src[3] );
|
||||
MSORT_COPY( &dst[3], &src[2] );
|
||||
}
|
||||
else
|
||||
{
|
||||
MSORT_COPY( &dst[2], &src[2] );
|
||||
MSORT_COPY( &dst[3], &src[3] );
|
||||
}
|
||||
}
|
||||
else if( count == 3 )
|
||||
MSORT_COPY( &dst[2], &src[2] );
|
||||
if( MSORT_CMP( &src[0], &src[1] ) )
|
||||
{
|
||||
MSORT_COPY( &dst[0], &src[1] );
|
||||
MSORT_COPY( &dst[1], &src[0] );
|
||||
}
|
||||
else
|
||||
{
|
||||
MSORT_COPY( &dst[0], &src[0] );
|
||||
MSORT_COPY( &dst[1], &src[1] );
|
||||
}
|
||||
swap = src;
|
||||
src = dst;
|
||||
dst = swap;
|
||||
swapflag = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rightcount = count >> 1;
|
||||
leftcount = count - rightcount;
|
||||
sp->src = src;
|
||||
sp->dst = dst;
|
||||
sp->count = count;
|
||||
sp->mergeflag = 1;
|
||||
sp->depthbit = depthbit;
|
||||
depthbit ^= 1;
|
||||
sp++;
|
||||
sp->src = src + leftcount;
|
||||
sp->dst = dst + leftcount;
|
||||
sp->count = rightcount;
|
||||
sp->mergeflag = 0;
|
||||
sp->depthbit = depthbit;
|
||||
sp++;
|
||||
count = leftcount;
|
||||
continue;
|
||||
}
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
rightcount = count >> 1;
|
||||
leftcount = count - rightcount;
|
||||
sl = src;
|
||||
sr = src + leftcount;
|
||||
dstbase = dst;
|
||||
for( ; ; )
|
||||
{
|
||||
if( MSORT_CMP( sl, sr ) )
|
||||
{
|
||||
MSORT_COPY( dst++, sr++ );
|
||||
if( --rightcount )
|
||||
continue;
|
||||
for( dstend = &dst[leftcount] ; dst < dstend ; )
|
||||
MSORT_COPY( dst++, sl++ );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
MSORT_COPY( dst++, sl++ );
|
||||
if( --leftcount )
|
||||
continue;
|
||||
for( dstend = &dst[rightcount] ; dst < dstend ; )
|
||||
MSORT_COPY( dst++, sr++ );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( sp == stack )
|
||||
return dstbase;
|
||||
sp--;
|
||||
src = sp->src;
|
||||
dst = sp->dst;
|
||||
count = sp->count;
|
||||
depthbit = sp->depthbit;
|
||||
if( !( sp->mergeflag ) )
|
||||
break;
|
||||
swapflag ^= 1;
|
||||
if( swapflag )
|
||||
{
|
||||
src = sp->dst;
|
||||
dst = sp->src;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef CC_MSORT_COPY
|
||||
#undef MSORT_COPY
|
||||
#undef CC_MSORT_COPY
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
/* Automatically generated CPU information header */
|
||||
|
||||
#define CPUCONF_CHAR_SIZE (1)
|
||||
#define CPUCONF_SHORT_SIZE (2)
|
||||
#define CPUCONF_INT_SIZE (4)
|
||||
#define CPUCONF_LONG_SIZE (8)
|
||||
#define CPUCONF_LONG_LONG_SIZE (8)
|
||||
#define CPUCONF_INTPTR_SIZE (8)
|
||||
#define CPUCONF_POINTER_SIZE (8)
|
||||
#define CPUCONF_FLOAT_SIZE (4)
|
||||
#define CPUCONF_DOUBLE_SIZE (8)
|
||||
#define CPUCONF_LONG_DOUBLE_SIZE (16)
|
||||
|
||||
#define CPUCONF_CHAR_BITS (8)
|
||||
#define CPUCONF_SHORT_BITS (16)
|
||||
#define CPUCONF_INT_BITS (32)
|
||||
#define CPUCONF_LONG_BITS (64)
|
||||
#define CPUCONF_LONG_LONG_BITS (64)
|
||||
#define CPUCONF_INTPTR_BITS (64)
|
||||
#define CPUCONF_POINTER_BITS (64)
|
||||
#define CPUCONF_FLOAT_BITS (32)
|
||||
#define CPUCONF_DOUBLE_BITS (64)
|
||||
#define CPUCONF_LONG_DOUBLE_BITS (128)
|
||||
|
||||
#define CPUCONF_CHAR_SIZESHIFT (0)
|
||||
#define CPUCONF_SHORT_SIZESHIFT (1)
|
||||
#define CPUCONF_INT_SIZESHIFT (2)
|
||||
#define CPUCONF_LONG_SIZESHIFT (3)
|
||||
#define CPUCONF_LONG_LONG_SIZESHIFT (3)
|
||||
#define CPUCONF_INTPTR_SIZESHIFT (3)
|
||||
#define CPUCONF_POINTER_SIZESHIFT (3)
|
||||
#define CPUCONF_FLOAT_SIZESHIFT (2)
|
||||
#define CPUCONF_DOUBLE_SIZESHIFT (3)
|
||||
#define CPUCONF_LONG_DOUBLE_SIZESHIFT (4)
|
||||
|
||||
#define CPUCONF_CHAR_BITSHIFT (3)
|
||||
#define CPUCONF_SHORT_BITSHIFT (4)
|
||||
#define CPUCONF_INT_BITSHIFT (5)
|
||||
#define CPUCONF_LONG_BITSHIFT (6)
|
||||
#define CPUCONF_LONG_LONG_BITSHIFT (6)
|
||||
#define CPUCONF_INTPTR_BITSHIFT (6)
|
||||
#define CPUCONF_POINTER_BITSHIFT (6)
|
||||
#define CPUCONF_FLOAT_BITSHIFT (5)
|
||||
#define CPUCONF_DOUBLE_BITSHIFT (6)
|
||||
#define CPUCONF_LONG_DOUBLE_BITSHIFT (7)
|
||||
|
||||
#define CPUCONF_LITTLE_ENDIAN
|
||||
#define CPUCONF_ARCH_AMD64
|
||||
#define CPUCONF_VENDOR_INTEL
|
||||
#define CPUCONF_IDENTIFIER "Intel(R) Core(TM) i7-2760QM CPU @ 2.40GHz"
|
||||
#define CPUCONF_CLASS_CORE2
|
||||
#define CPUCONF_LOGICAL_CORES_COUNT (16)
|
||||
#define CPUCONF_PHYSICAL_CORES_COUNT (8)
|
||||
#define CPUCONF_CORES_COUNT (8)
|
||||
#define CPUCONF_SYSTEM_MEMORY (8207917056LL)
|
||||
#define CPUCONF_WORD_SIZE (64)
|
||||
#define CPUCONF_CACHE_LINE_SIZE (64)
|
||||
#define CPUCONF_CACHE_LOAD_SIZE (64)
|
||||
#define CPUCONF_CACHE_L2_SIZE (262144)
|
||||
#define CPUCONF_CAP_GPREGS (16)
|
||||
#define CPUCONF_CAP_FPREGS (16)
|
||||
|
||||
#define CPUCONF_CAP_CMOV
|
||||
#define CPUCONF_CAP_MMX
|
||||
#define CPUCONF_CAP_SSE
|
||||
#define CPUCONF_CAP_SSE2
|
||||
#define CPUCONF_CAP_SSE3
|
||||
#define CPUCONF_CAP_SSSE3
|
||||
#define CPUCONF_CAP_SSE4_1
|
||||
#define CPUCONF_CAP_SSE4_2
|
||||
#define CPUCONF_CAP_HYPERTHREADING
|
||||
#define CPUCONF_CAP_MWAIT
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,179 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef CPUINFO_H
|
||||
#define CPUINFO_H
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t endianness;
|
||||
uint32_t intellevel;
|
||||
uint32_t amdlevel;
|
||||
|
||||
uint32_t arch;
|
||||
char vendorstring[12+1];
|
||||
char identifier[48+1];
|
||||
|
||||
uint32_t vendor;
|
||||
uint32_t class;
|
||||
uint32_t family;
|
||||
uint32_t model;
|
||||
uint32_t cacheline;
|
||||
uint32_t clflushsize;
|
||||
|
||||
int32_t cachelineL1code, cachesizeL1code, cacheassociativityL1code, cachesharedL1code;
|
||||
int32_t cachelineL1data, cachesizeL1data, cacheassociativityL1data, cachesharedL1data;
|
||||
int32_t cacheunifiedL1;
|
||||
int32_t cachelineL2, cachesizeL2, cacheassociativityL2, cachesharedL2;
|
||||
int32_t cachelineL3, cachesizeL3, cacheassociativityL3, cachesharedL3;
|
||||
|
||||
int64_t sysmemory;
|
||||
uint32_t socketphysicalcores;
|
||||
uint32_t socketlogicalcores;
|
||||
uint32_t socketcount;
|
||||
uint32_t totalcorecount;
|
||||
uint32_t wordsize;
|
||||
uint32_t gpregs;
|
||||
uint32_t fpregs;
|
||||
|
||||
|
||||
/* CPU capabilities */
|
||||
int capcmov:1;
|
||||
int capclflush:1;
|
||||
int captsc:1;
|
||||
int capmmx:1;
|
||||
int capmmxext:1;
|
||||
int cap3dnow:1;
|
||||
int cap3dnowext:1;
|
||||
int capsse:1;
|
||||
int capsse2:1;
|
||||
int capsse3:1;
|
||||
int capssse3:1;
|
||||
int capsse4p1:1;
|
||||
int capsse4p2:1;
|
||||
int capsse4a:1;
|
||||
int capavx:1;
|
||||
int capavx2:1;
|
||||
int capxop:1;
|
||||
int capfma3:1;
|
||||
int capfma4:1;
|
||||
int capmisalignsse:1;
|
||||
int capaes:1;
|
||||
int cappclmul;
|
||||
int caprdrnd:1;
|
||||
int capcmpxchg16b:1;
|
||||
int cappopcnt:1;
|
||||
int caplzcnt:1;
|
||||
int capmovbe:1;
|
||||
int caprdtscp:1;
|
||||
int capconstanttsc:1;
|
||||
int capf16c:1;
|
||||
int capbmi:1;
|
||||
int capbmi2:1;
|
||||
int captbm:1;
|
||||
int caphyperthreading:1;
|
||||
int capmwait:1;
|
||||
int caplongmode:1;
|
||||
int capthermalsensor:1;
|
||||
int capclockmodulation:1;
|
||||
/* CPU capabilities */
|
||||
|
||||
} cpuInfo;
|
||||
|
||||
|
||||
void cpuGetInfo( cpuInfo *cpu );
|
||||
|
||||
void cpuGetInfoEnv( cpuInfo *cpu );
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
CPUINFO_LITTLE_ENDIAN,
|
||||
CPUINFO_BIG_ENDIAN,
|
||||
CPUINFO_MIXED_ENDIAN
|
||||
};
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
CPUINFO_ARCH_AMD64,
|
||||
CPUINFO_ARCH_IA32,
|
||||
CPUINFO_ARCH_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
CPUINFO_VENDOR_AMD,
|
||||
CPUINFO_VENDOR_INTEL,
|
||||
CPUINFO_VENDOR_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
CPUINFO_CLASS_STEAMROLLER,
|
||||
CPUINFO_CLASS_JAGUAR,
|
||||
CPUINFO_CLASS_PILEDRIVER,
|
||||
CPUINFO_CLASS_BULLDOZER,
|
||||
CPUINFO_CLASS_BOBCAT,
|
||||
CPUINFO_CLASS_BARCELONA,
|
||||
CPUINFO_CLASS_ATHLON64SSE3,
|
||||
CPUINFO_CLASS_ATHLON64,
|
||||
CPUINFO_CLASS_ATHLON,
|
||||
CPUINFO_CLASS_K6_2,
|
||||
CPUINFO_CLASS_K6,
|
||||
|
||||
CPUINFO_CLASS_COREI7AVX2,
|
||||
CPUINFO_CLASS_COREI7AVX,
|
||||
CPUINFO_CLASS_COREI7,
|
||||
CPUINFO_CLASS_CORE2,
|
||||
CPUINFO_CLASS_NOCONA,
|
||||
CPUINFO_CLASS_PRESCOTT,
|
||||
CPUINFO_CLASS_PENTIUM4,
|
||||
CPUINFO_CLASS_PENTIUM3,
|
||||
CPUINFO_CLASS_PENTIUM2,
|
||||
|
||||
CPUINFO_CLASS_I686,
|
||||
CPUINFO_CLASS_I586,
|
||||
|
||||
CPUINFO_CLASS_AMD64GENERIC,
|
||||
CPUINFO_CLASS_IA32GENERIC,
|
||||
CPUINFO_CLASS_UNKNOWN,
|
||||
|
||||
CPUINFO_CLASS_COUNT
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* CPUINFO_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,601 @@
|
||||
/* gctcommon.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 10/03/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Any common use functions between all the tools.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GCTCOMMON_H
|
||||
#define GCTCOMMON_H
|
||||
|
||||
/* Standard C/C++ libraries */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#ifndef COMPILE_FOR_VSL
|
||||
#include <ctype.h>
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
/* Pthread libraries */
|
||||
#include <pthread.h>
|
||||
#if defined (_GNU_SOURCE)
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
|
||||
#ifndef COMPILE_FOR_VSL
|
||||
extern "C" {
|
||||
#include "common.h"
|
||||
#include "bu.h"
|
||||
#include "vmath.h"
|
||||
#include "bn.h"
|
||||
#include "raytrace.h"
|
||||
#include "rtgeom.h"
|
||||
#include "wdb.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQ
|
||||
#define SQ(a) (a)*(a)
|
||||
#endif
|
||||
|
||||
/* Stuff defined in BRL-CAD but might not be for others */
|
||||
#ifndef X
|
||||
#define X 0
|
||||
#endif
|
||||
#ifndef Y
|
||||
#define Y 1
|
||||
#endif
|
||||
#ifndef Z
|
||||
#define Z 2
|
||||
#endif
|
||||
|
||||
#ifndef VINIT
|
||||
#define VINIT(a,s) (a)[X] = (a)[Y] = (a)[Z] = (s)
|
||||
#endif
|
||||
|
||||
#ifndef VSET
|
||||
#define VSET(a,b,c,d) { \
|
||||
(a)[X] = (b); \
|
||||
(a)[Y] = (c); \
|
||||
(a)[Z] = (d); }
|
||||
#endif
|
||||
|
||||
#ifndef VADD2
|
||||
#define VADD2(a, b, c) { \
|
||||
(a)[X] = (b)[X] + (c)[X]; \
|
||||
(a)[Y] = (b)[Y] + (c)[Y]; \
|
||||
(a)[Z] = (b)[Z] + (c)[Z]; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef VEQUAL
|
||||
#define VEQUAL(a, b) ((a)[X]==(b)[X] && (a)[Y]==(b)[Y] && (a)[Z]==(b)[Z])
|
||||
#endif
|
||||
|
||||
#ifndef VMOVE
|
||||
#define VMOVE(a, b) { \
|
||||
(a)[X] = (b)[X]; \
|
||||
(a)[Y] = (b)[Y]; \
|
||||
(a)[Z] = (b)[Z]; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef VSCALE
|
||||
#define VSCALE(a, b, c) { \
|
||||
(a)[X] = (b)[X] * (c); \
|
||||
(a)[Y] = (b)[Y] * (c); \
|
||||
(a)[Z] = (b)[Z] * (c); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef VSUB2
|
||||
#define VSUB2(a, b, c) { \
|
||||
(a)[X] = (b)[X] - (c)[X]; \
|
||||
(a)[Y] = (b)[Y] - (c)[Y]; \
|
||||
(a)[Z] = (b)[Z] - (c)[Z]; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef VCROSS
|
||||
#define VCROSS(a,b,c) { \
|
||||
(a)[X] = (b)[Y] * (c)[Z] - (b)[Z] * (c)[Y]; \
|
||||
(a)[Y] = (b)[Z] * (c)[X] - (b)[X] * (c)[Z]; \
|
||||
(a)[Z] = (b)[X] * (c)[Y] - (b)[Y] * (c)[X]; }
|
||||
#endif
|
||||
|
||||
#ifndef VMAGSQ
|
||||
#define VMAGSQ(a) (SQ((a)[X]) + SQ((a)[Y]) + SQ((a)[Z]))
|
||||
#endif
|
||||
|
||||
#ifndef VMAG
|
||||
#define VMAG(a) sqrt(VMAGSQ(a))
|
||||
#endif
|
||||
|
||||
#ifndef VUNITIZE
|
||||
#define VUNITIZE(a) { \
|
||||
register double _f = VMAGSQ(a); \
|
||||
_f = sqrt(_f); \
|
||||
if (!VM_NEAR(_f, 1.0, VM_UNITIZE_TOL)) { \
|
||||
if (_f < VM_DIVIDE_TOL) { \
|
||||
VINIT((a), 0.0); \
|
||||
} else { \
|
||||
_f = 1.0/_f; \
|
||||
(a)[X] *= _f; \
|
||||
(a)[Y] *= _f; \
|
||||
(a)[Z] *= _f; \
|
||||
} \
|
||||
}\
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef VM_NEAR
|
||||
#define VM_NEAR(v1,v2,tol) ((((v2) - (tol)) <= (v1)) && ((v1) <= ((v2) + (tol))))
|
||||
#endif
|
||||
|
||||
#ifndef VM_DIVIDE_TOL
|
||||
#define VM_DIVIDE_TOL (1.0e-20)
|
||||
#endif
|
||||
|
||||
#ifndef VM_UNITIZE_TOL
|
||||
#define VM_UNITIZE_TOL (1.0e-15)
|
||||
#endif
|
||||
|
||||
#ifndef DIST_PT_PT_SQ
|
||||
#define DIST_PT_PT_SQ(_a,_b) \
|
||||
SQ((_a)[X] - (_b)[X]) + \
|
||||
SQ((_a)[Y] - (_b)[Y]) + \
|
||||
SQ((_a)[Z] - (_b)[Z])
|
||||
#endif
|
||||
|
||||
#ifndef DIST_PT_PT
|
||||
#define DIST_PT_PT(_a,_b) sqrt(DIST_PT_PT_SQ(_a, _b))
|
||||
#endif
|
||||
|
||||
//******************************************************************************
|
||||
// NAME ideal_thread_count
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Determine the ideal number of threads to create for multithreading
|
||||
// applications, based on what is available on the target system.
|
||||
//******************************************************************************
|
||||
static inline
|
||||
unsigned ideal_thread_count()
|
||||
{
|
||||
int count = 0;
|
||||
#if defined(PTW32_VERSION) || defined(__hpux)
|
||||
count = pthread_num_processors_np();
|
||||
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
||||
size_t size=sizeof(count);
|
||||
count = (sysctlbyname("hw.ncpu",&count,&size,NULL,0)?0:count);
|
||||
#elif defined(BOOST_HAS_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN)
|
||||
count = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
#elif defined(_GNU_SOURCE)
|
||||
count = get_nprocs();
|
||||
#elif defined(WIN32)
|
||||
SYSTEM_INFO info={{0}};
|
||||
GetSystemInfo(&info);
|
||||
count = info.dwNumberOfProcessors;
|
||||
#endif
|
||||
return (unsigned) (count>0)?count:1;
|
||||
}
|
||||
|
||||
#ifndef COMPILE_FOR_VSL
|
||||
//******************************************************************************
|
||||
// NAME output_obj
|
||||
//
|
||||
// INPUTS
|
||||
// fp - file pointer to write
|
||||
// vertex - list of vertices
|
||||
// normal - list of normals
|
||||
// indices - list of indices that make up triangles
|
||||
// gnames - list of geometry names
|
||||
// offsets - list of offsets between geometry items
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Runs the given lists and creates an OBJ file that holds all the data.
|
||||
//******************************************************************************
|
||||
static inline
|
||||
void output_obj (FILE *fp,
|
||||
std::vector<float> &vertex,
|
||||
std::vector<float> &normal,
|
||||
std::vector<long> &indices,
|
||||
std::vector<std::string> &gnames,
|
||||
std::vector<long> &offsets)
|
||||
{
|
||||
long i;
|
||||
|
||||
/* output vertices */
|
||||
fprintf (fp, "g\n");
|
||||
for (i = 0; i < (long)vertex.size(); i += 3)
|
||||
fprintf (fp, "v %.4f %.4f %.4f\n",
|
||||
vertex[i], vertex[i+1], vertex[i+2]);
|
||||
fprintf (fp, "\n# %d vertices\n", (int)vertex.size()/3);
|
||||
|
||||
fprintf (fp, "\n# 0 vertex parms\n");
|
||||
fprintf (fp, "\n# 0 texture vertices\n");
|
||||
fprintf (fp, "\n");
|
||||
|
||||
/* output normals */
|
||||
fprintf (fp, "g\n");
|
||||
for (i = 0; i < (long)normal.size(); i += 3)
|
||||
fprintf (fp, "vn %.4f %.4f %.4f\n",
|
||||
normal[i], normal[i+1], normal[i+2]);
|
||||
fprintf (fp, "\n# %d normals\n", (int)normal.size()/3);
|
||||
fprintf (fp, "\n");
|
||||
|
||||
/* out geometries */
|
||||
for (i = 0; i < (long)gnames.size(); i++)
|
||||
{
|
||||
fprintf (fp, "g %s\n", gnames.at(i).c_str());
|
||||
fprintf (fp, "s off\n");
|
||||
|
||||
long end = (long)indices.size();
|
||||
if (i < ((long)gnames.size() -1))
|
||||
end = offsets[i+1];
|
||||
|
||||
/* add 1 to everything because OBJ indices are 1 based, not 0 */
|
||||
for (long j = offsets[i]; j < end; j += 3)
|
||||
fprintf (fp, "f %ld//%ld %ld//%ld %ld//%ld\n",
|
||||
(indices[j+0] +1), (indices[j+0] +1),
|
||||
(indices[j+1] +1), (indices[j+1] +1),
|
||||
(indices[j+2] +1), (indices[j+2] +1));
|
||||
fprintf (fp, "\n# %ld facets\n", end - offsets[i]);
|
||||
}
|
||||
fprintf (fp, "\n# %d elements\n", (int)gnames.size());
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// NAME output_brlcad
|
||||
//
|
||||
// INPUTS
|
||||
// ofile - BRL-CAD database file name
|
||||
// vertex - list of vertices
|
||||
// normal - list of normals
|
||||
// indices - list of indices that make up triangles
|
||||
// gnames - list of geometry names
|
||||
// offsets - list of offsets between geometry items
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Runs the given lists and creates a BRLCAD database that holds all the data.
|
||||
//******************************************************************************
|
||||
static inline
|
||||
void output_brlcad (char *ofile,
|
||||
std::vector<float> &vertex,
|
||||
std::vector<float> &normal,
|
||||
std::vector<long> &indices,
|
||||
std::vector<std::string> &gnames,
|
||||
std::vector<long> &offsets)
|
||||
{
|
||||
struct rt_wdb *db_fp;
|
||||
struct wmember wm_hd; /* defined in wdb.h */
|
||||
long i;
|
||||
unsigned char rgb[3]; /* region color (red) */
|
||||
|
||||
if ((db_fp = wdb_fopen(ofile)) == NULL)
|
||||
{
|
||||
perror(ofile);
|
||||
return;
|
||||
}
|
||||
|
||||
VSET(rgb, 255, 0, 0);
|
||||
mk_id(db_fp, ofile); /* create the database header record */
|
||||
|
||||
/* assume everything is in mm at this point */
|
||||
|
||||
/* output components (i.e. Primitives/Regions pairs) */
|
||||
for (i = 0; i < (long)gnames.size(); i++)
|
||||
{
|
||||
char name[255];
|
||||
fastf_t *vertices = NULL;
|
||||
fastf_t *normals = NULL;
|
||||
int *faces = NULL;
|
||||
int nverts = 0, nnrmls = 0, nfaces = 0;
|
||||
|
||||
std::string gname = gnames.at(i).c_str();
|
||||
std::size_t pos = gname.find(".");
|
||||
|
||||
/* remove '.r', if it exists */
|
||||
if (pos != std::string::npos)
|
||||
gname = gname.substr(0, pos);
|
||||
|
||||
memset (name, 0, sizeof (char) * 255);
|
||||
sprintf (name, "%s.s", gname.c_str());
|
||||
|
||||
long end = (long)indices.size();
|
||||
if (i < ((long)gnames.size() -1))
|
||||
end = offsets[i+1];
|
||||
|
||||
/* allocate array to hold face combinations */
|
||||
nfaces = (int) (end - offsets[i]);
|
||||
faces = (int *) malloc (sizeof (int) * nfaces);
|
||||
memset (faces, 0, sizeof (int) * nfaces);
|
||||
|
||||
/* vector to tell if index is already added to vert/nrml lists */
|
||||
std::vector<long> already;
|
||||
|
||||
/* add vertices, normals, and indices */
|
||||
for (long j = offsets[i]; j < end; j++)
|
||||
{
|
||||
long index = indices[j];
|
||||
long myidx = j - offsets[i];
|
||||
|
||||
if (std::find(already.begin(),
|
||||
already.end(), index) == already.end())
|
||||
{
|
||||
vertices = (fastf_t*) realloc ((void *) vertices, sizeof(fastf_t) * (nverts + 3));
|
||||
normals = (fastf_t*) realloc ((void *) normals, sizeof(fastf_t) * (nnrmls + 3));
|
||||
|
||||
vertices[nverts] = vertex[index*3+0]; ++nverts;
|
||||
vertices[nverts] = vertex[index*3+1]; ++nverts;
|
||||
vertices[nverts] = vertex[index*3+2]; ++nverts;
|
||||
|
||||
normals[nnrmls] = normal[index*3+0]; ++nnrmls;
|
||||
normals[nnrmls] = normal[index*3+1]; ++nnrmls;
|
||||
normals[nnrmls] = normal[index*3+2]; ++nnrmls;
|
||||
|
||||
already.push_back(index);
|
||||
|
||||
faces[myidx] = (nverts / 3) -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (long k = 0; k < (long)already.size(); k++)
|
||||
if (already.at(k) == index)
|
||||
{
|
||||
faces[myidx] = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
already.clear();
|
||||
|
||||
/* make a BOT primitive */
|
||||
mk_bot_w_normals(db_fp, name, RT_BOT_SOLID, RT_BOT_UNORIENTED, 0,
|
||||
(nverts / 3), (nfaces / 3), vertices, faces,
|
||||
(fastf_t *)NULL, (struct bu_bitv *)NULL,
|
||||
(nnrmls / 3), normals, faces);
|
||||
|
||||
/* Make a region that is the union of this one BOT object.
|
||||
* To accomplish this, we need to create a linked list of items
|
||||
* that make up the combination. The wm_hd structure serves as
|
||||
* the head of the list items.
|
||||
*/
|
||||
BU_LIST_INIT(&wm_hd.l);
|
||||
|
||||
/* Create a wmember structure for the item that we want
|
||||
* in the combination. The return from mk_addmember is a pointer
|
||||
* to the wmember structure.
|
||||
*/
|
||||
(void)mk_addmember(name, &wm_hd.l, NULL, WMOP_UNION);
|
||||
|
||||
/* Create the combination. In this case we are going to make it
|
||||
* a region, hence the is_region flag is set, and we provide shader
|
||||
* parameter information.
|
||||
*/
|
||||
memset (name, 0, sizeof (char) * 255);
|
||||
sprintf (name, "%s.r", gname.c_str());
|
||||
mk_lcomb(db_fp,
|
||||
name, /* name of db region */
|
||||
&wm_hd, /* list of elements & boolean operations */
|
||||
1, /* is_region flag */
|
||||
"plastic", /* optical shader (just guessed) */
|
||||
"di=.8 sp=.2", /* shader params (again guessing) */
|
||||
rgb, /* item color */
|
||||
0); /* inherit (override) flag */
|
||||
|
||||
if (vertices) free (vertices);
|
||||
if (normals) free (normals);
|
||||
if (faces) free (faces);
|
||||
}
|
||||
|
||||
wdb_close(db_fp);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// NAME output_fastgen
|
||||
//
|
||||
// INPUTS
|
||||
// fp - file pointer to write
|
||||
// vertex - list of vertices
|
||||
// indices - list of indices that make up triangles
|
||||
// gnames - list of geometry names
|
||||
// offsets - list of offsets between geometry items
|
||||
// modes - list of geometry modes
|
||||
// materials - list of geometry materials
|
||||
// thicknesses - list of geometry thicknesses
|
||||
// positions - list of geometry positions
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Runs the given lists and creates a FASTGEN file that holds all the data.
|
||||
//******************************************************************************
|
||||
static inline
|
||||
void output_fastgen (FILE *fp,
|
||||
std::vector<float> &vertex,
|
||||
std::vector<long> &indices,
|
||||
std::vector<std::string> &gnames,
|
||||
std::vector<long> &offsets,
|
||||
std::vector<int> &modes,
|
||||
std::vector<int> &materials,
|
||||
std::vector<float> &thicknesses,
|
||||
std::vector<int> &positions)
|
||||
{
|
||||
long i;
|
||||
int cID = 0;
|
||||
|
||||
/* output components (i.e. SECTIONs) */
|
||||
for (i = 0; i < (long)gnames.size(); i++)
|
||||
{
|
||||
std::string gname = gnames.at(i).c_str();
|
||||
std::size_t pos = gname.find(".");
|
||||
|
||||
/* pick 1st comp ID as the one to use */
|
||||
if (pos != std::string::npos)
|
||||
gname = gname.substr(0, pos);
|
||||
|
||||
/* convert name to number */
|
||||
if (isdigit (gname.c_str()[0]))
|
||||
cID = (int) atoi (gname.c_str());
|
||||
else cID++;
|
||||
|
||||
/* print SECTION card */
|
||||
fprintf (fp, "%-8s%8d%8d%8d%8d\n", "SECTION", (cID / 1000),
|
||||
(cID % 1000), modes.at(i), 1);
|
||||
|
||||
long end = (long) indices.size();
|
||||
if (i < ((long) gnames.size() -1))
|
||||
end = offsets[i+1];
|
||||
|
||||
/* print GRID cards */
|
||||
for (long j = 0, id = 1; j < (long)vertex.size(); j+=3, id++)
|
||||
{
|
||||
float x = vertex[j+0];
|
||||
float y = vertex[j+1];
|
||||
float z = vertex[j+2];
|
||||
|
||||
fprintf (fp, "%-8s%8d%8s%8.2f%8.2f%8.2f\n", "GRID", (int) id, " ",
|
||||
x, y, z);
|
||||
}
|
||||
|
||||
/* print CTRI cards */
|
||||
/* add 1 to everything because FASTGEN indices are 1 based, not 0 */
|
||||
for (long j = offsets[i], id = 1; j < end; j += 3, id++)
|
||||
{
|
||||
fprintf (fp, "%-8s%8d%8d%8ld%8ld%8ld%8s%8.2f%8d\n", "CTRI", (int) id,
|
||||
materials.at(i),
|
||||
indices[j+0] +1,
|
||||
indices[j+1] +1,
|
||||
indices[j+2] +1,
|
||||
" ", thicknesses.at(i),
|
||||
positions.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (fp, "%-8s\n", "ENDDATA");
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// NAME output_vrml
|
||||
//
|
||||
// INPUTS
|
||||
// fp - file pointer to write
|
||||
// vertex - list of vertices
|
||||
// normal - list of normals
|
||||
// indices - list of indices that make up triangles
|
||||
// gnames - list of geometry names
|
||||
// offsets - list of offsets between geometry items
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Runs the given lists and creates a VRML file that holds all the data.
|
||||
//******************************************************************************
|
||||
static inline
|
||||
void output_vrml (FILE *fp,
|
||||
std::vector<float> &vertex,
|
||||
std::vector<float> &normal,
|
||||
std::vector<long> &indices,
|
||||
std::vector<std::string> &gnames,
|
||||
std::vector<long> &offsets)
|
||||
{
|
||||
long i;
|
||||
int cID = 0;
|
||||
|
||||
fprintf (fp, "#VRML V2.0 utf8\n");
|
||||
|
||||
/* output components (i.e. Shapes) */
|
||||
for (i = 0; i < (long)gnames.size(); i++)
|
||||
{
|
||||
std::string gname = gnames.at(i).c_str();
|
||||
std::size_t pos = gname.find(".");
|
||||
|
||||
/* pick 1st comp ID as the one to use */
|
||||
if (pos != std::string::npos)
|
||||
gname = gname.substr(0, pos);
|
||||
|
||||
/* convert name to number */
|
||||
if (isdigit (gname.c_str()[0]))
|
||||
cID = (int) atoi (gname.c_str());
|
||||
else cID++;
|
||||
|
||||
/* print Shape header */
|
||||
fprintf (fp, "DEF comp_%d Shape {\n", cID);
|
||||
fprintf (fp, "\t# Component_ID: %s\n\n", gname.c_str());
|
||||
|
||||
/* print Geometry header */
|
||||
fprintf (fp, "\tgeometry IndexedFaceSet {\n");
|
||||
fprintf (fp, "\t\tcoord Coordinate {\n");
|
||||
fprintf (fp, "\t\t\tpoint [\n");
|
||||
|
||||
long end = (long) indices.size();
|
||||
if (i < ((long) gnames.size() -1))
|
||||
end = offsets[i+1];
|
||||
|
||||
/* print points */
|
||||
for (long j = 0, id = 0; j < (long)vertex.size(); j+=3, id++)
|
||||
{
|
||||
float x = vertex[j+0];
|
||||
float y = vertex[j+1];
|
||||
float z = vertex[j+2];
|
||||
|
||||
fprintf (fp, "\t\t\t\t%.3f %.3f %.3f, # point %d\n", x, y, z, (int) id);
|
||||
}
|
||||
|
||||
fprintf (fp, "\t\t\t]\n"); /* close point */
|
||||
fprintf (fp, "\t\t}\n"); /* close coord */
|
||||
|
||||
fprintf (fp, "\t\tcoordIndex [\n");
|
||||
for (long j = offsets[i]; j < end; j += 3)
|
||||
{
|
||||
fprintf (fp, "\t\t\t%ld, %ld, %ld, -1\n",
|
||||
indices[j+0], indices[j+1], indices[j+2]);
|
||||
}
|
||||
fprintf (fp, "\t\t]\n"); /* close coordIndex */
|
||||
|
||||
fprintf (fp, "\t\tnormalPerVertex FALSE\n");
|
||||
fprintf (fp, "\t\tconvex TRUE\n");
|
||||
fprintf (fp, "\t\tcreaseAngle 0.5\n");
|
||||
fprintf (fp, "\t\tsolid FALSE\n");
|
||||
fprintf (fp, "\t}\n"); /* close geometry */
|
||||
fprintf (fp, "}\n"); /* close Shape */
|
||||
}
|
||||
}
|
||||
#endif // COMPILE_FOR_VSL
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
#define M3D_VectorZero(x) ({(x)[0]=0.0;(x)[1]=0.0;(x)[2]=0.0;})
|
||||
#define M3D_VectorMagnitude(x) (sqrt((x)[0]*(x)[0]+(x)[1]*(x)[1]+(x)[2]*(x)[2]))
|
||||
#define M3D_VectorCopy(x,y) ({(x)[0]=(y)[0];(x)[1]=(y)[1];(x)[2]=(y)[2];})
|
||||
#define M3D_VectorAdd(x,y) (x)[0]+=(y)[0];(x)[1]+=(y)[1];(x)[2]+=(y)[2]
|
||||
#define M3D_VectorAddStore(x,y,z) (x)[0]=(y)[0]+(z)[0];(x)[1]=(y)[1]+(z)[1];(x)[2]=(y)[2]+(z)[2]
|
||||
#define M3D_VectorAddMulScalar(x,y,z) (x)[0]+=(y)[0]*(z);(x)[1]+=(y)[1]*(z);(x)[2]+=(y)[2]*(z)
|
||||
#define M3D_VectorAddMul(x,y,z) (x)[0]+=(y)[0]*(z)[0];(x)[1]+=(y)[1]*(z)[1];(x)[2]+=(y)[2]*(z)[2]
|
||||
#define M3D_VectorSub(x,y) (x)[0]-=(y)[0];(x)[1]-=(y)[1];(x)[2]-=(y)[2]
|
||||
#define M3D_VectorSubStore(x,y,z) (x)[0]=(y)[0]-(z)[0];(x)[1]=(y)[1]-(z)[1];(x)[2]=(y)[2]-(z)[2]
|
||||
#define M3D_VectorSubMulScalar(x,y,z) (x)[0]-=(y)[0]*(z);(x)[1]-=(y)[1]*(z);(x)[2]-=(y)[2]*(z)
|
||||
#define M3D_VectorSubMul(x,y,z) (x)[0]-=(y)[0]*(z)[0];(x)[1]-=(y)[1]*(z)[1];(x)[2]-=(y)[2]*(z)[2]
|
||||
#define M3D_VectorMul(x,y) (x)[0]*=(y)[0];(x)[1]*=(y)[1];(x)[2]*=(y)[2]
|
||||
#define M3D_VectorMulStore(x,y,z) (x)[0]=(y)[0]*(z)[0];(x)[1]=(y)[1]*(z)[1];(x)[2]=(y)[2]*(z)[2]
|
||||
#define M3D_VectorMulScalar(x,y) (x)[0]*=(y);(x)[1]*=(y);(x)[2]*=(y)
|
||||
#define M3D_VectorMulScalarStore(x,y,z) (x)[0]=(y)[0]*(z);(x)[1]=(y)[1]*(z);(x)[2]=(y)[2]*(z)
|
||||
#define M3D_VectorDiv(x,y) (x)[0]/=(y)[0];(x)[1]/=(y)[1];(x)[2]/=(y)[2]
|
||||
#define M3D_VectorDivStore(x,y,z) (x)[0]=(y)[0]/(z)[0];(x)[1]=(y)[1]/(z)[1];(x)[2]=(y)[2]/(z)[2]
|
||||
#define M3D_VectorDotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
|
||||
#define M3D_PlanePoint(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3])
|
||||
#define M3D_VectorNormalize(x) ({typeof(*(x)) _f;_f=1.0/sqrt((x)[0]*(x)[0]+(x)[1]*(x)[1]+(x)[2]*(x)[2]);(x)[0]*=_f;(x)[1]*=_f;(x)[2]*=_f;})
|
||||
|
||||
#define M3D_VectorCrossProduct(x,y,z) ({(x)[0]=((y)[1]*(z)[2])-((y)[2]*(z)[1]);(x)[1]=((y)[2]*(z)[0])-((y)[0]*(z)[2]);(x)[2]=((y)[0]*(z)[1])-((y)[1]*(z)[0]);})
|
||||
#define M3D_VectorAddCrossProduct(x,y,z) ({(x)[0]+=((y)[1]*(z)[2])-((y)[2]*(z)[1]);(x)[1]+=((y)[2]*(z)[0])-((y)[0]*(z)[2]);(x)[2]+=((y)[0]*(z)[1])-((y)[1]*(z)[0]);})
|
||||
#define M3D_VectorSubCrossProduct(x,y,z) ({(x)[0]-=((y)[1]*(z)[2])-((y)[2]*(z)[1]);(x)[1]-=((y)[2]*(z)[0])-((y)[0]*(z)[2]);(x)[2]-=((y)[0]*(z)[1])-((y)[1]*(z)[0]);})
|
||||
|
||||
#define M3D_MatrixMulVector(d,p,m) ({ \
|
||||
(d)[0]=(p)[0]*(m)[0*4+0]+(p)[1]*(m)[1*4+0]+(p)[2]*(m)[2*4+0]; \
|
||||
(d)[1]=(p)[0]*(m)[0*4+1]+(p)[1]*(m)[1*4+1]+(p)[2]*(m)[2*4+1]; \
|
||||
(d)[2]=(p)[0]*(m)[0*4+2]+(p)[1]*(m)[1*4+2]+(p)[2]*(m)[2*4+2]; })
|
||||
|
||||
#define M3D_MatrixTransMulVector(d,p,m) ({ \
|
||||
(d)[0]=(p)[0]*(m)[0*4+0]+(p)[1]*(m)[0*4+1]+(p)[2]*(m)[0*4+2]; \
|
||||
(d)[1]=(p)[0]*(m)[1*4+0]+(p)[1]*(m)[1*4+1]+(p)[2]*(m)[1*4+2]; \
|
||||
(d)[2]=(p)[0]*(m)[2*4+0]+(p)[1]*(m)[2*4+1]+(p)[2]*(m)[2*4+2]; })
|
||||
|
||||
#define M3D_MatrixMulVectorSelf(p,m) ({ \
|
||||
typeof(*(p)) _n[3] = { p[0], p[1], p[2] }; \
|
||||
(p)[0]=(_n)[0]*(m)[0*4+0]+(_n)[1]*(m)[1*4+0]+(_n)[2]*(m)[2*4+0]; \
|
||||
(p)[1]=(_n)[0]*(m)[0*4+1]+(_n)[1]*(m)[1*4+1]+(_n)[2]*(m)[2*4+1]; \
|
||||
(p)[2]=(_n)[0]*(m)[0*4+2]+(_n)[1]*(m)[1*4+2]+(_n)[2]*(m)[2*4+2]; })
|
||||
|
||||
#define M3D_MatrixMulPoint(d,p,m) ({ \
|
||||
(d)[0]=(p)[0]*(m)[0*4+0]+(p)[1]*(m)[1*4+0]+(p)[2]*(m)[2*4+0]+(m)[3*4+0]; \
|
||||
(d)[1]=(p)[0]*(m)[0*4+1]+(p)[1]*(m)[1*4+1]+(p)[2]*(m)[2*4+1]+(m)[3*4+1]; \
|
||||
(d)[2]=(p)[0]*(m)[0*4+2]+(p)[1]*(m)[1*4+2]+(p)[2]*(m)[2*4+2]+(m)[3*4+2]; })
|
||||
|
||||
#define M3D_MatrixMulPointSelf(p,m) ({ \
|
||||
typeof(*(p)) _n[3] = { p[0], p[1], p[2] }; \
|
||||
(p)[0]=(_n)[0]*(m)[0*4+0]+(_n)[1]*(m)[1*4+0]+(_n)[2]*(m)[2*4+0]+(m)[3*4+0]; \
|
||||
(p)[1]=(_n)[0]*(m)[0*4+1]+(_n)[1]*(m)[1*4+1]+(_n)[2]*(m)[2*4+1]+(m)[3*4+1]; \
|
||||
(p)[2]=(_n)[0]*(m)[0*4+2]+(_n)[1]*(m)[1*4+2]+(_n)[2]*(m)[2*4+2]+(m)[3*4+2]; })
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,776 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Global memory management header.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MM_H
|
||||
#define MM_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define MM_DEBUG 0
|
||||
|
||||
#define MM_INLINE_LIST_FUNCTIONS
|
||||
|
||||
#define MM_ALLOC_CHECK
|
||||
|
||||
|
||||
#define MM_DEBUG_GUARD_BYTES (32)
|
||||
#define MM_DEBUG_MMAP (1)
|
||||
/* Enabling this will lead to ever growing memory usage! Strictly for debugging. */
|
||||
#define MM_DEBUG_MMAP_LINGERING (0)
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
#ifdef MM_NUMA
|
||||
#include <numa.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__linux__) || defined(__gnu_linux__) || defined(__linux) || defined(__linux)
|
||||
#define MM_LINUX (1)
|
||||
#define MM_UNIX (1)
|
||||
#elif defined(__APPLE__)
|
||||
#define MM_OSX (1)
|
||||
#define MM_UNIX (1)
|
||||
#elif defined(__unix__) || defined(__unix) || defined(unix)
|
||||
#define MM_UNIX (1)
|
||||
#elif defined(_WIN64) || defined(__WIN64__) || defined(WIN64)
|
||||
#define MM_WIN64 (1)
|
||||
#define MM_WIN32 (1)
|
||||
#define MM_WINDOWS (1)
|
||||
#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
|
||||
#define MM_WIN32 (1)
|
||||
#define MM_WINDOWS (1)
|
||||
#endif
|
||||
|
||||
#if __MINGW64__
|
||||
#define MM_MINGW32 (1)
|
||||
#define MM_MINGW64 (1)
|
||||
#elif __MINGW32__
|
||||
#define MM_MINGW32 (1)
|
||||
#endif
|
||||
|
||||
|
||||
#if !MM_UNIX
|
||||
#undef MM_DEBUG_MMAP
|
||||
#define MM_DEBUG_MMAP (0)
|
||||
#endif
|
||||
|
||||
|
||||
#define MM_CPU_COUNT_MAXIMUM (1024)
|
||||
#define MM_NODE_COUNT_MAXIMUM (256)
|
||||
|
||||
|
||||
#ifndef CPUCONF_CACHE_LINE_SIZE
|
||||
#define CPUCONF_CACHE_LINE_SIZE 64
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define MM_CACHE_ALIGN __attribute__((aligned(CPUCONF_CACHE_LINE_SIZE)))
|
||||
#define MM_RESTRICT __restrict
|
||||
#define MM_NOINLINE __attribute__((noinline))
|
||||
#else
|
||||
#define MM_CACHE_ALIGN
|
||||
#define MM_RESTRICT
|
||||
#define MM_NOINLINE
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
|
||||
#define MM_ALIGN16 __attribute__((aligned(16)))
|
||||
#define MM_ALIGN16_SAFE (1)
|
||||
#elif defined(_MSC_VER)
|
||||
#define MM_ALIGN16 __declspec(align(16))
|
||||
#define MM_ALIGN16_SAFE (1)
|
||||
#else
|
||||
#define MM_ALIGN16
|
||||
#define MM_ALIGN16_SAFE (0)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define MM_ERROR() {printf("MM Error at %s:%d\n",file,line);exit(1)}
|
||||
|
||||
#ifndef ADDRESS
|
||||
#define ADDRESS(p,o) ((void *)(((char *)p)+(o)))
|
||||
#endif
|
||||
|
||||
#ifndef ADDRESSDIFF
|
||||
#define ADDRESSDIFF(a,b) (((char *)a)-((char *)b))
|
||||
#endif
|
||||
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef __WIN32__
|
||||
int mmGetTimeOfDay( struct timeval *tv );
|
||||
#define gettimeofday(a,b) mmGetTimeOfDay(a)
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numaflag;
|
||||
int pagesize;
|
||||
int cpucount;
|
||||
int nodecount;
|
||||
int cpunode[MM_CPU_COUNT_MAXIMUM];
|
||||
int64_t nodesize[MM_NODE_COUNT_MAXIMUM];
|
||||
int nodecpucount[MM_NODE_COUNT_MAXIMUM];
|
||||
int64_t sysmemory;
|
||||
} mmContext;
|
||||
|
||||
extern mmContext mmcontext;
|
||||
|
||||
|
||||
#include "mmatomic.h"
|
||||
#include "mmthread.h"
|
||||
|
||||
|
||||
#if MM_DEBUG
|
||||
#define MM_FUNC(n) mm##n##Debug
|
||||
#define MM_PARAMS , char *file, int line
|
||||
#else
|
||||
#define MM_FUNC(n) mm##n
|
||||
#define MM_PARAMS
|
||||
#endif
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
void mmInit();
|
||||
void mmEnd();
|
||||
|
||||
|
||||
void mmThreadBindToNode( int nodeindex );
|
||||
void mmThreadBindToNode( int nodeindex );
|
||||
void mmThreadBindToCpu( int cpuindex );
|
||||
int mmCpuGetNode( int cpuindex );
|
||||
|
||||
void *mmNodeAlloc( int nodeindex, size_t size );
|
||||
void mmNodeFree( int nodeindex, void *v, size_t size );
|
||||
void mmNodeMap( int nodeindex, void *start, size_t bytes );
|
||||
|
||||
void *mmNodeAlignAlloc( int nodeindex, size_t size, intptr_t align );
|
||||
void mmNodeAlignFree( int nodeindex, void *v, size_t size );
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void **prev;
|
||||
void *next;
|
||||
} mmListNode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *first;
|
||||
void **last;
|
||||
} mmListDualHead;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *first;
|
||||
void *last;
|
||||
} mmListLoopHead;
|
||||
|
||||
#ifndef MM_INLINE_LIST_FUNCTIONS
|
||||
|
||||
void mmListAdd( void **list, void *item, intptr_t offset );
|
||||
void mmListRemove( void *item, intptr_t offset );
|
||||
void mmListMergeList( void **listdst, void **listsrc, intptr_t offset );
|
||||
void mmListMoveList( void **listdst, void **listsrc, intptr_t offset );
|
||||
|
||||
void mmListDualInit( mmListDualHead *head );
|
||||
void mmListDualAddFirst( mmListDualHead *head, void *item, intptr_t offset );
|
||||
void mmListDualAddLast( mmListDualHead *head, void *item, intptr_t offset );
|
||||
void mmListDualRemove( mmListDualHead *head, void *item, intptr_t offset );
|
||||
void *mmListDualLast( mmListDualHead *head, intptr_t offset );
|
||||
|
||||
#else
|
||||
|
||||
static inline void mmListAdd( void **list, void *item, intptr_t offset )
|
||||
{
|
||||
mmListNode *node, *next;
|
||||
node = ADDRESS( item, offset );
|
||||
node->prev = list;
|
||||
node->next = *list;
|
||||
if( *list )
|
||||
{
|
||||
next = ADDRESS( *list, offset );
|
||||
next->prev = &(node->next);
|
||||
}
|
||||
*list = item;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mmListRemove( void *item, intptr_t offset )
|
||||
{
|
||||
mmListNode *node, *next;
|
||||
node = ADDRESS( item, offset );
|
||||
*(node->prev) = (void *)node->next;
|
||||
if( node->next )
|
||||
{
|
||||
next = ADDRESS( node->next, offset );
|
||||
next->prev = node->prev;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mmListMergeList( void **listdst, void **listsrc, intptr_t offset )
|
||||
{
|
||||
void *item;
|
||||
mmListNode *node;
|
||||
if( !( *listsrc ) )
|
||||
return;
|
||||
for( item = *listdst ; item ; item = node->next )
|
||||
{
|
||||
node = ADDRESS( item, offset );
|
||||
listdst = &node->next;
|
||||
}
|
||||
item = *listsrc;
|
||||
node = ADDRESS( item, offset );
|
||||
node->prev = listdst;
|
||||
*listdst = item;
|
||||
*listsrc = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mmListMoveList( void **listdst, void **listsrc, intptr_t offset )
|
||||
{
|
||||
void *item;
|
||||
mmListNode *node;
|
||||
if( !( *listsrc ) )
|
||||
{
|
||||
*listdst = 0;
|
||||
return;
|
||||
}
|
||||
item = *listsrc;
|
||||
node = ADDRESS( item, offset );
|
||||
node->prev = listdst;
|
||||
*listdst = item;
|
||||
*listsrc = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mmListDualInit( mmListDualHead *head )
|
||||
{
|
||||
head->first = 0;
|
||||
head->last = &head->first;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mmListDualAddFirst( mmListDualHead *head, void *item, intptr_t offset )
|
||||
{
|
||||
mmListNode *node, *next;
|
||||
node = ADDRESS( item, offset );
|
||||
node->prev = &head->first;
|
||||
node->next = head->first;
|
||||
if( node->next )
|
||||
{
|
||||
next = ADDRESS( node->next, offset );
|
||||
next->prev = &(node->next);
|
||||
}
|
||||
else
|
||||
head->last = &(node->next);
|
||||
head->first = item;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mmListDualAddLast( mmListDualHead *head, void *item, intptr_t offset )
|
||||
{
|
||||
mmListNode *node;
|
||||
void **prev;
|
||||
prev = head->last;
|
||||
*prev = item;
|
||||
node = ADDRESS( item, offset );
|
||||
node->prev = head->last;
|
||||
head->last = &(node->next);
|
||||
node->next = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mmListDualRemove( mmListDualHead *head, void *item, intptr_t offset )
|
||||
{
|
||||
mmListNode *node, *next;
|
||||
node = ADDRESS( item, offset );
|
||||
*(node->prev) = (void *)node->next;
|
||||
if( node->next )
|
||||
{
|
||||
next = ADDRESS( node->next, offset );
|
||||
next->prev = node->prev;
|
||||
}
|
||||
else
|
||||
head->last = node->prev;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void *mmListDualLast( mmListDualHead *head, intptr_t offset )
|
||||
{
|
||||
if( !( head->first ) )
|
||||
return 0;
|
||||
return ADDRESS( head->last, -( offset + offsetof(mmListNode,next) ) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void mmListLoopInit( mmListLoopHead *head );
|
||||
void mmListLoopAddFirst( mmListLoopHead *head, void *item, intptr_t offset );
|
||||
void mmListLoopAddLast( mmListLoopHead *head, void *item, intptr_t offset );
|
||||
void mmListLoopInsert( mmListLoopHead *head, void *previtem, void *item, intptr_t offset );
|
||||
void mmListLoopRemove( mmListLoopHead *head, void *item, intptr_t offset );
|
||||
void *mmListLoopLast( mmListLoopHead *head, intptr_t offset );
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *child[2];
|
||||
void *parent;
|
||||
int flags;
|
||||
} mmBTreeNode;
|
||||
|
||||
#define MM_BTREE_FLAGS_LEFT (0)
|
||||
#define MM_BTREE_FLAGS_RIGHT (1)
|
||||
#define MM_BTREE_FLAGS_DIRECTION_MASK (1)
|
||||
#define MM_BTREE_FLAGS_STEP (2)
|
||||
|
||||
void mmBTreeInsert( void *item, void *parent, int itemflag, intptr_t offset, void **root );
|
||||
void mmBTreeRemove( void *item, intptr_t offset, void **root );
|
||||
|
||||
void *mmBtreeMostLeft( void *root, intptr_t offset );
|
||||
void *mmBtreeMostRight( void *root, intptr_t offset );
|
||||
void *mmBtreeNeighbourLeft( void *item, intptr_t offset );
|
||||
void *mmBtreeNeighbourRight( void *item, intptr_t offset );
|
||||
intptr_t mmBtreeItemCount( void *root, intptr_t offset );
|
||||
int mmBtreeListOrdered( void *root, intptr_t offset, int (*callback)( void *item, void *v ), void *v );
|
||||
int mmBtreeListBalanced( void *root, intptr_t offset, int (*callback)( void *item, void *v ), void *v );
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mmListNode listnode;
|
||||
mmBTreeNode node;
|
||||
int freecount;
|
||||
int blockindex;
|
||||
} mmBlock;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *blocklist;
|
||||
void *freelist;
|
||||
size_t chunksize;
|
||||
int chunkperblock;
|
||||
int alignment;
|
||||
size_t allocsize;
|
||||
int keepfreecount;
|
||||
int chunkfreecount;
|
||||
void *treeroot;
|
||||
void *(*relayalloc)( void *head, size_t bytes MM_PARAMS );
|
||||
void (*relayfree)( void *head, void *v, size_t bytes MM_PARAMS );
|
||||
void *relayvalue;
|
||||
mtSpin spinlock;
|
||||
} mmBlockHead;
|
||||
|
||||
void MM_FUNC(BlockInit)( mmBlockHead *head, size_t chunksize, int chunkperblock, int keepfreecount, int alignment MM_PARAMS );
|
||||
void MM_FUNC(BlockNodeInit)( mmBlockHead *head, int nodeindex, size_t chunksize, int chunkperblock, int keepfreecount, int alignment MM_PARAMS );
|
||||
void *MM_FUNC(BlockAlloc)( mmBlockHead *head MM_PARAMS );
|
||||
void MM_FUNC(BlockRelease)( mmBlockHead *head, void *v MM_PARAMS );
|
||||
void MM_FUNC(BlockFree)( mmBlockHead *head, void *v MM_PARAMS );
|
||||
void MM_FUNC(BlockFreeAll)( mmBlockHead *head MM_PARAMS );
|
||||
void MM_FUNC(BlockProcessList)( mmBlockHead *head, void *userpointer, int (*processchunk)( void *chunk, void *userpointer ) MM_PARAMS );
|
||||
int MM_FUNC(BlockUseCount)( mmBlockHead *head MM_PARAMS );
|
||||
int MM_FUNC(BlockFreeCount)( mmBlockHead *head MM_PARAMS );
|
||||
|
||||
#if MM_DEBUG
|
||||
#define mmBlockInit(v,w,x,y,z) MM_FUNC(BlockInit)(v,w,x,y,z,__FILE__,__LINE__)
|
||||
#define mmBlockNodeInit(u,v,w,x,y,z) MM_FUNC(BlockNodeInit)(u,v,w,x,y,z,__FILE__,__LINE__)
|
||||
#define mmBlockAlloc(x) MM_FUNC(BlockAlloc)(x,__FILE__,__LINE__)
|
||||
#define mmBlockRelease(x,y) MM_FUNC(BlockRelease)(x,y,__FILE__,__LINE__)
|
||||
#define mmBlockFree(x,y) MM_FUNC(BlockFree)(x,y,__FILE__,__LINE__)
|
||||
#define mmBlockFreeAll(x) MM_FUNC(BlockFreeAll)(x,__FILE__,__LINE__)
|
||||
#define mmBlockProcessList(x,y,z) MM_FUNC(BlockProcessList)(x,y,z,__FILE__,__LINE__)
|
||||
#define mmBlockUseCount(x) MM_FUNC(BlockProcessList)(x,__FILE__,__LINE__)
|
||||
#define mmBlockFreeCount(x) MM_FUNC(BlockProcessList)(x,__FILE__,__LINE__)
|
||||
#endif
|
||||
|
||||
/*
|
||||
void mmBlockRelayByVolume( mmBlockHead *head, void *volumehead );
|
||||
void mmBlockRelayByZone( mmBlockHead *head, void *zonehead );
|
||||
*/
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mmBlockHead indexblock;
|
||||
void *indextree;
|
||||
intptr_t indexlimit;
|
||||
mtSpin spinlock;
|
||||
} mmIndexHead;
|
||||
|
||||
void mmIndexInit( mmIndexHead *head, int indexesperblock );
|
||||
void mmIndexFreeAll( mmIndexHead *head );
|
||||
void mmIndexAdd( mmIndexHead *head, intptr_t index );
|
||||
intptr_t mmIndexGet( mmIndexHead *head );
|
||||
int mmIndexRemove( mmIndexHead *head, intptr_t index );
|
||||
size_t mmIndexCount( mmIndexHead *head );
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uintptr_t bitmask;
|
||||
int bitshift;
|
||||
uintptr_t countalign;
|
||||
uintptr_t indexshift;
|
||||
uintptr_t indexmask;
|
||||
uintptr_t initmask;
|
||||
size_t mapsize;
|
||||
uintptr_t *map;
|
||||
mtSpin spinlock;
|
||||
} mmBitTableHead;
|
||||
|
||||
void mmBitTableInit( mmBitTableHead *head, int bitsperentry, int chunksize, int initmask );
|
||||
void mmBitTableFreeAll( mmBitTableHead *head );
|
||||
void mmBitTableSet( mmBitTableHead *head, uintptr_t index, int flags, int editmask );
|
||||
uintptr_t mmBitTableGet( mmBitTableHead *head, uintptr_t index );
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t size;
|
||||
size_t used;
|
||||
void *next;
|
||||
} mmGrowNode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mmGrowNode *first;
|
||||
size_t nodesize;
|
||||
mtSpin spinlock;
|
||||
} mmGrow;
|
||||
|
||||
int MM_FUNC(GrowInit)( mmGrow *mgrow, size_t nodesize MM_PARAMS );
|
||||
void MM_FUNC(GrowFreeAll)( mmGrow *mgrow MM_PARAMS );
|
||||
void *MM_FUNC(GrowAlloc)( mmGrow *mgrow, size_t bytes MM_PARAMS );
|
||||
|
||||
#if MM_DEBUG
|
||||
#define mmGrowInit(x,y) MM_FUNC(GrowInit)(x,y,__FILE__,__LINE__)
|
||||
#define mmGrowFreeAll(x) MM_FUNC(GrowFreeAll)(x,__FILE__,__LINE__)
|
||||
#define mmGrowAlloc(x,y) MM_FUNC(GrowAlloc)(x,y,__FILE__,__LINE__)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void ***table;
|
||||
intptr_t pagecount;
|
||||
intptr_t pagesize;
|
||||
intptr_t pagemask;
|
||||
intptr_t pageshift;
|
||||
mtSpin spinlock;
|
||||
} mmDirectory;
|
||||
|
||||
#define MM_DIR_ENTRY(dir,index) ( (dir)->table[ index >> (dir)->pageshift ][ index & (dir)->pagemask ] )
|
||||
|
||||
int MM_FUNC(DirInit)( mmDirectory *dir, intptr_t pageshift, intptr_t pagecount MM_PARAMS );
|
||||
void MM_FUNC(DirSize)( mmDirectory *dir, intptr_t size MM_PARAMS );
|
||||
void MM_FUNC(DirSet)( mmDirectory *dir, intptr_t index, void *entry MM_PARAMS );
|
||||
void *MM_FUNC(DirGet)( mmDirectory *dir, intptr_t index MM_PARAMS );
|
||||
void MM_FUNC(DirSetFast)( mmDirectory *dir, intptr_t index, void *entry MM_PARAMS );
|
||||
void *MM_FUNC(DirGetFast)( mmDirectory *dir, intptr_t index MM_PARAMS );
|
||||
void MM_FUNC(DirFree)( mmDirectory *dir MM_PARAMS );
|
||||
|
||||
#if MM_DEBUG
|
||||
#define mmDirInit(x,y,z) MM_FUNC(DirInit)(x,y,z,__FILE__,__LINE__)
|
||||
#define mmDirSize(x,y) MM_FUNC(DirSize)(x,y,__FILE__,__LINE__)
|
||||
#define mmDirSet(x,y,z) MM_FUNC(DirSet)(x,y,z,__FILE__,__LINE__)
|
||||
#define mmDirGet(x,y) MM_FUNC(DirGet)(x,y,__FILE__,__LINE__)
|
||||
#define mmDirSetFast(x,y,z) MM_FUNC(DirSetFast)(x,y,z,__FILE__,__LINE__)
|
||||
#define mmDirGetFast(x,y) MM_FUNC(DirGetFast)(x,y,__FILE__,__LINE__)
|
||||
#define mmDirFree(x) MM_FUNC(DirFree)(x,__FILE__,__LINE__)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
void *MM_FUNC(AlignAlloc)( size_t bytes, intptr_t align MM_PARAMS );
|
||||
void MM_FUNC(AlignFree)( void *v MM_PARAMS );
|
||||
void *MM_FUNC(AlignGrow)( void *v, size_t bytes, size_t copybytes, intptr_t align MM_PARAMS );
|
||||
void *MM_FUNC(AlignRelayAlloc)( void *(*relayalloc)( void *head, size_t bytes MM_PARAMS ), void *relayvalue, size_t bytes, intptr_t align, size_t displacement MM_PARAMS );
|
||||
void MM_FUNC(AlignRelayFree)( void (*relayfree)( void *head, void *v, size_t bytes MM_PARAMS ), void *relayvalue, void *v, size_t bytes MM_PARAMS );
|
||||
|
||||
#if MM_DEBUG
|
||||
#define mmAlignAlloc(x,y) MM_FUNC(AlignAlloc)(x,y,__FILE__,__LINE__)
|
||||
#define mmAlignFree(x) MM_FUNC(AlignFree)(x,__FILE__,__LINE__)
|
||||
#define mmAlignGrow(x) MM_FUNC(AlignGrow)(x,__FILE__,__LINE__)
|
||||
#define mmAlignRelayAlloc(v,w,x,y,z) MM_FUNC(AlignRelayAlloc)(v,w,x,y,z,__FILE__,__LINE__)
|
||||
#define mmAlignRelayFree(w,x,y,z) MM_FUNC(AlignRelayFree)(w,x,y,z,__FILE__,__LINE__)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t volumesize;
|
||||
size_t volumeblocksize;
|
||||
size_t minchunksize;
|
||||
size_t volumechunksize;
|
||||
size_t keepfreesize;
|
||||
size_t totalfreesize;
|
||||
size_t alignment;
|
||||
void *freeroot;
|
||||
void *volumelist;
|
||||
void *(*relayalloc)( void *head, size_t bytes MM_PARAMS );
|
||||
void (*relayfree)( void *head, void *v, size_t bytes MM_PARAMS );
|
||||
void *relayvalue;
|
||||
mtSpin spinlock;
|
||||
} mmVolumeHead;
|
||||
|
||||
void MM_FUNC(VolumeInit)( mmVolumeHead *head, size_t volumesize, size_t minchunksize, size_t keepfreesize, size_t alignment MM_PARAMS );
|
||||
void MM_FUNC(VolumeNodeInit)( mmVolumeHead *head, int nodeindex, size_t volumesize, size_t minchunksize, size_t keepfreesize, size_t alignment MM_PARAMS );
|
||||
void *MM_FUNC(VolumeAlloc)( mmVolumeHead *head, size_t bytes MM_PARAMS );
|
||||
void MM_FUNC(VolumeRelease)( mmVolumeHead *head, void *v MM_PARAMS );
|
||||
void MM_FUNC(VolumeFree)( mmVolumeHead *head, void *v MM_PARAMS );
|
||||
void MM_FUNC(VolumeShrink)( mmVolumeHead *head, void *v, size_t bytes MM_PARAMS );
|
||||
size_t MM_FUNC(VolumeGetAllocSize)( mmVolumeHead *head, void *v );
|
||||
void MM_FUNC(VolumeClean)( mmVolumeHead *head MM_PARAMS );
|
||||
void MM_FUNC(VolumeFreeAll)( mmVolumeHead *head MM_PARAMS );
|
||||
void *MM_FUNC(VolumeRealloc)( mmVolumeHead *head, void *v, size_t bytes MM_PARAMS );
|
||||
|
||||
#if MM_DEBUG
|
||||
#define mmVolumeInit(w,x,y,z,a) MM_FUNC(VolumeInit)(w,x,y,z,a,__FILE__,__LINE__);
|
||||
#define mmVolumeNodeInit(v,w,x,y,z) MM_FUNC(VolumeNodeInit)(v,w,x,y,z,__FILE__,__LINE__);
|
||||
#define mmVolumeAlloc(x,y) MM_FUNC(VolumeAlloc)(x,y,__FILE__,__LINE__);
|
||||
#define mmVolumeRelease(x,y) MM_FUNC(VolumeRelease)(x,y,__FILE__,__LINE__);
|
||||
#define mmVolumeFree(x,y) MM_FUNC(VolumeFree)(x,y,__FILE__,__LINE__);
|
||||
#define mmVolumeShrink(x,y,z) MM_FUNC(VolumeShrink)(x,y,z,__FILE__,__LINE__);
|
||||
#define mmVolumeGetAllocSize(x) MM_FUNC(VolumeGetAllocSize)(x,y,__FILE__,__LINE__);
|
||||
#define mmVolumeClean(x) MM_FUNC(VolumeClean)(x,__FILE__,__LINE__);
|
||||
#define mmVolumeFreeAll(x) MM_FUNC(VolumeFreeAll)(x,__FILE__,__LINE__);
|
||||
#define mmVolumeRealloc(x) MM_FUNC(VolumeRealloc)(x,y,z,__FILE__,__LINE__);
|
||||
|
||||
#define mmVolumeAlloc MM_FUNC(VolumeAlloc)
|
||||
#define mmVolumeRelease MM_FUNC(VolumeRelease)
|
||||
#define mmVolumeFree MM_FUNC(VolumeFree)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
void mmVolumeRelayByZone( mmVolumeHead *head, void *zonehead );
|
||||
*/
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *address;
|
||||
size_t pagesize;
|
||||
size_t pagealignment;
|
||||
size_t zonesize;
|
||||
size_t alignment;
|
||||
size_t chunkheadersize;
|
||||
void *chunklist;
|
||||
mtSpin spinlock;
|
||||
} mmZoneHead;
|
||||
|
||||
int MM_FUNC(ZoneInit)( mmZoneHead *head, size_t zonesize, intptr_t alignment MM_PARAMS );
|
||||
void *MM_FUNC(ZoneAlloc)( mmZoneHead *head, size_t bytes MM_PARAMS );
|
||||
void MM_FUNC(ZoneFree)( mmZoneHead *head, void *v MM_PARAMS );
|
||||
void MM_FUNC(ZoneFreeAll)( mmZoneHead *head MM_PARAMS );
|
||||
|
||||
#if MM_DEBUG
|
||||
#define mmZoneInit(x,y,z) MM_FUNC(ZoneInit)(x,y,z,__FILE__,__LINE__);
|
||||
#define mmZoneAlloc(x,y) MM_FUNC(ZoneAlloc)(x,y,__FILE__,__LINE__);
|
||||
#define mmZoneFree(x,y) MM_FUNC(ZoneFree)(x,y,__FILE__,__LINE__);
|
||||
#define mmZoneFreeAll(x) MM_FUNC(ZoneFreeAll)(x,__FILE__,__LINE__);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
void *mmAlloc( void *unused, size_t bytes MM_PARAMS );
|
||||
void *mmRealloc( void *unused, void *v, size_t bytes MM_PARAMS );
|
||||
void mmFree( void *unused, void *v, size_t bytes MM_PARAMS );
|
||||
|
||||
void *mmDebugAlloc( size_t bytes, char *file, int line );
|
||||
void *mmDebugRealloc( void *v, size_t bytes, char *file, int line );
|
||||
void mmDebugFree( void *v, char *file, int line );
|
||||
#define mmDebugAlloc(x) mmDebugAlloc(x,__FILE__,__LINE__)
|
||||
#define mmDebugFree(x) mmDebugFree(x,__FILE__,__LINE__)
|
||||
#define mmDebugRealloc(x,y) mmDebugRealloc(x,y,__FILE__,__LINE__)
|
||||
|
||||
void mmListUses( char *file, int line );
|
||||
#define mmListUses() mmListUses(__FILE__,__LINE__);
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
#if MM_DEBUG
|
||||
#define malloc(x) mmAlloc(0,(x),__FILE__,__LINE__)
|
||||
#define realloc(x,y) mmRealloc(0,(x),(y),__FILE__,__LINE__)
|
||||
#define free(x) mmFree(0,(x),0,__FILE__,__LINE__)
|
||||
#elif defined(MM_ALLOC_CHECK)
|
||||
|
||||
static inline void *mmAllocCheck( size_t size, char *file, int line )
|
||||
{
|
||||
void *p;
|
||||
p = malloc( size );
|
||||
#if MM_WINDOWS
|
||||
if( !( p ) )
|
||||
fprintf( stderr, "WARNING : Denied memory allocation ( %ld bytes ) at %s:%d\n", (long)size, file, line );
|
||||
#else
|
||||
if( !( p ) )
|
||||
fprintf( stderr, "WARNING : Denied memory allocation ( %lld bytes ) at %s:%d\n", (long long)size, file, line );
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline void *mmReallocCheck( void *p, size_t size, char *file, int line )
|
||||
{
|
||||
p = realloc( p, size );
|
||||
#if MM_WINDOWS
|
||||
if( !( p ) )
|
||||
fprintf( stderr, "WARNING : Denied memory allocation ( %ld bytes ) at %s:%d\n", (long)size, file, line );
|
||||
#else
|
||||
if( !( p ) )
|
||||
fprintf( stderr, "WARNING : Denied memory allocation ( %lld bytes ) at %s:%d\n", (long long)size, file, line );
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
#define malloc(x) mmAllocCheck((x),__FILE__,__LINE__)
|
||||
#define realloc(x,y) mmReallocCheck((x),(y),__FILE__,__LINE__)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
static inline uint64_t mmGetMillisecondsTime()
|
||||
{
|
||||
struct timeval lntime;
|
||||
gettimeofday( &lntime, 0 );
|
||||
return ( (uint64_t)lntime.tv_sec * 1000 ) + ( (uint64_t)lntime.tv_usec / 1000 );
|
||||
}
|
||||
|
||||
|
||||
static inline uint64_t mmGetMicrosecondsTime()
|
||||
{
|
||||
struct timeval lntime;
|
||||
gettimeofday( &lntime, 0 );
|
||||
return ( (uint64_t)lntime.tv_sec * 1000000 ) + (uint64_t)lntime.tv_usec;
|
||||
}
|
||||
|
||||
|
||||
static inline uint64_t mmGetNanosecondsTime()
|
||||
{
|
||||
struct timeval lntime;
|
||||
gettimeofday( &lntime, 0 );
|
||||
return ( (uint64_t)lntime.tv_sec * 1000000000 ) + ( (uint64_t)lntime.tv_usec * 1000 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,529 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "cpuconfig.h"
|
||||
#include "mm.h"
|
||||
|
||||
|
||||
void mmAtomicListAdd( mmAtomicP *list, void *item, intptr_t offset )
|
||||
{
|
||||
mmAtomicListNode *node, *nextnode;
|
||||
void *nextitem;
|
||||
|
||||
node = ADDRESS( item, offset );
|
||||
mmAtomicWriteP( &node->prev, list );
|
||||
for( ; ; )
|
||||
{
|
||||
/* Mark prev->next as busy */
|
||||
nextitem = mmAtomicReadP( list );
|
||||
if( ( nextitem == MM_ATOMIC_LIST_BUSY ) || !( mmAtomicCmpReplaceP( list, nextitem, MM_ATOMIC_LIST_BUSY ) ) )
|
||||
continue;
|
||||
mmAtomicWriteP( &node->next, nextitem );
|
||||
if( nextitem )
|
||||
{
|
||||
nextnode = ADDRESS( nextitem, offset );
|
||||
/* Set next->prev to node->next */
|
||||
if( !( mmAtomicCmpReplaceP( &nextnode->prev, list, &(node->next) ) ) )
|
||||
{
|
||||
mmAtomicWriteP( list, nextitem );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mmAtomicWrite32( &node->status, MM_ATOMIC_LIST_VALID );
|
||||
/* Finally set prev->next to point to the item */
|
||||
mmAtomicWriteP( list, item );
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void mmAtomicListRemove( void *item, intptr_t offset )
|
||||
{
|
||||
mmAtomicListNode *node, *nextnode;
|
||||
mmAtomicP *prevnext;
|
||||
void *nextitem;
|
||||
|
||||
node = ADDRESS( item, offset );
|
||||
if( !( mmAtomicCmpReplace32( &node->status, MM_ATOMIC_LIST_VALID, MM_ATOMIC_LIST_DELETED ) ) )
|
||||
return;
|
||||
for( ; ; )
|
||||
{
|
||||
/* Mark item->next as busy */
|
||||
nextitem = mmAtomicReadP( &node->next );
|
||||
if( ( nextitem == MM_ATOMIC_LIST_BUSY ) || !( mmAtomicCmpReplaceP( &node->next, nextitem, MM_ATOMIC_LIST_BUSY ) ) )
|
||||
continue;
|
||||
|
||||
/* Mark item->prev as busy */
|
||||
prevnext = mmAtomicReadP( &node->prev );
|
||||
if( ( prevnext == MM_ATOMIC_LIST_BUSY ) || !( mmAtomicCmpReplaceP( &node->prev, prevnext, MM_ATOMIC_LIST_BUSY ) ) )
|
||||
{
|
||||
mmAtomicWriteP( &node->next, nextitem );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Mark prev->next as busy */
|
||||
if( !( mmAtomicCmpReplaceP( prevnext, item, MM_ATOMIC_LIST_BUSY ) ) )
|
||||
{
|
||||
mmAtomicWriteP( &node->next, nextitem );
|
||||
mmAtomicWriteP( &node->prev, prevnext );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Fix next item */
|
||||
if( nextitem )
|
||||
{
|
||||
nextnode = ADDRESS( nextitem, offset );
|
||||
if( !( mmAtomicCmpReplaceP( &nextnode->prev, &node->next, prevnext ) ) )
|
||||
{
|
||||
mmAtomicWriteP( &node->next, nextitem );
|
||||
mmAtomicWriteP( &node->prev, prevnext );
|
||||
mmAtomicWriteP( prevnext, item );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally set prev->next to point to the next item */
|
||||
mmAtomicWriteP( prevnext, nextitem );
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void mmAtomicListDualInit( mmAtomicListDualHead *head )
|
||||
{
|
||||
mmAtomicWriteP( &head->first, 0 );
|
||||
mmAtomicWriteP( &head->last, &head->first );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void mmAtomicListDualAddFirst( mmAtomicListDualHead *head, void *item, intptr_t offset )
|
||||
{
|
||||
mmAtomicListNode *node, *nextnode;
|
||||
mmAtomicP *nextprev;
|
||||
void *nextitem;
|
||||
|
||||
node = ADDRESS( item, offset );
|
||||
mmAtomicWriteP( &node->prev, &head->first );
|
||||
for( ; ; )
|
||||
{
|
||||
/* Mark prev->next as busy */
|
||||
nextitem = mmAtomicReadP( &head->first );
|
||||
if( ( nextitem == MM_ATOMIC_LIST_BUSY ) || !( mmAtomicCmpReplaceP( &head->first, nextitem, MM_ATOMIC_LIST_BUSY ) ) )
|
||||
continue;
|
||||
mmAtomicWriteP( &node->next, nextitem );
|
||||
|
||||
nextprev = &head->last;
|
||||
if( nextitem )
|
||||
{
|
||||
nextnode = ADDRESS( nextitem, offset );
|
||||
nextprev = &nextnode->prev;
|
||||
}
|
||||
|
||||
/* Set next->prev to node->next */
|
||||
if( !( mmAtomicCmpReplaceP( nextprev, &head->first, &(node->next) ) ) )
|
||||
{
|
||||
mmAtomicWriteP( &head->first, nextitem );
|
||||
continue;
|
||||
}
|
||||
|
||||
mmAtomicWrite32( &node->status, MM_ATOMIC_LIST_VALID );
|
||||
|
||||
/* Finally set prev->next to point to the item */
|
||||
mmAtomicWriteP( &head->first, item );
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void mmAtomicListDualAddLast( mmAtomicListDualHead *head, void *item, intptr_t offset )
|
||||
{
|
||||
mmAtomicListNode *node;
|
||||
mmAtomicP *lastnext;
|
||||
|
||||
node = ADDRESS( item, offset );
|
||||
mmAtomicWriteP( &node->next, 0 );
|
||||
for( ; ; )
|
||||
{
|
||||
/* Mark head->last as busy */
|
||||
lastnext = mmAtomicReadP( &head->last );
|
||||
if( ( lastnext == MM_ATOMIC_LIST_BUSY ) || !( mmAtomicCmpReplaceP( &head->last, lastnext, MM_ATOMIC_LIST_BUSY ) ) )
|
||||
continue;
|
||||
mmAtomicWriteP( &node->prev, lastnext );
|
||||
|
||||
/* Mark last->next as busy */
|
||||
if( !( mmAtomicCmpReplaceP( lastnext, 0, MM_ATOMIC_LIST_BUSY ) ) )
|
||||
{
|
||||
mmAtomicWriteP( &head->last, lastnext );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set head->first to item if the list is empty */
|
||||
/*
|
||||
TODO TODO
|
||||
|
||||
firstitem = mmAtomicReadP( &head->first );
|
||||
if( ( firstitem == MM_ATOMIC_LIST_BUSY ) || ( !( firstitem ) && !( mmAtomicCmpReplaceP( &head->last, MM_ATOMIC_LIST_BUSY, &(node->next) ) ) ) )
|
||||
{
|
||||
mmAtomicWriteP( &head->last, lastnext );
|
||||
mmAtomicWriteP( lastnext, 0 );
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
mmAtomicWrite32( &node->status, MM_ATOMIC_LIST_VALID );
|
||||
|
||||
/* Set prev->next to item */
|
||||
mmAtomicWriteP( lastnext, item );
|
||||
|
||||
/* Finally set head->last to point to node->next */
|
||||
mmAtomicWriteP( &head->last, &(node->next) );
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void mmAtomicListDualRemove( mmAtomicListDualHead *head, void *item, intptr_t offset )
|
||||
{
|
||||
mmAtomicListNode *node, *nextnode;
|
||||
mmAtomicP *prevnext, *nextprev;
|
||||
void *nextitem;
|
||||
|
||||
node = ADDRESS( item, offset );
|
||||
if( !( mmAtomicCmpReplace32( &node->status, MM_ATOMIC_LIST_VALID, MM_ATOMIC_LIST_DELETED ) ) )
|
||||
return;
|
||||
for( ; ; )
|
||||
{
|
||||
/* Mark item->next as busy */
|
||||
nextitem = mmAtomicReadP( &node->next );
|
||||
if( ( nextitem == MM_ATOMIC_LIST_BUSY ) || !( mmAtomicCmpReplaceP( &node->next, nextitem, MM_ATOMIC_LIST_BUSY ) ) )
|
||||
continue;
|
||||
|
||||
/* Mark item->prev as busy */
|
||||
prevnext = mmAtomicReadP( &node->prev );
|
||||
if( ( prevnext == MM_ATOMIC_LIST_BUSY ) || !( mmAtomicCmpReplaceP( &node->prev, prevnext, MM_ATOMIC_LIST_BUSY ) ) )
|
||||
{
|
||||
mmAtomicWriteP( &node->next, nextitem );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Mark prev->next as busy */
|
||||
if( !( mmAtomicCmpReplaceP( prevnext, item, MM_ATOMIC_LIST_BUSY ) ) )
|
||||
{
|
||||
mmAtomicWriteP( &node->next, nextitem );
|
||||
mmAtomicWriteP( &node->prev, prevnext );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Fix next item */
|
||||
nextprev = &head->last;
|
||||
if( nextitem )
|
||||
{
|
||||
nextnode = ADDRESS( nextitem, offset );
|
||||
nextprev = &nextnode->prev;
|
||||
}
|
||||
if( !( mmAtomicCmpReplaceP( nextprev, &node->next, prevnext ) ) )
|
||||
{
|
||||
mmAtomicWriteP( &node->next, nextitem );
|
||||
mmAtomicWriteP( &node->prev, prevnext );
|
||||
mmAtomicWriteP( prevnext, item );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Finally set prev->next to point to the next item */
|
||||
mmAtomicWriteP( prevnext, nextitem );
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
void mmAtomicBarrierBuild( mmAtomicBarrier *barrier, int childcount, mmAtomicBarrier *parent )
|
||||
{
|
||||
mmAtomicWrite32( &barrier->flag, 0 );
|
||||
barrier->flagref = 0;
|
||||
barrier->resetvalue = childcount;
|
||||
mmAtomicWrite32( &barrier->counter, childcount );
|
||||
barrier->parent = parent;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef CPUCONF_STORE_REODERING_AFTER_STORE
|
||||
#ifndef MM_ATOMIC_BARRIER_DELAYED_RESET
|
||||
#undef MM_ATOMIC_BARRIER_DELAYED_RESET
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MM_ATOMIC_BARRIER_NEXTFLAGREF(x) (x+1)
|
||||
|
||||
/*
|
||||
int fooooooo = 0;
|
||||
*/
|
||||
|
||||
int mmAtomicBarrierWait( mmAtomicBarrier *barrier, int32_t spinwaitcounter, mmAtomicBarrierStat *barrierstat )
|
||||
{
|
||||
int32_t flagref, nextflagref, spincountdown;
|
||||
mmAtomicBarrier *leaf;
|
||||
|
||||
leaf = barrier;
|
||||
flagref = barrier->flagref;
|
||||
|
||||
#ifdef MM_ATOMIC_BARRIER_DEBUG
|
||||
if( mmAtomicRead32( &barrier->flag ) != flagref )
|
||||
printf( "Error, %d != %d\n", mmAtomicRead32( &barrier->flag ), flagref );
|
||||
#endif
|
||||
|
||||
nextflagref = MM_ATOMIC_BARRIER_NEXTFLAGREF( flagref );
|
||||
for( ; ; )
|
||||
{
|
||||
if( !( mmAtomicAddTestZero32( &barrier->counter, -1 ) ) )
|
||||
break;
|
||||
|
||||
#ifndef MM_ATOMIC_BARRIER_DELAYED_RESET
|
||||
barrier->flagref = nextflagref;
|
||||
MM_ATOMIC_ACCESS_32(&barrier->counter) += barrier->resetvalue;
|
||||
#endif
|
||||
|
||||
if( barrier->parent )
|
||||
barrier = barrier->parent;
|
||||
else
|
||||
{
|
||||
/* Barrier fully cleared */
|
||||
barrierstat->clearcounter++;
|
||||
|
||||
#ifndef MM_ATOMIC_BARRIER_DELAYED_RESET
|
||||
#ifdef CPUCONF_STORE_REODERING_AFTER_STORE
|
||||
mmWriteBarrier();
|
||||
#endif
|
||||
for( barrier = leaf ; barrier ; barrier = barrier->parent )
|
||||
mmAtomicWrite32( &barrier->flag, nextflagref );
|
||||
#else
|
||||
for( barrier = leaf ; barrier ; barrier = barrier->parent )
|
||||
{
|
||||
barrier->flagref = nextflagref;
|
||||
MM_ATOMIC_ACCESS_32(&barrier->counter) += barrier->resetvalue;
|
||||
/* No barrier : earlier, we disallowed delayed reset if CPUCONF_STORE_REODERING_AFTER_STORE */
|
||||
mmAtomicWrite32( &barrier->flag, nextflagref );
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Spin! */
|
||||
if( !( spinwaitcounter ) )
|
||||
goto spinyield;
|
||||
if( !( spincountdown = mmAtomicSpinWaitNeq32Count( &barrier->flag, flagref, spinwaitcounter ) ) )
|
||||
{
|
||||
barrierstat->yieldcounter++;
|
||||
spinyield:
|
||||
|
||||
|
||||
/*
|
||||
printf( "YIELD %d\n", fooooooo++ );
|
||||
*/
|
||||
|
||||
|
||||
for( ; mmAtomicRead32( &barrier->flag ) == flagref ; )
|
||||
mtYield();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef MM_ATOMIC_BARRIER_DELAYED_RESET
|
||||
#ifdef CPUCONF_STORE_REODERING_AFTER_STORE
|
||||
mmWriteBarrier();
|
||||
#endif
|
||||
for( ; leaf != barrier ; leaf = leaf->parent )
|
||||
mmAtomicWrite32( &leaf->flag, nextflagref );
|
||||
#else
|
||||
for( ; leaf != barrier ; leaf = leaf->parent )
|
||||
{
|
||||
leaf->flagref = nextflagref;
|
||||
MM_ATOMIC_ACCESS_32(&leaf->counter) += leaf->resetvalue;
|
||||
/* No barrier : earlier, we disallowed delayed reset if CPUCONF_STORE_REODERING_AFTER_STORE */
|
||||
mmAtomicWrite32( &leaf->flag, nextflagref );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static int mmAtomicCounterBuildStage( mmAtomicCounter *counter, int itembase, int itemcount, int counterstagesize, void *parent, int * const nodeindex )
|
||||
{
|
||||
int nodesize, nodebasesize, itemremainder, childcount, nodecount;
|
||||
mmAtomicCounterNode *node;
|
||||
|
||||
if( itemcount == 1 )
|
||||
{
|
||||
counter->locknode[itembase] = parent;
|
||||
return 1;
|
||||
}
|
||||
nodebasesize = itemcount / counterstagesize;
|
||||
itemremainder = itemcount - ( nodebasesize * counterstagesize );
|
||||
for( nodecount = 0 ; itemcount ; nodecount++, itemcount -= nodesize )
|
||||
{
|
||||
nodesize = nodebasesize;
|
||||
if( nodecount < itemremainder )
|
||||
nodesize++;
|
||||
if( nodesize >= 2 )
|
||||
{
|
||||
node = &counter->nodearray[ (*nodeindex)++ ];
|
||||
childcount = mmAtomicCounterBuildStage( counter, itembase, nodesize, counterstagesize, node, nodeindex );
|
||||
node->resetvalue = childcount;
|
||||
mmAtomicWrite32( &node->counter, childcount );
|
||||
node->parent = parent;
|
||||
}
|
||||
else
|
||||
counter->locknode[itembase] = parent;
|
||||
itembase += nodesize;
|
||||
}
|
||||
|
||||
return nodecount;
|
||||
}
|
||||
|
||||
|
||||
void mmAtomicCounterInit( mmAtomicCounter *counter, int lockcount, int stagesize )
|
||||
{
|
||||
int stagecount, nodecount, childcount;
|
||||
void *alloc;
|
||||
mmAtomicCounterNode *node;
|
||||
|
||||
counter->nodearray = 0;
|
||||
stagecount = lockcount;
|
||||
nodecount = 1;
|
||||
for( ; stagecount > 1 ; )
|
||||
{
|
||||
stagecount = ( stagecount + (stagesize-1) ) / stagesize;
|
||||
nodecount += stagecount;
|
||||
}
|
||||
|
||||
alloc = mmAlignAlloc( nodecount * sizeof(mmAtomicCounterNode) + lockcount * sizeof(mmAtomicCounterNode *), CPUCONF_CACHE_LINE_SIZE );
|
||||
counter->lockcount = lockcount;
|
||||
counter->nodecount = nodecount;
|
||||
counter->nodearray = alloc;
|
||||
counter->locknode = ADDRESS( alloc, nodecount * sizeof(mmAtomicCounterNode) );
|
||||
|
||||
counter->nodecount = 0;
|
||||
node = &counter->nodearray[ counter->nodecount++ ];
|
||||
childcount = mmAtomicCounterBuildStage( counter, 0, lockcount, stagesize, node, &counter->nodecount );
|
||||
if( counter->nodecount > nodecount )
|
||||
{
|
||||
printf( "What the hell?\n" );
|
||||
exit( 1 );
|
||||
}
|
||||
node->resetvalue = childcount;
|
||||
mmAtomicWrite32( &node->counter, childcount );
|
||||
node->parent = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void mmAtomicCounterDestroy( mmAtomicCounter *counter )
|
||||
{
|
||||
if( counter->nodearray )
|
||||
{
|
||||
mmAlignFree( counter->nodearray );
|
||||
counter->nodearray = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int mmAtomicCounterHit( mmAtomicCounter *counter, int lockindex )
|
||||
{
|
||||
mmAtomicCounterNode *node;
|
||||
node = counter->locknode[lockindex];
|
||||
for( ; ; )
|
||||
{
|
||||
if( !( mmAtomicAddTestZero32( &node->counter, -1 ) ) )
|
||||
break;
|
||||
MM_ATOMIC_ACCESS_32(&node->counter) += node->resetvalue;
|
||||
|
||||
/*
|
||||
printf( "Node %d ; %d\n", (int)( node - counter->nodearray ), MM_ATOMIC_ACCESS_32(&node->counter) );
|
||||
*/
|
||||
|
||||
if( node->parent )
|
||||
node = node->parent;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Implement a counter without all threads trashing each other's cache
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,526 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
|
||||
#include "cpuconfig.h"
|
||||
|
||||
#include "cc.h"
|
||||
#include "mm.h"
|
||||
|
||||
#include "mmbinsort.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
#define MM_BINSORT_INSERTION_SORT
|
||||
*/
|
||||
|
||||
|
||||
|
||||
typedef float mmbsf;
|
||||
#define mmbsffloor(x) floorf(x)
|
||||
#define mmbsfceil(x) ceilf(x)
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int itemcount;
|
||||
int flags;
|
||||
mmbsf min, max;
|
||||
void *p;
|
||||
void **last;
|
||||
} mmBinSortBucket;
|
||||
|
||||
#define MM_BINSORT_BUCKET_FLAGS_SUBGROUP (0x1)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mmbsf groupbase, groupmax, bucketrange;
|
||||
int bucketmax;
|
||||
mmBinSortBucket bucket[];
|
||||
} mmBinSortGroup;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int numanodeindex;
|
||||
size_t memsize;
|
||||
size_t itemlistoffset;
|
||||
int rootbucketcount; /* Count of buckets for root */
|
||||
int groupbucketcount; /* Count of buckets per group */
|
||||
int groupthreshold; /* Count of items required in a bucket */
|
||||
int collapsethreshold;
|
||||
int maxdepth;
|
||||
|
||||
/* Callback to user code to obtain the value of an item */
|
||||
double (*itemvalue)( void *item );
|
||||
|
||||
/* Memory management */
|
||||
mmBlockHead bucketblock;
|
||||
mmBlockHead groupblock;
|
||||
|
||||
/* Top-level group, *MUST* be at end of struct due to bucket[] zero-length array */
|
||||
mmBinSortGroup root;
|
||||
|
||||
} mmBinSortHead;
|
||||
|
||||
|
||||
/****/
|
||||
|
||||
|
||||
void *mmBinSortInit( size_t itemlistoffset, int rootbucketcount, int groupbucketcount, double rootmin, double rootmax, int groupthreshold, double (*itemvaluecallback)( void *item ), int maxdepth, int numanodeindex )
|
||||
{
|
||||
int bucketindex;
|
||||
size_t memsize;
|
||||
mmBinSortHead *bsort;
|
||||
mmBinSortGroup *group;
|
||||
mmBinSortBucket *bucket;
|
||||
|
||||
if( !( mmcontext.numaflag ) )
|
||||
numanodeindex = -1;
|
||||
memsize = sizeof(mmBinSortHead) + ( rootbucketcount * sizeof(mmBinSortBucket) );
|
||||
if( numanodeindex >= 0 )
|
||||
{
|
||||
bsort = mmNodeAlloc( numanodeindex, memsize );
|
||||
mmBlockNodeInit( &bsort->bucketblock, numanodeindex, sizeof(mmBinSortBucket), 1024, 1024, 0x40 );
|
||||
mmBlockNodeInit( &bsort->groupblock, numanodeindex, sizeof(mmBinSortGroup) + ( groupbucketcount * sizeof(mmBinSortBucket) ), 16, 16, 0x40 );
|
||||
}
|
||||
else
|
||||
{
|
||||
bsort = malloc( memsize );
|
||||
mmBlockInit( &bsort->bucketblock, sizeof(mmBinSortBucket), 1024, 1024, 0x40 );
|
||||
mmBlockInit( &bsort->groupblock, sizeof(mmBinSortGroup) + ( groupbucketcount * sizeof(mmBinSortBucket) ), 16, 16, 0x40 );
|
||||
}
|
||||
bsort->numanodeindex = numanodeindex;
|
||||
bsort->memsize = memsize;
|
||||
|
||||
bsort->itemlistoffset = itemlistoffset;
|
||||
bsort->rootbucketcount = rootbucketcount;
|
||||
bsort->groupbucketcount = groupbucketcount;
|
||||
bsort->groupthreshold = groupthreshold;
|
||||
bsort->collapsethreshold = groupthreshold >> 2;
|
||||
bsort->maxdepth = maxdepth;
|
||||
|
||||
bsort->itemvalue = itemvaluecallback;
|
||||
|
||||
group = &bsort->root;
|
||||
group->groupbase = rootmin;
|
||||
group->groupmax = rootmax;
|
||||
group->bucketrange = ( rootmax - rootmin ) / (double)rootbucketcount;
|
||||
group->bucketmax = rootbucketcount - 1;
|
||||
bucket = group->bucket;
|
||||
for( bucketindex = 0 ; bucketindex < rootbucketcount ; bucketindex++ )
|
||||
{
|
||||
bucket->flags = 0;
|
||||
bucket->itemcount = 0;
|
||||
bucket->min = FLT_MAX;
|
||||
bucket->max = -FLT_MAX;
|
||||
bucket->p = 0;
|
||||
bucket++;
|
||||
}
|
||||
|
||||
return bsort;
|
||||
}
|
||||
|
||||
|
||||
void mmBinSortFree( void *binsort )
|
||||
{
|
||||
mmBinSortHead *bsort;
|
||||
bsort = binsort;
|
||||
mmBlockFreeAll( &bsort->bucketblock );
|
||||
mmBlockFreeAll( &bsort->groupblock );
|
||||
if( bsort->numanodeindex >= 0 )
|
||||
mmNodeFree( bsort->numanodeindex, bsort, bsort->memsize );
|
||||
else
|
||||
free( bsort );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int MM_NOINLINE mmBinSortBucketIndex( mmBinSortGroup *group, mmbsf value )
|
||||
{
|
||||
int bucketindex = (int)mmbsffloor( ( value - group->groupbase ) / group->bucketrange );
|
||||
if( bucketindex < 0 )
|
||||
bucketindex = 0;
|
||||
if( bucketindex > group->bucketmax )
|
||||
bucketindex = group->bucketmax;
|
||||
return bucketindex;
|
||||
}
|
||||
|
||||
|
||||
/****/
|
||||
|
||||
|
||||
static mmBinSortGroup *mmBinSortSpawnGroup( mmBinSortHead *bsort, void *itembase, mmbsf base, mmbsf range )
|
||||
{
|
||||
int bucketindex;
|
||||
mmbsf value;
|
||||
void *item, *itemnext;
|
||||
mmBinSortGroup *group;
|
||||
mmBinSortBucket *bucket;
|
||||
|
||||
group = mmBlockAlloc( &bsort->groupblock );
|
||||
group->groupbase = base;
|
||||
group->groupmax = base + range;
|
||||
group->bucketrange = range / (mmbsf)bsort->groupbucketcount;
|
||||
group->bucketmax = bsort->groupbucketcount - 1;
|
||||
|
||||
bucket = group->bucket;
|
||||
for( bucketindex = 0 ; bucketindex < bsort->groupbucketcount ; bucketindex++ )
|
||||
{
|
||||
bucket->flags = 0;
|
||||
bucket->itemcount = 0;
|
||||
bucket->min = FLT_MAX;
|
||||
bucket->max = -FLT_MAX;
|
||||
bucket->p = 0;
|
||||
bucket->last = &bucket->p;
|
||||
bucket++;
|
||||
}
|
||||
|
||||
for( item = itembase ; item ; item = itemnext )
|
||||
{
|
||||
itemnext = ((mmListNode *)ADDRESS( item, bsort->itemlistoffset ))->next;
|
||||
|
||||
value = bsort->itemvalue( item );
|
||||
bucketindex = mmBinSortBucketIndex( group, value );
|
||||
|
||||
if( value < bucket->min )
|
||||
bucket->min = value;
|
||||
if( value > bucket->max )
|
||||
bucket->max = value;
|
||||
|
||||
bucket = &group->bucket[ bucketindex ];
|
||||
bucket->itemcount++;
|
||||
mmListAdd( bucket->last, item, bsort->itemlistoffset );
|
||||
bucket->last = &((mmListNode *)ADDRESS( item, bsort->itemlistoffset ))->next;
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
|
||||
/* Debugging */
|
||||
/*
|
||||
static int mmBinSortBucketCount( mmBinSortHead *bsort, mmBinSortBucket *bucket )
|
||||
{
|
||||
int itemcount;
|
||||
void *item;
|
||||
itemcount = 0;
|
||||
for( item = bucket->p ; item ; item = ((mmListNode *)ADDRESS( item, bsort->itemlistoffset ))->next )
|
||||
itemcount++;
|
||||
return itemcount;
|
||||
}
|
||||
|
||||
|
||||
static int mmBinSortGroupCount( mmBinSortHead *bsort, mmBinSortGroup *group )
|
||||
{
|
||||
int itemcount, bucketindex;
|
||||
mmBinSortBucket *bucket;
|
||||
bucket = group->bucket;
|
||||
itemcount = 0;
|
||||
for( bucketindex = 0, bucket = group->bucket ; bucketindex < bsort->groupbucketcount ; bucketindex++, bucket++ )
|
||||
{
|
||||
if( bucket->flags & MM_BINSORT_BUCKET_FLAGS_SUBGROUP )
|
||||
itemcount += mmBinSortGroupCount( bsort, bucket->p );
|
||||
else
|
||||
itemcount += mmBinSortBucketCount( bsort, bucket );
|
||||
}
|
||||
return itemcount;
|
||||
}
|
||||
|
||||
|
||||
static void mmBinSortBucketCheck( mmBinSortHead *bsort, mmBinSortBucket *bucket )
|
||||
{
|
||||
int itemcount;
|
||||
if( bucket->flags & MM_BINSORT_BUCKET_FLAGS_SUBGROUP )
|
||||
itemcount = mmBinSortGroupCount( bsort, bucket->p );
|
||||
else
|
||||
itemcount = mmBinSortBucketCount( bsort, bucket );
|
||||
printf( "Countcheck (0x%x) %d ~ %d\n", bucket->flags, itemcount, bucket->itemcount );
|
||||
if( itemcount != bucket->itemcount )
|
||||
exit( 1 );
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
static void mmBinSortCollapseGroup( mmBinSortHead *bsort, mmBinSortBucket *parentbucket )
|
||||
{
|
||||
int bucketindex, itemcount;
|
||||
mmBinSortGroup *group;
|
||||
mmBinSortBucket *bucket;
|
||||
void *item, *itemnext;
|
||||
|
||||
group = parentbucket->p;
|
||||
parentbucket->p = 0;
|
||||
parentbucket->last = &parentbucket->p;
|
||||
|
||||
itemcount = 0;
|
||||
for( bucketindex = 0, bucket = group->bucket ; bucketindex < bsort->groupbucketcount ; bucketindex++, bucket++ )
|
||||
{
|
||||
if( bucket->flags & MM_BINSORT_BUCKET_FLAGS_SUBGROUP )
|
||||
mmBinSortCollapseGroup( bsort, bucket );
|
||||
for( item = bucket->p ; item ; item = itemnext )
|
||||
{
|
||||
itemnext = ((mmListNode *)ADDRESS( item, bsort->itemlistoffset ))->next;
|
||||
mmListAdd( parentbucket->last, item, bsort->itemlistoffset );
|
||||
parentbucket->last = &((mmListNode *)ADDRESS( item, bsort->itemlistoffset ))->next;
|
||||
itemcount++;
|
||||
}
|
||||
}
|
||||
parentbucket->flags &= ~MM_BINSORT_BUCKET_FLAGS_SUBGROUP;
|
||||
parentbucket->itemcount = itemcount;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/****/
|
||||
|
||||
|
||||
void mmBinSortAdd( void *binsort, void *item, double itemvalue )
|
||||
{
|
||||
int bucketindex, depth;
|
||||
mmbsf value;
|
||||
mmBinSortHead *bsort;
|
||||
mmBinSortGroup *group, *subgroup;
|
||||
mmBinSortBucket *bucket;
|
||||
|
||||
bsort = binsort;
|
||||
value = itemvalue;
|
||||
group = &bsort->root;
|
||||
for( depth = 0 ; ; group = bucket->p, depth++ )
|
||||
{
|
||||
bucketindex = mmBinSortBucketIndex( group, value );
|
||||
bucket = &group->bucket[ bucketindex ];
|
||||
bucket->itemcount++;
|
||||
if( bucket->flags & MM_BINSORT_BUCKET_FLAGS_SUBGROUP )
|
||||
continue;
|
||||
if( ( bucket->itemcount >= bsort->groupthreshold ) && ( depth < bsort->maxdepth ) )
|
||||
{
|
||||
/* Build a new sub group, sort all entries into it */
|
||||
subgroup = mmBinSortSpawnGroup( bsort, bucket->p, group->groupbase + ( (mmbsf)bucketindex * group->bucketrange ), group->bucketrange );
|
||||
bucket->flags |= MM_BINSORT_BUCKET_FLAGS_SUBGROUP;
|
||||
bucket->p = subgroup;
|
||||
continue;
|
||||
}
|
||||
if( value < bucket->min )
|
||||
bucket->min = value;
|
||||
if( value > bucket->max )
|
||||
bucket->max = value;
|
||||
|
||||
#ifdef MM_BINSORT_INSERTION_SORT
|
||||
void *itemfind, *itemnext;
|
||||
void **insert;
|
||||
insert = &bucket->p;
|
||||
for( itemfind = bucket->p ; itemfind ; itemfind = itemnext )
|
||||
{
|
||||
itemnext = ((mmListNode *)ADDRESS( itemfind, bsort->itemlistoffset ))->next;
|
||||
if( itemvalue <= bsort->itemvalue( itemfind ) )
|
||||
break;
|
||||
insert = &((mmListNode *)ADDRESS( itemfind, bsort->itemlistoffset ))->next;
|
||||
}
|
||||
mmListAdd( insert, item, bsort->itemlistoffset );
|
||||
#else
|
||||
mmListAdd( &bucket->p, item, bsort->itemlistoffset );
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mmBinSortRemove( void *binsort, void *item, double itemvalue )
|
||||
{
|
||||
int bucketindex;
|
||||
mmbsf value;
|
||||
mmBinSortHead *bsort;
|
||||
mmBinSortGroup *group;
|
||||
mmBinSortBucket *bucket;
|
||||
|
||||
bsort = binsort;
|
||||
value = itemvalue;
|
||||
group = &bsort->root;
|
||||
for( ; ; group = bucket->p )
|
||||
{
|
||||
bucketindex = mmBinSortBucketIndex( group, value );
|
||||
bucket = &group->bucket[ bucketindex ];
|
||||
bucket->itemcount--;
|
||||
if( bucket->flags & MM_BINSORT_BUCKET_FLAGS_SUBGROUP )
|
||||
{
|
||||
if( bucket->itemcount >= bsort->collapsethreshold )
|
||||
continue;
|
||||
mmBinSortCollapseGroup( bsort, bucket );
|
||||
}
|
||||
break;
|
||||
}
|
||||
mmListRemove( item, bsort->itemlistoffset );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void mmBinSortUpdate( void *binsort, void *item, double olditemvalue, double newitemvalue )
|
||||
{
|
||||
mmBinSortRemove( binsort, item, olditemvalue );
|
||||
mmBinSortAdd( binsort, item, newitemvalue );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/****/
|
||||
|
||||
|
||||
void *mmBinSortGetRootBucket( void *binsort, int bucketindex, int *itemcount )
|
||||
{
|
||||
mmBinSortHead *bsort;
|
||||
mmBinSortBucket *bucket;
|
||||
|
||||
bsort = binsort;
|
||||
bucket = &bsort->root.bucket[ bucketindex ];
|
||||
|
||||
*itemcount = bucket->itemcount;
|
||||
return bucket->p;
|
||||
}
|
||||
|
||||
|
||||
void *mmBinSortGetGroupBucket( void *binsortgroup, int bucketindex, int *itemcount )
|
||||
{
|
||||
mmBinSortGroup *group;
|
||||
mmBinSortBucket *bucket;
|
||||
|
||||
group = binsortgroup;
|
||||
bucket = &group->bucket[ bucketindex ];
|
||||
|
||||
*itemcount = bucket->itemcount;
|
||||
return bucket->p;
|
||||
}
|
||||
|
||||
|
||||
/****/
|
||||
|
||||
|
||||
static void *mmBinSortGroupFirstItem( mmBinSortHead *bsort, mmBinSortGroup *group, mmbsf failmax )
|
||||
{
|
||||
int bucketindex, topbucket;
|
||||
void *item;
|
||||
mmBinSortBucket *bucket;
|
||||
mmBinSortGroup *subgroup;
|
||||
|
||||
if( failmax > group->groupmax )
|
||||
topbucket = group->bucketmax;
|
||||
else
|
||||
{
|
||||
topbucket = (int)mmbsfceil( ( failmax - group->groupbase ) / group->bucketrange );
|
||||
if( ( topbucket < 0 ) || ( topbucket > group->bucketmax ) )
|
||||
topbucket = group->bucketmax;
|
||||
}
|
||||
/*
|
||||
printf( " Failmax %f ; Base %f ; Range %f ; Index %f\n", failmax, group->groupbase, group->bucketrange, mmbsfceil( failmax - group->groupbase ) / group->bucketrange );
|
||||
printf( " Top bucket : %d\n", topbucket );
|
||||
*/
|
||||
bucket = group->bucket;
|
||||
for( bucketindex = 0 ; bucketindex <= topbucket ; bucketindex++, bucket++ )
|
||||
{
|
||||
/*
|
||||
printf( " Bucket %d ; Count %d ; Flags 0x%x ; %p\n", bucketindex, bucket->itemcount, bucket->flags, bucket->p );
|
||||
*/
|
||||
if( bucket->flags & MM_BINSORT_BUCKET_FLAGS_SUBGROUP )
|
||||
{
|
||||
subgroup = bucket->p;
|
||||
item = mmBinSortGroupFirstItem( bsort, subgroup, failmax );
|
||||
if( item )
|
||||
return item;
|
||||
}
|
||||
else if( bucket->p )
|
||||
return bucket->p;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void *mmBinSortGetFirstItem( void *binsort, double failmax )
|
||||
{
|
||||
int bucketindex, topbucket;
|
||||
mmBinSortHead *bsort;
|
||||
mmBinSortGroup *group;
|
||||
mmBinSortBucket *bucket;
|
||||
void *item;
|
||||
|
||||
bsort = binsort;
|
||||
if( failmax > bsort->root.groupmax )
|
||||
topbucket = bsort->root.bucketmax;
|
||||
else
|
||||
{
|
||||
topbucket = (int)mmbsfceil( ( (mmbsf)failmax - bsort->root.groupbase ) / bsort->root.bucketrange );
|
||||
if( ( topbucket < 0 ) || ( topbucket > bsort->root.bucketmax ) )
|
||||
topbucket = bsort->root.bucketmax;
|
||||
}
|
||||
|
||||
/*
|
||||
printf( "TopBucket : %d / %d\n", topbucket, bsort->root.bucketmax );
|
||||
*/
|
||||
bucket = bsort->root.bucket;
|
||||
for( bucketindex = 0 ; bucketindex <= topbucket ; bucketindex++, bucket++ )
|
||||
{
|
||||
/*
|
||||
printf( " Bucket %d ; Count %d ; Flags 0x%x ; %p\n", bucketindex, bucket->itemcount, bucket->flags, bucket->p );
|
||||
*/
|
||||
if( bucket->flags & MM_BINSORT_BUCKET_FLAGS_SUBGROUP )
|
||||
{
|
||||
group = bucket->p;
|
||||
item = mmBinSortGroupFirstItem( bsort, group, (mmbsf)failmax );
|
||||
if( item )
|
||||
return item;
|
||||
}
|
||||
else if( bucket->p )
|
||||
return bucket->p;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****/
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
void *mmBinSortInit( size_t itemlistoffset, int rootbucketcount, int groupbucketcount, double rootmin, double rootmax, int groupthreshold, double (*itemvaluecallback)( void *item ), int maxdepth, int numanodeindex );
|
||||
void mmBinSortFree( void *binsort );
|
||||
|
||||
|
||||
void mmBinSortAdd( void *binsort, void *item, double itemvalue );
|
||||
void mmBinSortRemove( void *binsort, void *item, double itemvalue );
|
||||
void mmBinSortUpdate( void *binsort, void *item, double olditemvalue, double newitemvalue );
|
||||
|
||||
void *mmBinSortGetRootBucket( void *binsort, int bucketindex, int *itemcount );
|
||||
void *mmBinSortGetGroupBucket( void *binsortgroup, int bucketindex, int *itemcount );
|
||||
|
||||
|
||||
void *mmBinSortGetFirstItem( void *binsort, double failmax );
|
||||
|
||||
|
||||
@@ -0,0 +1,487 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "cpuconfig.h"
|
||||
#include "cc.h"
|
||||
#include "mm.h"
|
||||
#include "mmbitmap.h"
|
||||
|
||||
|
||||
/* Friendlier to cache on SMP systems */
|
||||
#define BP_BITMAP_PREWRITE_CHECK
|
||||
|
||||
|
||||
/*
|
||||
TODO
|
||||
If we don't have atomic instruction support, we need a much better mutex locking mechanism!!
|
||||
*/
|
||||
|
||||
|
||||
void mmBitMapInit( mmBitMap *bitmap, size_t entrycount, int initvalue )
|
||||
{
|
||||
size_t mapsize, index;
|
||||
long value;
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
mmAtomicL *map;
|
||||
#else
|
||||
long *map;
|
||||
#endif
|
||||
|
||||
mapsize = ( entrycount + CPUCONF_LONG_BITS - 1 ) >> CPUCONF_LONG_BITSHIFT;
|
||||
bitmap->map = malloc( mapsize * sizeof(mmAtomicL) );
|
||||
bitmap->mapsize = mapsize;
|
||||
bitmap->entrycount = entrycount;
|
||||
|
||||
map = bitmap->map;
|
||||
value = ( initvalue & 0x1 ? ~0x0 : 0x0 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
for( index = 0 ; index < mapsize ; index++ )
|
||||
mmAtomicWriteL( &map[index], value );
|
||||
#else
|
||||
for( index = 0 ; index < mapsize ; index++ )
|
||||
map[index] = value;
|
||||
mtMutexInit( &bitmap->mutex );
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mmBitMapReset( mmBitMap *bitmap, int resetvalue )
|
||||
{
|
||||
size_t index;
|
||||
long value;
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
mmAtomicL *map;
|
||||
#else
|
||||
long *map;
|
||||
#endif
|
||||
|
||||
map = bitmap->map;
|
||||
value = ( resetvalue & 0x1 ? ~(long)0x0 : (long)0x0 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
for( index = 0 ; index < bitmap->mapsize ; index++ )
|
||||
mmAtomicWriteL( &map[index], value );
|
||||
#else
|
||||
for( index = 0 ; index < bitmap->mapsize ; index++ )
|
||||
map[index] = value;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mmBitMapFree( mmBitMap *bitmap )
|
||||
{
|
||||
free( bitmap->map );
|
||||
bitmap->map = 0;
|
||||
bitmap->mapsize = 0;
|
||||
#ifndef MM_ATOMIC_SUPPORT
|
||||
mtMutexDestroy( &bitmap->mutex );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
int mmBitMapDirectGet( mmBitMap *bitmap, size_t entryindex )
|
||||
{
|
||||
int value;
|
||||
size_t index, shift;
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
value = ( MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) >> shift ) & 0x1;
|
||||
#else
|
||||
value = ( bitmap->map[index] >> shift ) & 0x1;
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
void mmBitMapDirectSet( mmBitMap *bitmap, size_t entryindex )
|
||||
{
|
||||
size_t index, shift;
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) |= (long)1 << shift;
|
||||
#else
|
||||
bitmap->map[index] |= (long)1 << shift;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
void mmBitMapDirectClear( mmBitMap *bitmap, size_t entryindex )
|
||||
{
|
||||
size_t index, shift;
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) &= ~( (long)1 << shift );
|
||||
#else
|
||||
bitmap->map[index] &= ~( (long)1 << shift );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
int mmBitMapDirectMaskGet( mmBitMap *bitmap, size_t entryindex, long mask )
|
||||
{
|
||||
int value;
|
||||
size_t index, shift;
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
value = ( MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) >> shift ) & mask;
|
||||
#else
|
||||
value = ( bitmap->map[index] >> shift ) & mask;
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
void mmBitMapDirectMaskSet( mmBitMap *bitmap, size_t entryindex, long value, long mask )
|
||||
{
|
||||
size_t index, shift;
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) = ( MM_ATOMIC_ACCESS_L( &bitmap->map[index] ) & ~( mask << shift ) ) | ( value << shift );
|
||||
#else
|
||||
bitmap->map[index] = ( bitmap->map[index] & ~( mask << shift ) ) | ( value << shift );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
int mmBitMapGet( mmBitMap *bitmap, size_t entryindex )
|
||||
{
|
||||
int value;
|
||||
size_t index, shift;
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
value = ( mmAtomicReadL( &bitmap->map[index] ) >> shift ) & 0x1;
|
||||
#else
|
||||
mtMutexLock( &bitmap->mutex );
|
||||
value = ( bitmap->map[index] >> shift ) & 0x1;
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
void mmBitMapSet( mmBitMap *bitmap, size_t entryindex )
|
||||
{
|
||||
size_t index, shift;
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
#ifdef BP_BITMAP_PREWRITE_CHECK
|
||||
if( !( mmAtomicReadL( &bitmap->map[index] ) & ( (long)1 << shift ) ) )
|
||||
mmAtomicOrL( &bitmap->map[index], (long)1 << shift );
|
||||
#else
|
||||
mmAtomicOrL( &bitmap->map[index], (long)1 << shift );
|
||||
#endif
|
||||
#else
|
||||
mtMutexLock( &bitmap->mutex );
|
||||
bitmap->map[index] |= (long)1 << shift;
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
void mmBitMapClear( mmBitMap *bitmap, size_t entryindex )
|
||||
{
|
||||
size_t index, shift;
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
#ifdef BP_BITMAP_PREWRITE_CHECK
|
||||
if( mmAtomicReadL( &bitmap->map[index] ) & ( (long)1 << shift ) )
|
||||
mmAtomicAndL( &bitmap->map[index], ~( (long)1 << shift ) );
|
||||
#else
|
||||
mmAtomicAndL( &bitmap->map[index], ~( (long)1 << shift ) );
|
||||
#endif
|
||||
#else
|
||||
mtMutexLock( &bitmap->mutex );
|
||||
bitmap->map[index] &= ~( (long)1 << shift );
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
int mmBitMapMaskGet( mmBitMap *bitmap, size_t entryindex, long mask )
|
||||
{
|
||||
int value;
|
||||
size_t index, shift;
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
value = ( mmAtomicReadL( &bitmap->map[index] ) >> shift ) & mask;
|
||||
#else
|
||||
mtMutexLock( &bitmap->mutex );
|
||||
value = ( bitmap->map[index] >> shift ) & mask;
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
void mmBitMapMaskSet( mmBitMap *bitmap, size_t entryindex, long value, long mask )
|
||||
{
|
||||
size_t index, shift;
|
||||
long oldvalue, newvalue;
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shift = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
for( ; ; )
|
||||
{
|
||||
oldvalue = mmAtomicReadL( &bitmap->map[index] );
|
||||
newvalue = ( oldvalue & ~( mask << shift ) ) | ( value << shift );
|
||||
if( mmAtomicCmpReplaceL( &bitmap->map[index], oldvalue, newvalue ) )
|
||||
break;
|
||||
}
|
||||
#else
|
||||
mtMutexLock( &bitmap->mutex );
|
||||
bitmap->map[index] = ( bitmap->map[index] & ~( mask << shift ) ) | ( value << shift );
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: Yeah... That code was written in one go, maybe I should test if it's working fine, just in case? */
|
||||
int mmBitMapFindSet( mmBitMap *bitmap, size_t entryindex, size_t entryindexlast, size_t *retentryindex )
|
||||
{
|
||||
unsigned long value;
|
||||
size_t index, shift, shiftbase, shiftmax, indexlast, shiftlast;
|
||||
|
||||
indexlast = entryindexlast >> CPUCONF_LONG_BITSHIFT;
|
||||
shiftlast = entryindexlast & ( CPUCONF_LONG_BITS - 1 );
|
||||
|
||||
/* Leading bits search */
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shiftbase = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
value = mmAtomicReadL( &bitmap->map[index] );
|
||||
#else
|
||||
mtMutexLock( &bitmap->mutex );
|
||||
value = bitmap->map[index];
|
||||
#endif
|
||||
if( value != (unsigned long)0x0 )
|
||||
{
|
||||
shiftmax = CPUCONF_LONG_BITS;
|
||||
if( ( index == indexlast ) && ( shiftlast > shiftbase ) )
|
||||
shiftmax = shiftlast;
|
||||
value >>= shiftbase;
|
||||
for( shift = shiftbase ; shift < shiftmax ; shift++, value >>= 1 )
|
||||
{
|
||||
if( !( value & 0x1 ) )
|
||||
continue;
|
||||
entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
|
||||
if( entryindex >= bitmap->entrycount )
|
||||
break;
|
||||
#ifndef MM_ATOMIC_SUPPORT
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
*retentryindex = entryindex;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if( ( index == indexlast ) && ( shiftlast > shiftbase ) )
|
||||
{
|
||||
#ifndef MM_ATOMIC_SUPPORT
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Main search */
|
||||
for( ; ; )
|
||||
{
|
||||
index = ( index + 1 ) % bitmap->mapsize;
|
||||
if( index == indexlast )
|
||||
break;
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
value = mmAtomicReadL( &bitmap->map[index] );
|
||||
#else
|
||||
value = bitmap->map[index];
|
||||
#endif
|
||||
if( value != (unsigned long)0x0 )
|
||||
{
|
||||
for( shift = 0 ; ; shift++, value >>= 1 )
|
||||
{
|
||||
if( !( value & 0x1 ) )
|
||||
continue;
|
||||
entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
|
||||
if( entryindex >= bitmap->entrycount )
|
||||
break;
|
||||
#ifndef MM_ATOMIC_SUPPORT
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
*retentryindex = entryindex;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Trailing bits search */
|
||||
shiftlast = entryindexlast & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
value = mmAtomicReadL( &bitmap->map[index] );
|
||||
#else
|
||||
value = bitmap->map[index];
|
||||
#endif
|
||||
if( value != (unsigned long)0x0 )
|
||||
{
|
||||
for( shift = 0 ; shift < shiftlast ; shift++, value >>= 1 )
|
||||
{
|
||||
if( !( value & 0x1 ) )
|
||||
continue;
|
||||
entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
|
||||
if( entryindex >= bitmap->entrycount )
|
||||
break;
|
||||
#ifndef MM_ATOMIC_SUPPORT
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
if( ( index == indexlast ) && ( shift >= shiftlast ) )
|
||||
return 0;
|
||||
*retentryindex = entryindex;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#ifndef MM_ATOMIC_SUPPORT
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mmBitMapFindClear( mmBitMap *bitmap, size_t entryindex, size_t entryindexlast, size_t *retentryindex )
|
||||
{
|
||||
unsigned long value;
|
||||
size_t index, shift, shiftbase, shiftmax, indexlast, shiftlast;
|
||||
|
||||
indexlast = entryindexlast >> CPUCONF_LONG_BITSHIFT;
|
||||
shiftlast = entryindexlast & ( CPUCONF_LONG_BITS - 1 );
|
||||
|
||||
/* Leading bits search */
|
||||
index = entryindex >> CPUCONF_LONG_BITSHIFT;
|
||||
shiftbase = entryindex & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
value = mmAtomicReadL( &bitmap->map[index] );
|
||||
#else
|
||||
mtMutexLock( &bitmap->mutex );
|
||||
value = bitmap->map[index];
|
||||
#endif
|
||||
if( value != ~(unsigned long)0x0 )
|
||||
{
|
||||
shiftmax = CPUCONF_LONG_BITS;
|
||||
if( ( index == indexlast ) && ( shiftlast > shiftbase ) )
|
||||
shiftmax = shiftlast;
|
||||
value >>= shiftbase;
|
||||
for( shift = shiftbase ; shift < shiftmax ; shift++, value >>= 1 )
|
||||
{
|
||||
if( value & 0x1 )
|
||||
continue;
|
||||
entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
|
||||
if( entryindex >= bitmap->entrycount )
|
||||
break;
|
||||
#ifndef MM_ATOMIC_SUPPORT
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
*retentryindex = entryindex;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if( ( index == indexlast ) && ( shiftlast > shiftbase ) )
|
||||
{
|
||||
#ifndef MM_ATOMIC_SUPPORT
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Main search */
|
||||
for( ; ; )
|
||||
{
|
||||
index = ( index + 1 ) % bitmap->mapsize;
|
||||
if( index == indexlast )
|
||||
break;
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
value = mmAtomicReadL( &bitmap->map[index] );
|
||||
#else
|
||||
value = bitmap->map[index];
|
||||
#endif
|
||||
if( value != ~(unsigned long)0x0 )
|
||||
{
|
||||
for( shift = 0 ; ; shift++, value >>= 1 )
|
||||
{
|
||||
if( value & 0x1 )
|
||||
continue;
|
||||
entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
|
||||
if( entryindex >= bitmap->entrycount )
|
||||
break;
|
||||
#ifndef MM_ATOMIC_SUPPORT
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
*retentryindex = entryindex;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Trailing bits search */
|
||||
shiftlast = entryindexlast & ( CPUCONF_LONG_BITS - 1 );
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
value = mmAtomicReadL( &bitmap->map[index] );
|
||||
#else
|
||||
value = bitmap->map[index];
|
||||
#endif
|
||||
if( value != ~(unsigned long)0x0 )
|
||||
{
|
||||
for( shift = 0 ; shift < shiftlast ; shift++, value >>= 1 )
|
||||
{
|
||||
if( value & 0x1 )
|
||||
continue;
|
||||
entryindex = ( index << CPUCONF_LONG_BITSHIFT ) | shift;
|
||||
if( entryindex >= bitmap->entrycount )
|
||||
break;
|
||||
#ifndef MM_ATOMIC_SUPPORT
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
if( ( index == indexlast ) && ( shift >= shiftlast ) )
|
||||
return 0;
|
||||
*retentryindex = entryindex;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#ifndef MM_ATOMIC_SUPPORT
|
||||
mtMutexUnlock( &bitmap->mutex );
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t entrycount;
|
||||
size_t mapsize;
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
mmAtomicL *map;
|
||||
#else
|
||||
long *map;
|
||||
mtMutex mutex;
|
||||
#endif
|
||||
} mmBitMap;
|
||||
|
||||
void mmBitMapInit( mmBitMap *bitmap, size_t entrycount, int initvalue );
|
||||
void mmBitMapReset( mmBitMap *bitmap, int resetvalue );
|
||||
void mmBitMapFree( mmBitMap *bitmap );
|
||||
|
||||
int mmBitMapDirectGet( mmBitMap *bitmap, size_t entryindex );
|
||||
void mmBitMapDirectSet( mmBitMap *bitmap, size_t entryindex );
|
||||
void mmBitMapDirectClear( mmBitMap *bitmap, size_t entryindex );
|
||||
|
||||
int mmBitMapDirectMaskGet( mmBitMap *bitmap, size_t entryindex, long mask );
|
||||
void mmBitMapDirectMaskSet( mmBitMap *bitmap, size_t entryindex, long value, long mask );
|
||||
|
||||
int mmBitMapGet( mmBitMap *bitmap, size_t entryindex );
|
||||
void mmBitMapSet( mmBitMap *bitmap, size_t entryindex );
|
||||
void mmBitMapClear( mmBitMap *bitmap, size_t entryindex );
|
||||
|
||||
int mmBitMapMaskGet( mmBitMap *bitmap, size_t entryindex, long mask );
|
||||
void mmBitMapMaskSet( mmBitMap *bitmap, size_t entryindex, long value, long mask );
|
||||
|
||||
int mmBitMapFindSet( mmBitMap *bitmap, size_t entryindex, size_t entryindexlast, size_t *retentryindex );
|
||||
int mmBitMapFindClear( mmBitMap *bitmap, size_t entryindex, size_t entryindexlast, size_t *retentryindex );
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,154 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
#define MM_HASH_DEBUG_STATISTICS
|
||||
*/
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
MM_HASH_ENTRYCMP_INVALID,
|
||||
MM_HASH_ENTRYCMP_FOUND,
|
||||
MM_HASH_ENTRYCMP_SKIP
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MM_HASH_ENTRYLIST_BREAK,
|
||||
MM_HASH_ENTRYLIST_CONTINUE
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Clear the entry so that entryvalid() returns zero */
|
||||
void (*clearentry)( void *entry );
|
||||
/* Returns non-zero if the entry is valid and existing */
|
||||
int (*entryvalid)( void *entry );
|
||||
/* Return key for an arbitrary set of user-defined data */
|
||||
uint32_t (*entrykey)( void *entry );
|
||||
/* Return MM_HASH_ENTRYCMP* to stop or continue the search */
|
||||
int (*entrycmp)( void *entry, void *entryref );
|
||||
/* Return MM_HASH_ENTRYLIST* to stop or continue the search */
|
||||
int (*entrylist)( void *opaque, void *entry, void *entryref );
|
||||
} mmHashAccess;
|
||||
|
||||
|
||||
/* Do not keep track of entry count, table will not be able to say when it needs to shrink or grow */
|
||||
#define MM_HASH_FLAGS_NO_COUNT (0x1)
|
||||
|
||||
|
||||
size_t mmHashRequiredSize( size_t entrysize, uint32_t hashbits, uint32_t pageshift );
|
||||
void mmHashInit( void *hashtable, mmHashAccess *access, size_t entrysize, uint32_t hashbits, uint32_t pageshift, uint32_t flags );
|
||||
int mmHashGetStatus( void *hashtable, int *rethashbits );
|
||||
|
||||
enum
|
||||
{
|
||||
MM_HASH_STATUS_MUSTGROW,
|
||||
MM_HASH_STATUS_MUSTSHRINK,
|
||||
MM_HASH_STATUS_NORMAL,
|
||||
MM_HASH_STATUS_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
void *mmHashDirectFindEntry( void *hashtable, mmHashAccess *access, void *findentry );
|
||||
void *mmHashLockFindEntry( void *hashtable, mmHashAccess *access, void *findentry );
|
||||
|
||||
void mmHashDirectListEntry( void *hashtable, mmHashAccess *access, void *listentry, void *opaque );
|
||||
void mmHashLockListEntry( void *hashtable, mmHashAccess *access, void *listentry, void *opaque );
|
||||
|
||||
int mmHashDirectReadEntry( void *hashtable, mmHashAccess *access, void *readentry );
|
||||
int mmHashLockReadEntry( void *hashtable, mmHashAccess *access, void *readentry );
|
||||
|
||||
int mmHashDirectCallEntry( void *hashtable, mmHashAccess *access, void *callentry, void (*callback)( void *opaque, void *entry, int newflag ), void *opaque, int addflag );
|
||||
int mmHashLockCallEntry( void *hashtable, mmHashAccess *access, void *callentry, void (*callback)( void *opaque, void *entry, int newflag ), void *opaque, int addflag );
|
||||
|
||||
/* The hash key for replaced entries must remain the same! */
|
||||
int mmHashDirectReplaceEntry( void *hashtable, mmHashAccess *access, void *replaceentry, int addflag );
|
||||
int mmHashLockReplaceEntry( void *hashtable, mmHashAccess *access, void *replaceentry, int addflag );
|
||||
|
||||
int mmHashDirectAddEntry( void *hashtable, mmHashAccess *access, void *adddentry, int nodupflag );
|
||||
int mmHashLockAddEntry( void *hashtable, mmHashAccess *access, void *adddentry, int nodupflag );
|
||||
|
||||
int mmHashDirectDeleteEntry( void *hashtable, mmHashAccess *access, void *deleteentry, int readflag );
|
||||
int mmHashLockDeleteEntry( void *hashtable, mmHashAccess *access, void *deleteentry, int readflag );
|
||||
|
||||
void mmHashResize( void *newtable, void *oldtable, mmHashAccess *access, uint32_t hashbits, uint32_t pageshift );
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
MM_HASH_FAILURE,
|
||||
MM_HASH_SUCCESS,
|
||||
MM_HASH_TRYAGAIN /* Internal, can not be returned by any public call */
|
||||
};
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t hashkey;
|
||||
uint32_t pagestart;
|
||||
uint32_t pagefinal;
|
||||
void *next;
|
||||
} mmHashLockRange;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *hashtable;
|
||||
void *rangelist;
|
||||
int newcount;
|
||||
} mmHashLock;
|
||||
|
||||
|
||||
void mmHashLockInit( mmHashLock *hashlock, int newcount );
|
||||
void mmHashLockAdd( void *hashtable, mmHashAccess *access, void *entry, mmHashLock *hashlock, mmHashLockRange *lockrange );
|
||||
void mmHashLockAcquire( void *hashtable, mmHashAccess *access, mmHashLock *hashlock );
|
||||
void mmHashLockRelease( void *hashtable, mmHashLock *hashlock );
|
||||
|
||||
void mmHashGlobalLockEnable( void *hashtable );
|
||||
void mmHashGlobalLockDisable( void *hashtable );
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
void mmHashDirectDebugDuplicate( void *hashtable, mmHashAccess *access, void (*callback)( void *opaque, void *entry0, void *entry1 ), void *opaque );
|
||||
|
||||
void mmHashDirectDebugPages( void *hashtable );
|
||||
|
||||
void mmHashStatistics( void *hashtable, long *accesscount, long *collisioncount, long *relocationcount, long *entrycount, long *entrycountmax, long *hashsizemax );
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,540 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Threading interface, POSIX implementation.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef STAND_ALONE_MD
|
||||
|
||||
#if defined(COMPILE_FOR_VSL)
|
||||
#define MT_QT
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MT_QT)
|
||||
|
||||
#include "mmthreadqt.h"
|
||||
|
||||
#elif defined(MT_DISABLED)
|
||||
|
||||
struct mtNull
|
||||
{
|
||||
};
|
||||
|
||||
typedef struct mtNull mtMutex;
|
||||
typedef struct mtNull mtSpin;
|
||||
typedef struct mtNull mtSignal;
|
||||
|
||||
#define mtMutexInit(a)
|
||||
#define mtMutexDestroy(a)
|
||||
#define mtMutexLock(a)
|
||||
#define mtMutexUnlock(a)
|
||||
#define mtMutexTryLock(a)
|
||||
|
||||
#define mtSpinInit(a)
|
||||
#define mtSpinDestroy(a)
|
||||
#define mtSpinLock(a)
|
||||
#define mtSpinUnlock(a)
|
||||
#define mtSpinTryLock(a)
|
||||
|
||||
#define mtSignalInit(a)
|
||||
#define mtSignalDestroy(a)
|
||||
#define mtSignalDispatch(a)
|
||||
#define mtSignalBroadcast(a)
|
||||
#define mtSignalMutexWait(a,b)
|
||||
|
||||
#else
|
||||
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if _POSIX_SPIN_LOCKS > 0
|
||||
#define MT_SPIN_LOCK_SUPPORT
|
||||
#endif
|
||||
/*
|
||||
#define MT_BARRIER_SUPPORT
|
||||
#define MT_RWLOCK_SUPPORT
|
||||
*/
|
||||
|
||||
|
||||
static inline void mtYield()
|
||||
{
|
||||
sched_yield();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
typedef struct mtThread mtThread;
|
||||
|
||||
struct mtThread
|
||||
{
|
||||
pthread_t pthread;
|
||||
};
|
||||
|
||||
|
||||
#define MT_THREAD_FLAGS_JOINABLE (0x1)
|
||||
#define MT_THREAD_FLAGS_SETSTACK (0x2)
|
||||
|
||||
|
||||
static inline void mtThreadCreate( mtThread *thread, void *(*threadmain)( void *value ), void *value, int flags, void *stack, size_t stacksize )
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
|
||||
pthread_attr_init( &attr );
|
||||
#if !MM_WIN32 && !MM_WIN64
|
||||
if( flags & MT_THREAD_FLAGS_SETSTACK )
|
||||
pthread_attr_setstack( &attr, stack, stacksize );
|
||||
#endif
|
||||
if( flags & MT_THREAD_FLAGS_JOINABLE )
|
||||
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
|
||||
else
|
||||
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
|
||||
pthread_create( &thread->pthread, &attr, threadmain, value );
|
||||
pthread_attr_destroy( &attr );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtThreadExit()
|
||||
{
|
||||
pthread_exit( 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtThreadJoin( mtThread *thread )
|
||||
{
|
||||
void *ret;
|
||||
pthread_join( thread->pthread, &ret );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static inline size_t mtGetMinimumStackSize()
|
||||
{
|
||||
#ifdef PTHREAD_STACK_MIN
|
||||
return PTHREAD_STACK_MIN;
|
||||
#else
|
||||
return ( mmcontext.pagesize ? 4*mmcontext.pagesize : 16384 );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef MT_DEBUG
|
||||
#ifndef DEBUG_WARNING()
|
||||
#define DEBUG_WARNING() ({printf( "\nRF WARNING : %s %s %d\n", __FILE__, __FUNCTION__, __LINE__ ); fflush( stdout );})
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef struct mtMutex mtMutex;
|
||||
|
||||
struct mtMutex
|
||||
{
|
||||
#ifdef MT_DEBUG
|
||||
unsigned char *function;
|
||||
unsigned char *file;
|
||||
int line;
|
||||
#endif
|
||||
pthread_mutex_t pmutex;
|
||||
};
|
||||
|
||||
static inline void mtMutexInit( mtMutex *mutex )
|
||||
{
|
||||
pthread_mutex_init( &mutex->pmutex, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtMutexDestroy( mtMutex *mutex )
|
||||
{
|
||||
pthread_mutex_destroy( &mutex->pmutex );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MT_DEBUG
|
||||
|
||||
#define mtMutexLock(a) mtMutexLockDebug(a,__FUNCTION__,__FILE__,__LINE__)
|
||||
#define mtMutexUnlock(a) mtMutexUnlockDebug(a,__FUNCTION__,__FILE__,__LINE__)
|
||||
#define mtMutexTryLock(a) mtMutexTryLockDebug(a,__FUNCTION__,__FILE__,__LINE__)
|
||||
|
||||
static inline void mtMutexLockDebug( mtMutex *mutex, const unsigned char *function, const unsigned char *file, const int line )
|
||||
{
|
||||
printf( "Mutex lock : Thread %d on %p from %s() in %s:%d\n", (int)pthread_self(), mutex, function, file, line );
|
||||
fflush( stdout );
|
||||
if( pthread_mutex_trylock( &mutex->pmutex ) )
|
||||
{
|
||||
printf( " Mutex %p locked by %s() in %s:%d\n", mutex, mutex->function, mutex->file, mutex->line );
|
||||
fflush( stdout );
|
||||
if( pthread_mutex_lock( &mutex->pmutex ) )
|
||||
DEBUG_WARNING();
|
||||
}
|
||||
mutex->function = (unsigned char *)function;
|
||||
mutex->file = (unsigned char *)file;
|
||||
mutex->line = line;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtMutexUnlockDebug( mtMutex *mutex, const unsigned char *function, const unsigned char *file, const int line )
|
||||
{
|
||||
mutex->function = (unsigned char *)function;
|
||||
mutex->file = (unsigned char *)file;
|
||||
mutex->line = line;
|
||||
printf( "Mutex Unlock : Thread %d on %p from %s() in %s:%d\n", (int)pthread_self(), mutex, function, file, line );
|
||||
fflush( stdout );
|
||||
if( pthread_mutex_unlock( &mutex->pmutex ) )
|
||||
DEBUG_WARNING();
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int mtMutexTryLockDebug( mtMutex *mutex, const unsigned char *function, const unsigned char *file, const int line )
|
||||
{
|
||||
printf( "Mutex Trylock : Thread %d on %p from %s() in %s:%d\n", (int)pthread_self(), mutex, function, file, line );
|
||||
fflush( stdout );
|
||||
if( !( pthread_mutex_trylock( &mutex->pmutex ) ) )
|
||||
{
|
||||
mutex->function = (unsigned char *)function;
|
||||
mutex->file = (unsigned char *)file;
|
||||
mutex->line = line;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void mtMutexLock( mtMutex *mutex )
|
||||
{
|
||||
pthread_mutex_lock( &mutex->pmutex );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtMutexUnlock( mtMutex *mutex )
|
||||
{
|
||||
pthread_mutex_unlock( &mutex->pmutex );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int mtMutexTryLock( mtMutex *mutex )
|
||||
{
|
||||
return !( pthread_mutex_trylock( &mutex->pmutex ) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
typedef struct mtSignal mtSignal;
|
||||
|
||||
struct mtSignal
|
||||
{
|
||||
pthread_cond_t pcond;
|
||||
};
|
||||
|
||||
static inline void mtSignalInit( mtSignal *signal )
|
||||
{
|
||||
pthread_cond_init( &signal->pcond, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtSignalDestroy( mtSignal *signal )
|
||||
{
|
||||
pthread_cond_destroy( &signal->pcond );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtSignalWake( mtSignal *signal )
|
||||
{
|
||||
#ifdef MT_DEBUG
|
||||
if( pthread_cond_signal( &signal->pcond ) )
|
||||
DEBUG_WARNING();
|
||||
#else
|
||||
pthread_cond_signal( &signal->pcond );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtSignalBroadcast( mtSignal *signal )
|
||||
{
|
||||
#ifdef MT_DEBUG
|
||||
if( pthread_cond_broadcast( &signal->pcond ) )
|
||||
DEBUG_WARNING();
|
||||
#else
|
||||
pthread_cond_broadcast( &signal->pcond );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtSignalWait( mtSignal *signal, mtMutex *mutex )
|
||||
{
|
||||
#ifdef MT_DEBUG
|
||||
if( pthread_cond_wait( &signal->pcond, &mutex->pmutex ) )
|
||||
DEBUG_WARNING();
|
||||
#else
|
||||
pthread_cond_wait( &signal->pcond, &mutex->pmutex );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtSignalWaitTimeout( mtSignal *signal, mtMutex *mutex, long milliseconds )
|
||||
{
|
||||
uint64_t microsecs;
|
||||
struct timespec ts;
|
||||
struct timeval tp;
|
||||
gettimeofday( &tp, NULL );
|
||||
ts.tv_sec = tp.tv_sec + ( milliseconds / 1000 );
|
||||
microsecs = tp.tv_usec + ( ( milliseconds % 1000 ) * 1000 );
|
||||
if( microsecs >= 1000000 )
|
||||
{
|
||||
ts.tv_sec++;
|
||||
microsecs -= 1000000;
|
||||
}
|
||||
ts.tv_nsec = microsecs * 1000;
|
||||
pthread_cond_timedwait( &signal->pcond, &mutex->pmutex, &ts );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MT_DEBUG
|
||||
#define MT_MUTEX_INITIALIZER { 0, 0, 0, PTHREAD_MUTEX_INITIALIZER }
|
||||
#else
|
||||
#define MT_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
#ifdef MM_ATOMIC_SUPPORT
|
||||
|
||||
typedef struct mtSpin mtSpin;
|
||||
|
||||
struct mtSpin
|
||||
{
|
||||
mmAtomic32 atomicspin;
|
||||
};
|
||||
|
||||
static inline void mtSpinInit( mtSpin *spin )
|
||||
{
|
||||
mmAtomicWrite32( &spin->atomicspin, 0x0 );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtSpinDestroy( mtSpin *spin )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtSpinLock( mtSpin *spin )
|
||||
{
|
||||
mmAtomicSpin32( &spin->atomicspin, 0x0, 0x1 );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtSpinUnlock( mtSpin *spin )
|
||||
{
|
||||
mmAtomicWrite32( &spin->atomicspin, 0x0 );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int mtSpinTryLock( mtSpin *spin )
|
||||
{
|
||||
return mmAtomicCmpReplace32( &spin->atomicspin, 0x0, 0x1 );
|
||||
}
|
||||
|
||||
#elif _POSIX_SPIN_LOCKS > 0
|
||||
|
||||
typedef struct mtSpin mtSpin;
|
||||
|
||||
struct mtSpin
|
||||
{
|
||||
#ifdef MT_DEBUG
|
||||
unsigned char *function;
|
||||
unsigned char *file;
|
||||
int line;
|
||||
#endif
|
||||
pthread_spinlock_t pspinlock;
|
||||
};
|
||||
|
||||
static inline void mtSpinInit( mtSpin *spin )
|
||||
{
|
||||
pthread_spin_init( &spin->pspinlock, PTHREAD_PROCESS_PRIVATE );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtSpinDestroy( mtSpin *spin )
|
||||
{
|
||||
pthread_spin_destroy( &spin->pspinlock );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtSpinLock( mtSpin *spin )
|
||||
{
|
||||
#ifdef MT_DEBUG
|
||||
if( pthread_spin_lock( &spin->pspinlock ) )
|
||||
DEBUG_WARNING();
|
||||
#else
|
||||
pthread_spin_lock( &spin->pspinlock );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtSpinUnlock( mtSpin *spin )
|
||||
{
|
||||
#ifdef MT_DEBUG
|
||||
if( pthread_spin_unlock( &spin->pspinlock ) )
|
||||
DEBUG_WARNING();
|
||||
#else
|
||||
pthread_spin_unlock( &spin->pspinlock );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int mtSpinTryLock( mtSpin *spin )
|
||||
{
|
||||
return !( pthread_spin_trylock( &spin->pspinlock ) );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
typedef struct mtMutex mtSpin;
|
||||
|
||||
#define mtSpinInit(a) mtMutexInit(a)
|
||||
#define mtSpinDestroy(a) mtMutexDestroy(a)
|
||||
#define mtSpinLock(a) mtMutexLock(a)
|
||||
#define mtSpinUnlock(a) mtMutexUnlock(a)
|
||||
#define mtSpinTryLock(a) mtMutexTryLock(a)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
#ifdef MT_BARRIER_SUPPORT
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pthread_barrier_t pbarrier;
|
||||
} mtBarrier;
|
||||
|
||||
static inline void mtBarrierInit( mtBarrier *barrier, int count )
|
||||
{
|
||||
pthread_barrier_init( &barrier->pbarrier, 0, count );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtBarrierDestroy( mtBarrier *barrier )
|
||||
{
|
||||
pthread_barrier_destroy( &barrier->pbarrier );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int mtBarrierWait( mtBarrier *barrier )
|
||||
{
|
||||
return pthread_barrier_wait( &barrier->pbarrier );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
#ifdef MT_RWLOCK_SUPPORT
|
||||
|
||||
typedef struct mtRWlock mtRWlock;
|
||||
|
||||
struct mtRWlock
|
||||
{
|
||||
pthread_rwlock_t prwlock;
|
||||
};
|
||||
|
||||
|
||||
static inline void mtRWlockInit( mtRWlock *rwlock )
|
||||
{
|
||||
pthread_rwlock_init( &rwlock->prwlock, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtRWlockDestroy( mtRWlock *rwlock )
|
||||
{
|
||||
pthread_rwlock_destroy( &rwlock->prwlock );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtRWlockRead( mtRWlock *rwlock )
|
||||
{
|
||||
pthread_rwlock_rdlock( &rwlock->prwlock );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtRWlockWrite( mtRWlock *rwlock )
|
||||
{
|
||||
pthread_rwlock_wrlock( &rwlock->prwlock );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void mtRWlockUnlock( mtRWlock *rwlock )
|
||||
{
|
||||
pthread_rwlock_unlock( &rwlock->prwlock );
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int mtRWlockTryRead( mtRWlock *rwlock )
|
||||
{
|
||||
return pthread_rwlock_rdlock( &rwlock->prwlock );
|
||||
}
|
||||
|
||||
static inline int mtRWlockTryWrite( mtRWlock *rwlock )
|
||||
{
|
||||
return pthread_rwlock_wrlock( &rwlock->prwlock );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
/* BrlcadAppWalker.cpp
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/19/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Implements the comb_pre_func, comb_post_func, and primitive_func operations
|
||||
* that the BrlcadTreeWalker will call.
|
||||
*/
|
||||
|
||||
/* Standard libraries */
|
||||
#include <algorithm>
|
||||
|
||||
/* BRL-CAD libraries */
|
||||
extern "C" {
|
||||
#include "vmath.h"
|
||||
#include "nmg.h"
|
||||
#include "rtgeom.h"
|
||||
#include "bu.h"
|
||||
#include "rtfunc.h"
|
||||
#include "raytrace.h"
|
||||
#include "db.h"
|
||||
}
|
||||
|
||||
/* Local headers */
|
||||
#include "BrlcadAppWalker.h"
|
||||
|
||||
//******************************************************************************
|
||||
// NAME constructor
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Construct the object.
|
||||
//******************************************************************************
|
||||
BrlcadAppWalker::BrlcadAppWalker()
|
||||
{
|
||||
regionNeedsConversion = false;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// NAME destructor
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Cleanup the object.
|
||||
//******************************************************************************
|
||||
BrlcadAppWalker::~BrlcadAppWalker()
|
||||
{
|
||||
}
|
||||
|
||||
void BrlcadAppWalker::comb_pre_func(struct directory *dp,
|
||||
BrlcadTreeWalker *btw)
|
||||
{
|
||||
int regCount = btw->inRegion();
|
||||
//fprintf(stderr, "entering %s inRegion(%d)", dp->d_namep, regCount);
|
||||
//btw->printObjStack();
|
||||
//fprintf(stderr, "flags...");
|
||||
//btw->printFlags();
|
||||
//btw->printFlagStack();
|
||||
int tf = btw->getFlags();
|
||||
if (regCount == 1)
|
||||
{
|
||||
if (dp->d_flags & RT_DIR_REGION)
|
||||
{
|
||||
regionNeedsConversion = false;
|
||||
}
|
||||
}
|
||||
else if (regCount > 1)
|
||||
{
|
||||
if (tf & FLAG_UNION)
|
||||
{
|
||||
// Should never happen. Union of region into region is bogus
|
||||
regionNeedsConversion = true;
|
||||
}
|
||||
else if (tf & (FLAG_SUBTRACT|FLAG_INTERSECT|FLAG_NOT|FLAG_XOR))
|
||||
{
|
||||
regionNeedsConversion = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BrlcadAppWalker::comb_post_func(struct directory *dp,
|
||||
struct rt_comb_internal *comb,
|
||||
BrlcadTreeWalker *btw)
|
||||
{
|
||||
int regCount = btw->inRegion();
|
||||
//fprintf(stderr, "leaving %s inRegion(%d)", dp->d_namep, regCount);
|
||||
//btw->printObjStack(); btw->printFlags();
|
||||
//btw->printFlagStack();
|
||||
|
||||
//fprintf(stderr, "groupstack: %ld\n", m_groupStack.size());
|
||||
int tf = btw->getFlags();
|
||||
if (regCount == 1 )
|
||||
{
|
||||
if (dp->d_flags & RT_DIR_REGION)
|
||||
{
|
||||
if (regionNeedsConversion)
|
||||
if (m_nonBotRegions.empty())
|
||||
m_nonBotRegions.push_back(dp->d_namep);
|
||||
else if (std::find(m_nonBotRegions.begin(),
|
||||
m_nonBotRegions.end(),
|
||||
dp->d_namep) == m_nonBotRegions.end())
|
||||
m_nonBotRegions.push_back(dp->d_namep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BrlcadAppWalker::primitive_func(struct directory *dp,
|
||||
BrlcadTreeWalker *btw)
|
||||
{
|
||||
int tf = btw->getFlags();
|
||||
int inRegion = btw->inRegion();
|
||||
|
||||
// btw->printObjStack(); btw->printFlags();
|
||||
|
||||
if (inRegion > 0)
|
||||
{
|
||||
// if non-bot
|
||||
// rnc = true
|
||||
// add wireframe
|
||||
// else
|
||||
// add triangles
|
||||
|
||||
if (tf & (FLAG_SUBTRACT|FLAG_INTERSECT|FLAG_NOT|FLAG_XOR))
|
||||
{
|
||||
regionNeedsConversion = true;
|
||||
}
|
||||
|
||||
struct rt_db_internal intern;
|
||||
btw->brlcad_get_internal(&intern, dp, NULL);
|
||||
|
||||
if (intern.idb_minor_type == ID_BOT)
|
||||
{
|
||||
//fprintf(stderr, "%s is a bot\n", dp->d_namep);
|
||||
// add a drawable for the triangles from this BOT
|
||||
if (m_botRegions.empty())
|
||||
m_botRegions.push_back(dp->d_namep);
|
||||
else if (std::find(m_botRegions.begin(),
|
||||
m_botRegions.end(),
|
||||
dp->d_namep) == m_botRegions.end())
|
||||
m_botRegions.push_back(dp->d_namep);
|
||||
}
|
||||
else
|
||||
{
|
||||
//fprintf(stderr, "%s is a prim in region %s\n", dp->d_namep, m_currentGeode->getName().c_str());
|
||||
regionNeedsConversion = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just a primitive hanging out in space in no region?
|
||||
struct rt_db_internal intern;
|
||||
btw->brlcad_get_internal(&intern, dp, NULL);
|
||||
|
||||
if (intern.idb_minor_type == ID_BOT)
|
||||
{
|
||||
if (m_botRegions.empty())
|
||||
m_botRegions.push_back(dp->d_namep);
|
||||
else if (std::find(m_botRegions.begin(),
|
||||
m_botRegions.end(),
|
||||
dp->d_namep) == m_botRegions.end())
|
||||
m_botRegions.push_back(dp->d_namep);
|
||||
}
|
||||
}
|
||||
//fprintf(stderr, "%s done\n", dp->d_namep);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/* BrlcadAppWalker.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/19/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Implements the comb_pre_func, comb_post_func, and primitive_func operations
|
||||
* that the BrlcadTreeWalker will call.
|
||||
*/
|
||||
|
||||
#ifndef BRLCADAPPWALKER_H
|
||||
#define BRLCADAPPWALKER_H
|
||||
|
||||
/* Standard libraries */
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/* Linterface headers */
|
||||
#include "Interface/AppWalkerInterface.h"
|
||||
|
||||
/* Local headers */
|
||||
#include "BrlcadTreeWalker.h"
|
||||
|
||||
class BrlcadAppWalker : public AppWalkerInterface
|
||||
{
|
||||
public:
|
||||
BrlcadAppWalker();
|
||||
~BrlcadAppWalker();
|
||||
|
||||
virtual void comb_pre_func(struct directory *dp,
|
||||
BrlcadTreeWalker *btw);
|
||||
virtual void comb_post_func(struct directory *dp,
|
||||
struct rt_comb_internal *comb,
|
||||
BrlcadTreeWalker *btw);
|
||||
virtual void primitive_func(struct directory *dp,
|
||||
BrlcadTreeWalker *btw);
|
||||
|
||||
std::vector<std::string> getBotRegions() { return m_botRegions; }
|
||||
std::vector<std::string> getNonBotRegions() { return m_nonBotRegions; }
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_botRegions;
|
||||
std::vector<std::string> m_nonBotRegions;
|
||||
bool regionNeedsConversion; // region needs conversion
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,128 @@
|
||||
/* BrlcadLoader.cpp
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/19/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* This class contains the functions to comb a BRL-CAD database file and
|
||||
* return region names.
|
||||
*/
|
||||
|
||||
/* Local headers */
|
||||
#include "BrlcadLoader.h"
|
||||
#include "BrlcadAppWalker.h"
|
||||
|
||||
//******************************************************************************
|
||||
// NAME constructor
|
||||
//
|
||||
// INPUTS
|
||||
// filename - target file name
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Construct the object.
|
||||
//******************************************************************************
|
||||
BrlcadLoader::BrlcadLoader(const std::string filename)
|
||||
: GLoaderInterface(filename)
|
||||
, m_dbip(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// NAME destructor
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Cleanup the object.
|
||||
//******************************************************************************
|
||||
BrlcadLoader::~BrlcadLoader()
|
||||
{
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// NAME startLoader
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Walk geometry to get all the region names within.
|
||||
//******************************************************************************
|
||||
void BrlcadLoader::startLoader()
|
||||
{
|
||||
m_status = true;
|
||||
|
||||
// First initialize the librt resource
|
||||
if (rt_uniresource.re_magic != RESOURCE_MAGIC)
|
||||
{
|
||||
rt_init_resource(&rt_uniresource, 0, NULL);
|
||||
}
|
||||
|
||||
//
|
||||
// Open the database and load the geometry
|
||||
//
|
||||
if ((m_dbip = db_open(m_fileName.c_str(), "r")) == DBI_NULL)
|
||||
{
|
||||
m_status = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (db_dirbuild(m_dbip))
|
||||
{
|
||||
m_status = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// update all objects with the correct number of
|
||||
// times the object is referenced by other objects
|
||||
db_update_nref(m_dbip, &rt_uniresource);
|
||||
|
||||
BrlcadAppWalker appWalker;
|
||||
BrlcadTreeWalker tw(m_dbip, &rt_uniresource, appWalker);
|
||||
struct directory *dp;
|
||||
|
||||
// Look at all items in the geometry file
|
||||
FOR_ALL_DIRECTORY_START(dp, m_dbip) {
|
||||
// if an item isn't referred to by any other object
|
||||
// this is a top level object we should start traversing
|
||||
// to construct the geometry
|
||||
if (dp->d_nref == 0)
|
||||
tw.brlcad_functree(dp); // Traverse the tree, generating geometry
|
||||
} FOR_ALL_DIRECTORY_END;
|
||||
//fprintf(stderr, "final\n");
|
||||
|
||||
// set both bot and non-bot lists
|
||||
m_botRegionNames = appWalker.getBotRegions();
|
||||
m_nonbotRegionNames = appWalker.getNonBotRegions();
|
||||
|
||||
db_close(m_dbip);
|
||||
m_dbip = NULL;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/* BrlcadLoader.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/19/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* This class contains the functions to comb a BRL-CAD database file and
|
||||
* return region names.
|
||||
*/
|
||||
|
||||
#ifndef BRLCAD_LOADER_H
|
||||
#define BRLCAD_LOADER_H
|
||||
|
||||
/* BRL-CAD libraries */
|
||||
extern "C" {
|
||||
#include "vmath.h"
|
||||
#include "raytrace.h"
|
||||
#include "rtgeom.h"
|
||||
}
|
||||
|
||||
/* Interface headers */
|
||||
#include "Interface/GLoaderInterface.h"
|
||||
|
||||
/* Class */
|
||||
class BrlcadLoader : public GLoaderInterface
|
||||
{
|
||||
public:
|
||||
BrlcadLoader(const std::string);
|
||||
~BrlcadLoader();
|
||||
|
||||
std::vector<std::string> getBotRegionNames() const { return m_botRegionNames; }
|
||||
std::vector<std::string> getNonbotRegionNames() const { return m_nonbotRegionNames; }
|
||||
|
||||
virtual std::vector<std::string> getGeomNames() { return getNonbotRegionNames(); }
|
||||
virtual void startLoader();
|
||||
|
||||
protected:
|
||||
struct db_i *m_dbip;
|
||||
std::vector<std::string> m_botRegionNames;
|
||||
std::vector<std::string> m_nonbotRegionNames;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,224 @@
|
||||
/* BrlcadTreeWalker.cpp
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/19/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* This object walks a brlcad heirarchy starting at a particular
|
||||
* directory entry.
|
||||
*/
|
||||
|
||||
#include "BrlcadTreeWalker.h"
|
||||
|
||||
BrlcadTreeWalker::BrlcadTreeWalker(struct db_i* dbip,
|
||||
struct resource *resp,
|
||||
AppWalkerInterface &appWalker)
|
||||
: m_dbip(dbip)
|
||||
, m_resp(resp)
|
||||
, m_inRegion(0)
|
||||
, m_appWalker(appWalker)
|
||||
{
|
||||
m_treeFlags.push_back(0);
|
||||
RT_CK_DBI(m_dbip);
|
||||
if (m_resp)
|
||||
{
|
||||
RT_CK_RESOURCE(m_resp);
|
||||
}
|
||||
|
||||
// XXX This dreck is necessary because the ft_plot() functions expect RTG to be initialized
|
||||
if (BU_LIST_FIRST(bu_list, &RTG.rtg_vlfree) == 0)
|
||||
{
|
||||
char *envflags;
|
||||
envflags = getenv("LIBRT_DEBUG");
|
||||
if (envflags)
|
||||
{
|
||||
if (RTG.debug)
|
||||
bu_log("WARNING: discarding LIBRT_DEBUG value in favor of application specified flags\n");
|
||||
else
|
||||
RTG.debug = strtol(envflags, NULL, 0x10);
|
||||
}
|
||||
|
||||
BU_LIST_INIT(&RTG.rtg_vlfree);
|
||||
}
|
||||
}
|
||||
|
||||
BrlcadTreeWalker::~BrlcadTreeWalker()
|
||||
{
|
||||
}
|
||||
|
||||
int BrlcadTreeWalker::brlcad_get_internal(struct rt_db_internal *intern,
|
||||
struct directory *dp,
|
||||
matp_t matrix)
|
||||
{
|
||||
return rt_db_get_internal(intern, dp, m_dbip, matrix, m_resp);
|
||||
}
|
||||
|
||||
void BrlcadTreeWalker::brlcad_functree(struct directory *dp)
|
||||
{
|
||||
RT_CK_DBI(m_dbip);
|
||||
if (m_resp)
|
||||
{
|
||||
RT_CK_RESOURCE(m_resp);
|
||||
}
|
||||
|
||||
if (!dp)
|
||||
{
|
||||
return; /* nothing to do */
|
||||
}
|
||||
|
||||
m_objStack.push_back(StackNode(dp));
|
||||
|
||||
if (dp->d_flags & RT_DIR_COMB)
|
||||
{
|
||||
if (dp->d_flags & RT_DIR_REGION)
|
||||
{
|
||||
if (m_inRegion == 0)
|
||||
{
|
||||
m_topRegionName = dp->d_namep;
|
||||
}
|
||||
m_inRegion++;
|
||||
}
|
||||
|
||||
m_appWalker.comb_pre_func(dp, this);
|
||||
struct rt_db_internal in;
|
||||
struct rt_comb_internal *comb = (struct rt_comb_internal *)NULL;
|
||||
|
||||
if (rt_db_get_internal(&in, dp, m_dbip, /*mat_t*/ NULL, m_resp) < 0)
|
||||
return;
|
||||
|
||||
comb = (struct rt_comb_internal *)in.idb_ptr;
|
||||
if (!comb)
|
||||
{
|
||||
bu_log("%s:%d null comb pointer for combination called %s",
|
||||
__FILE__, __LINE__, dp->d_namep);
|
||||
bu_bomb("");
|
||||
}
|
||||
|
||||
m_treeFlags.push_back(FLAG_NONE);
|
||||
brlcad_functree_subtree(comb->tree, dp);
|
||||
m_treeFlags.pop_back();
|
||||
|
||||
/* Finally, the combination post process */
|
||||
m_appWalker.comb_post_func(dp, comb, this);
|
||||
|
||||
rt_db_free_internal(&in);
|
||||
|
||||
if (dp->d_flags & RT_DIR_REGION)
|
||||
{
|
||||
m_inRegion--;
|
||||
if (m_inRegion == 0)
|
||||
m_topRegionName.clear();
|
||||
}
|
||||
}
|
||||
else if (dp->d_flags & RT_DIR_SOLID || dp->d_major_type & DB5_MAJORTYPE_BINARY_MASK)
|
||||
{
|
||||
m_appWalker.primitive_func(dp, this);
|
||||
}
|
||||
else if (strcmp("_GLOBAL", dp->d_namep))
|
||||
{
|
||||
// This is not the _GLOBAL and isn't a solid/primtive or combination
|
||||
bu_log("brlcad_functree: %s is neither COMB nor SOLID? %d %d\n",
|
||||
dp->d_namep, dp->d_major_type, dp->d_minor_type);
|
||||
}
|
||||
|
||||
m_objStack.pop_back();
|
||||
}
|
||||
|
||||
/***
|
||||
* The parent argument exists solely to be able to report error status against
|
||||
* a particular object in the BRLCAD database.
|
||||
*/
|
||||
void BrlcadTreeWalker::brlcad_functree_subtree(union tree *tp,
|
||||
struct directory *parent)
|
||||
{
|
||||
if (!tp)
|
||||
return;
|
||||
|
||||
switch (tp->tr_op)
|
||||
{
|
||||
case OP_DB_LEAF:
|
||||
{
|
||||
struct directory *dp;
|
||||
|
||||
if (tp->tr_l.tl_mat)
|
||||
{
|
||||
m_objStack.push_back(StackNode(tp->tr_l.tl_mat));
|
||||
m_treeFlags.push_back(m_treeFlags.back()|FLAG_MATRIX);
|
||||
}
|
||||
|
||||
if ((dp=db_lookup(m_dbip, tp->tr_l.tl_name, LOOKUP_NOISY)) == RT_DIR_NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
brlcad_functree(dp);
|
||||
|
||||
if (tp->tr_l.tl_mat)
|
||||
{
|
||||
m_treeFlags.pop_back();
|
||||
m_objStack.pop_back();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_UNION:
|
||||
case OP_INTERSECT:
|
||||
case OP_SUBTRACT:
|
||||
case OP_XOR:
|
||||
m_objStack.push_back(StackNode(tp->tr_op));
|
||||
// add union to treeFlags & push new value
|
||||
m_treeFlags.push_back(m_treeFlags.back()|FLAG_UNION);
|
||||
brlcad_functree_subtree(tp->tr_b.tb_left, parent);
|
||||
m_treeFlags.pop_back();
|
||||
|
||||
// add flag to treeFlags & push new value
|
||||
m_treeFlags.push_back(m_treeFlags.back()|op2flag(tp->tr_op));
|
||||
brlcad_functree_subtree(tp->tr_b.tb_right, parent);
|
||||
m_treeFlags.pop_back();
|
||||
|
||||
m_objStack.pop_back();
|
||||
break;
|
||||
case OP_SOLID:
|
||||
case OP_REGION:
|
||||
case OP_NOP:
|
||||
case OP_NOT:
|
||||
case OP_GUARD:
|
||||
case OP_XNOP:
|
||||
case OP_NMG_TESS:
|
||||
case OP_FREE:
|
||||
// These types not implemented.
|
||||
break;
|
||||
default:
|
||||
bu_log("%s:%d brlcad_functree_subtree: unrecognized operator %d in \"%s\"\n",
|
||||
__FILE__, __LINE__, tp->tr_op, parent->d_namep);
|
||||
bu_bomb("");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/* BrlcadTreeWalker.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/19/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* This object walks a brlcad heirarchy starting at a particular
|
||||
* directory entry.
|
||||
*/
|
||||
|
||||
#ifndef BRLCADTREEWALKER_H
|
||||
#define BRLCADTREEWALKER_H
|
||||
|
||||
/* Standard libraries */
|
||||
#include <vector>
|
||||
|
||||
/* BRL-CAD libraries */
|
||||
extern "C" {
|
||||
#include "vmath.h"
|
||||
#include "nmg.h"
|
||||
#include "rtgeom.h"
|
||||
#include "bu.h"
|
||||
#include "raytrace.h"
|
||||
#include "db.h"
|
||||
}
|
||||
|
||||
/* Interface headers */
|
||||
#include "Interface/AppWalkerInterface.h"
|
||||
|
||||
/** enumeration of all the types of operators that might be on the
|
||||
* heirarchy of the graph that the BrlcadTreeWalker maintains
|
||||
*
|
||||
* Shared by the BrlcadTreeWalker and BrlcadBotLoader
|
||||
*/
|
||||
enum treeFlags { FLAG_NONE=0,
|
||||
FLAG_MATRIX=1,
|
||||
FLAG_SUBTRACT=2,
|
||||
FLAG_INTERSECT=4,
|
||||
FLAG_UNION=8,
|
||||
FLAG_NOT=16,
|
||||
FLAG_XOR=32,
|
||||
FLAG_LEAF=64
|
||||
};
|
||||
|
||||
/**
|
||||
* HELPER CLASS: StackNode
|
||||
*
|
||||
* This encapsulates a single item on the directed acyclic graph of a
|
||||
* BRLCAD heirarchy. The stack is maintained by the BrlcadTreeWalker to
|
||||
* keep track of various states along the path.
|
||||
*
|
||||
* XXX This really should be private to the BrlcadTreeWalker. No-one else has
|
||||
* any business looking at this.
|
||||
*/
|
||||
class StackNode {
|
||||
public:
|
||||
enum ItemType { OBJECT, OPERATION, MATRIX };
|
||||
|
||||
StackNode(struct directory *dp) : m_itemType(OBJECT) { m_dp = dp; }
|
||||
StackNode(int op) : m_itemType(OPERATION) { m_op = op; }
|
||||
StackNode(mat_t m) : m_itemType(MATRIX) { MAT_COPY(m_mat, m); }
|
||||
|
||||
ItemType getType() const { return m_itemType; }
|
||||
struct directory *getDirectory() const
|
||||
{
|
||||
if (m_itemType == OBJECT) {
|
||||
return m_dp;
|
||||
}
|
||||
abort();
|
||||
return NULL; // make compiler happy
|
||||
}
|
||||
int getOperation() const
|
||||
{
|
||||
if (m_itemType == OPERATION) {
|
||||
return m_op;
|
||||
}
|
||||
abort();
|
||||
return 0; // make compiler happy
|
||||
}
|
||||
fastf_t * getMatrix() const
|
||||
{
|
||||
if (m_itemType == MATRIX) {
|
||||
return (fastf_t *)m_mat;
|
||||
}
|
||||
abort();
|
||||
return NULL; // make compiler happy
|
||||
}
|
||||
void print(const int depth);
|
||||
|
||||
private:
|
||||
ItemType m_itemType;
|
||||
struct directory *m_dp;
|
||||
int m_op;
|
||||
mat_t m_mat;
|
||||
};
|
||||
|
||||
/* Class */
|
||||
class BrlcadTreeWalker
|
||||
{
|
||||
public:
|
||||
BrlcadTreeWalker(struct db_i* dbip,
|
||||
struct resource *resp,
|
||||
AppWalkerInterface &appWalker);
|
||||
~BrlcadTreeWalker();
|
||||
|
||||
/// Start walking the heirarchy at a particular directory entry
|
||||
void brlcad_functree(struct directory *);
|
||||
int brlcad_get_internal(struct rt_db_internal *intern,
|
||||
struct directory *dp,
|
||||
mat_t matrix);
|
||||
inline int inRegion() const { return m_inRegion; }
|
||||
inline const char *regionName() const { return m_topRegionName.c_str(); }
|
||||
inline int getFlags() const { if (m_treeFlags.size() > 0) return m_treeFlags.back(); else return 0; }
|
||||
|
||||
private:
|
||||
// This is a helper function for brlcad_functree which
|
||||
// handles walking the union tree structure for a single combination
|
||||
void brlcad_functree_subtree(union tree *, struct directory *);
|
||||
static inline int op2flag(int op)
|
||||
{
|
||||
switch (op) {
|
||||
case OP_UNION : return FLAG_UNION;
|
||||
case OP_SUBTRACT : return FLAG_SUBTRACT;
|
||||
case OP_INTERSECT : return FLAG_INTERSECT;
|
||||
case OP_XOR : return FLAG_XOR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct db_i *m_dbip;
|
||||
struct resource *m_resp;
|
||||
int m_inRegion;
|
||||
std::string m_topRegionName;
|
||||
AppWalkerInterface &m_appWalker;
|
||||
std::vector<StackNode>m_objStack;
|
||||
std::vector<int> m_treeFlags;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
set(GCT_BRLCAD_SRCS
|
||||
BrlcadAppWalker.cpp
|
||||
BrlcadLoader.cpp
|
||||
BrlcadTreeWalker.cpp
|
||||
DbGeometry.cpp
|
||||
DbTracer.cpp
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../openNURBS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../tcl/generic
|
||||
)
|
||||
|
||||
add_library(BrlcadGCT SHARED ${GCT_BRLCAD_SRCS})
|
||||
set_target_properties(BrlcadGCT PROPERTIES VERSION 1.1.0 SOVERSION 1)
|
||||
|
||||
install(TARGETS BrlcadGCT
|
||||
RUNTIME DESTINATION ${BIN_DIR}
|
||||
LIBRARY DESTINATION ${LIB_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_DIR})
|
||||
|
||||
if(MSVC)
|
||||
set_property(TARGET BrlcadGCT APPEND PROPERTY COMPILE_DEFINITIONS "BRLCADGCT_DLL_EXPORTS")
|
||||
endif(MSVC)
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 8
|
||||
# mode: cmake
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
# ex: shiftwidth=2 tabstop=8
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/* DbGeometry.cpp
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/20/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Implements the INativeGeometry interface for BRL-CAD targets.
|
||||
*/
|
||||
|
||||
// Local headers
|
||||
#include "DbGeometry.h"
|
||||
|
||||
namespace GeomConversion {
|
||||
|
||||
namespace BRLCAD {
|
||||
|
||||
static struct resource resource[MAX_PSW];
|
||||
|
||||
//*******************************************************************
|
||||
// NAME constructor
|
||||
//
|
||||
// INPUTS
|
||||
// filename - target file name
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Construct the object.
|
||||
//*******************************************************************
|
||||
DbGeometry::DbGeometry(std::string filename)
|
||||
: Interface::INativeGeometry(filename)
|
||||
, m_rtip(RTI_NULL)
|
||||
{
|
||||
char titleBuf[1028];
|
||||
m_rtip = rt_dirbuild(filename.c_str(), titleBuf, sizeof(titleBuf));
|
||||
if (m_rtip == RTI_NULL)
|
||||
return; // throw exception???
|
||||
|
||||
/* Initialize all the per-CPU memory resources. The number of
|
||||
* processors can change at runtime, init them all.
|
||||
*/
|
||||
for (int i=0; i < MAX_PSW; i++)
|
||||
{
|
||||
rt_init_resource(&(resource[i]), i, m_rtip);
|
||||
bn_rand_init(resource[i].re_randptr, i);
|
||||
}
|
||||
|
||||
m_geometryType = Interface::BRLCAD;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME destructor
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Cleanup the object.
|
||||
//*******************************************************************
|
||||
DbGeometry::~DbGeometry()
|
||||
{
|
||||
// cleanup rt_i
|
||||
if (m_rtip != RTI_NULL)
|
||||
{
|
||||
rt_free_rti(m_rtip);
|
||||
m_rtip = RTI_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME getGeometry
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Return a reference to the internal target data.
|
||||
//*******************************************************************
|
||||
void* DbGeometry::getGeometry()
|
||||
{
|
||||
return ((void*) m_rtip);
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME getResources
|
||||
//
|
||||
// INPUTS
|
||||
// i - index of the desired resource
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Return a reference to CPU resource for the given index.
|
||||
//*******************************************************************
|
||||
struct resource* DbGeometry::getResource(int i)
|
||||
{
|
||||
return &(resource[i]);
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME loadGeometry
|
||||
//
|
||||
// INPUTS
|
||||
// rname - region name
|
||||
// tcount - thread count
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Load a given piece of the geometry.
|
||||
//*******************************************************************
|
||||
void DbGeometry::loadGeometry(std::string rname, int tcount)
|
||||
{
|
||||
m_rtip->useair = 1; // convert air objects when found
|
||||
|
||||
if (rt_gettree(m_rtip, rname.c_str()))
|
||||
{
|
||||
bu_log("BRLCAD::DbGeometry::loadRegion - Error loading <%s>\n",
|
||||
rname.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
rt_prep_parallel(m_rtip, tcount);
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME cleanupGeometry
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Perform cleanup of any geometry.
|
||||
//*******************************************************************
|
||||
void DbGeometry::cleanupGeometry()
|
||||
{
|
||||
rt_clean(m_rtip);
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME getGeometryMin
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Return minimum 3D dimension of the loaded geometry.
|
||||
//*******************************************************************
|
||||
double* DbGeometry::getGeometryMin()
|
||||
{
|
||||
return m_rtip->rti_pmin;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME getGeometryMax
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Return maximum 3D dimension of the loaded geometry.
|
||||
//*******************************************************************
|
||||
double* DbGeometry::getGeometryMax()
|
||||
{
|
||||
return m_rtip->rti_pmax;
|
||||
}
|
||||
|
||||
} // namespace BRLCAD
|
||||
|
||||
} // namespace GeomConversion
|
||||
@@ -0,0 +1,83 @@
|
||||
/* DbGeometry.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/20/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Implements the INativeGeometry interface for BRL-CAD targets.
|
||||
*/
|
||||
|
||||
#ifndef BRLCADDBGEOMETRY_H
|
||||
#define BRLCADDBGEOMETRY_H
|
||||
|
||||
// BRL-CAD headers
|
||||
extern "C" {
|
||||
#include "bu.h"
|
||||
#include "raytrace.h"
|
||||
}
|
||||
|
||||
// Local headers
|
||||
#include "Interface/INativeGeometry.h"
|
||||
|
||||
namespace GeomConversion {
|
||||
|
||||
namespace BRLCAD {
|
||||
|
||||
/**
|
||||
* DbGeometry
|
||||
*
|
||||
* Implements the INativeGeometry interface for BRL-CAD targets.
|
||||
*/
|
||||
class DbGeometry : public Interface::INativeGeometry
|
||||
{
|
||||
public:
|
||||
DbGeometry(std::string);
|
||||
~DbGeometry();
|
||||
|
||||
virtual void* getGeometry();
|
||||
struct resource* getResource(int);
|
||||
|
||||
virtual void loadGeometry(std::string, int tcount=1);
|
||||
virtual void cleanupGeometry();
|
||||
|
||||
virtual double* getGeometryMin();
|
||||
virtual double* getGeometryMax();
|
||||
|
||||
private:
|
||||
struct rt_i *m_rtip;
|
||||
};
|
||||
|
||||
} // namespace DbGeometry
|
||||
|
||||
} // namespace GeomConversion
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,203 @@
|
||||
/* DbTracer.cpp
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 10/02/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Implements the IGeometryTracer interface for shotlining BRL-CAD targets.
|
||||
*/
|
||||
|
||||
// Local headers
|
||||
#include "DbTracer.h"
|
||||
|
||||
namespace GeomConversion {
|
||||
|
||||
namespace BRLCAD {
|
||||
|
||||
//*******************************************************************
|
||||
// NAME hit_func
|
||||
//
|
||||
// INPUTS
|
||||
// ap - application structure
|
||||
// PartHeadp - pointer to the beginning of the trace list
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Called when a shotline produces a hit. This user defined
|
||||
// callback copies the in and out hit points into structures and
|
||||
// stores them in the ray's result list.
|
||||
//*******************************************************************
|
||||
static int
|
||||
hit_func(struct application *ap, struct partition *PartHeadp, struct seg *)
|
||||
{
|
||||
/* iterating over partitions, this will keep track of the current
|
||||
* partition we're working on.
|
||||
*/
|
||||
struct partition *pp;
|
||||
|
||||
/* will serve as a pointer for the entry and exit hitpoints */
|
||||
struct hit *hitp;
|
||||
|
||||
/* will serve as a pointer to the solid primitive we hit */
|
||||
struct soltab *stp;
|
||||
|
||||
/* output variables */
|
||||
Interface::ray_results *result = (Interface::ray_results *) ap->a_uptr;
|
||||
Interface::one_hit singleHit;
|
||||
|
||||
VMOVE(result->origin, ap->a_ray.r_pt);
|
||||
result->x = ap->a_x;
|
||||
result->y = ap->a_y;
|
||||
|
||||
/* iterate over each partition until we get back to the head.
|
||||
* each partition corresponds to a specific homogeneous region of
|
||||
* material.
|
||||
*/
|
||||
for (pp=PartHeadp->pt_forw; pp != PartHeadp; pp = pp->pt_forw)
|
||||
{
|
||||
/* entry hit point, so we type less */
|
||||
hitp = pp->pt_inhit;
|
||||
|
||||
/* primitive we encountered on entry */
|
||||
stp = pp->pt_inseg->seg_stp;
|
||||
|
||||
/* clear data struct */
|
||||
ONE_HIT_INIT(singleHit);
|
||||
|
||||
/* record IN hit point */
|
||||
VJOIN1(singleHit.point, ap->a_ray.r_pt,
|
||||
hitp->hit_dist, ap->a_ray.r_dir);
|
||||
|
||||
/* calculate IN normal vector */
|
||||
/* compute the normal vector at the entry point, flipping the
|
||||
* normal if necessary.
|
||||
*/
|
||||
RT_HIT_NORMAL(singleHit.normal, hitp, stp,
|
||||
&(ap->a_ray), pp->pt_inflip);
|
||||
|
||||
/* save IN solid and surface numbers */
|
||||
/* singleHit.solidNumber = stp->st_bit; */
|
||||
singleHit.solidName = stp->st_dp->d_namep;
|
||||
singleHit.solidSurface = hitp->hit_surfno;
|
||||
|
||||
/* push hit to the result list */
|
||||
result->hitData.push_back(singleHit);
|
||||
|
||||
/* exit point, so we type less */
|
||||
hitp = pp->pt_outhit;
|
||||
|
||||
/* primitive we exited from */
|
||||
stp = pp->pt_outseg->seg_stp;
|
||||
|
||||
/* clear data struct */
|
||||
ONE_HIT_INIT(singleHit);
|
||||
|
||||
/* record OUT hit point */
|
||||
VJOIN1(singleHit.point, ap->a_ray.r_pt,
|
||||
hitp->hit_dist, ap->a_ray.r_dir);
|
||||
|
||||
/* calculate OUT normal vector */
|
||||
/* compute the normal vector at the exit point, flipping the
|
||||
* normal if necessary.
|
||||
*/
|
||||
RT_HIT_NORMAL(singleHit.normal, hitp, stp,
|
||||
&(ap->a_ray), pp->pt_outflip);
|
||||
|
||||
/* save OUT solid and surface numbers */
|
||||
/* singleHit.solidNumber = stp->st_bit; */
|
||||
singleHit.solidName = stp->st_dp->d_namep;
|
||||
singleHit.solidSurface = hitp->hit_surfno;
|
||||
|
||||
/* push hit to the result list */
|
||||
result->hitData.push_back(singleHit);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME constructor
|
||||
//
|
||||
// INPUTS
|
||||
// ti - pointer to a target
|
||||
// cpuID - thread ID
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Construct the object.
|
||||
//*******************************************************************
|
||||
DbTracer::DbTracer(Interface::INativeGeometry *ti, int cpuID)
|
||||
: Interface::IGeometryTracer(ti)
|
||||
, m_cpuID(cpuID)
|
||||
{
|
||||
// set up the application object that will be used
|
||||
RT_APPLICATION_INIT(&m_ap);
|
||||
m_ap.a_rt_i = (struct rt_i *) ti->getGeometry();
|
||||
m_ap.a_hit = hit_func;
|
||||
m_ap.a_resource = ((DbGeometry *) ti)->getResource(cpuID);
|
||||
m_ap.a_user = cpuID;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME destructor
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Cleanup the object.
|
||||
//*******************************************************************
|
||||
DbTracer::~DbTracer()
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME fireRay
|
||||
//
|
||||
// INPUTS
|
||||
// data - pointer to a tracer_ray_data
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Perform a shotline.
|
||||
//*******************************************************************
|
||||
void DbTracer::fireRay(Interface::trace_data *ray)
|
||||
{
|
||||
// set application data for this ray
|
||||
VMOVE(m_ap.a_ray.r_pt, ray->point);
|
||||
VMOVE(m_ap.a_ray.r_dir, ray->direc);
|
||||
m_ap.a_ray_length = ray->length;
|
||||
m_ap.a_uptr = (void *) &(ray->results);
|
||||
m_ap.a_x = ray->results.x;
|
||||
m_ap.a_y = ray->results.y;
|
||||
|
||||
// perform shot
|
||||
(void)rt_shootray(&m_ap);
|
||||
}
|
||||
|
||||
} // namespace BRLCAD
|
||||
|
||||
} // namespace GeomConversion
|
||||
@@ -0,0 +1,80 @@
|
||||
/* DbTracer.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 10/02/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Implements the IGeometryTracer interface for shotlining BRL-CAD targets.
|
||||
*/
|
||||
|
||||
#ifndef BRLCADDBTRACER_H
|
||||
#define BRLCADDBTRACER_H
|
||||
|
||||
// BRL-CAD libraries
|
||||
extern "C" {
|
||||
#include "bu.h"
|
||||
#include "vmath.h"
|
||||
#include "raytrace.h"
|
||||
#include "rtgeom.h"
|
||||
}
|
||||
|
||||
// Local headers
|
||||
#include "Interface/IGeometryTracer.h"
|
||||
#include "DbGeometry.h"
|
||||
|
||||
namespace GeomConversion {
|
||||
|
||||
namespace BRLCAD {
|
||||
|
||||
/**
|
||||
* DbTracer
|
||||
*
|
||||
* Implements the IGeometryTracer interface for BRL-CAD targets.
|
||||
*/
|
||||
class DbTracer : public Interface::IGeometryTracer
|
||||
{
|
||||
public:
|
||||
DbTracer(Interface::INativeGeometry*, int);
|
||||
~DbTracer();
|
||||
|
||||
virtual void fireRay(Interface::trace_data*);
|
||||
|
||||
private:
|
||||
int m_cpuID;
|
||||
struct application m_ap;
|
||||
};
|
||||
|
||||
} // namespace BRLCAD
|
||||
|
||||
} // namespace GeomConversion
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../Auxiliary
|
||||
)
|
||||
|
||||
add_library(BallPivoting SHARED ballpivoting.c)
|
||||
target_link_libraries(BallPivoting AUX)
|
||||
set_target_properties(BallPivoting PROPERTIES VERSION 1.0.0 SOVERSION 1)
|
||||
|
||||
install(TARGETS BallPivoting
|
||||
RUNTIME DESTINATION ${BIN_DIR}
|
||||
LIBRARY DESTINATION ${LIB_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_DIR})
|
||||
|
||||
if(MSVC)
|
||||
set_property(TARGET BallPivoting APPEND PROPERTY COMPILE_DEFINITIONS "BALLPIVOTING_DLL_EXPORTS")
|
||||
endif(MSVC)
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 8
|
||||
# mode: cmake
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
# ex: shiftwidth=2 tabstop=8
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,202 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Define to use double floating point precision */
|
||||
/*
|
||||
#define BP_CONF_DOUBLE_PRECISION
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef BP_CONF_DOUBLE_PRECISION
|
||||
typedef double bpf;
|
||||
#else
|
||||
typedef float bpf;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
////
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int orphancount;
|
||||
int hingelostcount;
|
||||
int conflictcount;
|
||||
int pointdupcount;
|
||||
} bpInfo;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double progress;
|
||||
int stage;
|
||||
const char *stagename;
|
||||
long trianglecount;
|
||||
long triangleguess;
|
||||
} bpStatus;
|
||||
|
||||
enum
|
||||
{
|
||||
BP_STATUS_STAGE_INIT,
|
||||
BP_STATUS_STAGE_SORT,
|
||||
BP_STATUS_STAGE_MESH,
|
||||
BP_STATUS_STAGE_STRIP,
|
||||
BP_STATUS_STAGE_CONNECT,
|
||||
BP_STATUS_STAGE_CLEAN,
|
||||
BP_STATUS_STAGE_NORMALS,
|
||||
BP_STATUS_STAGE_PACK,
|
||||
BP_STATUS_STAGE_STORE,
|
||||
BP_STATUS_STAGE_DONE,
|
||||
|
||||
BP_STATUS_STAGE_COUNT
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Input format configuration */
|
||||
size_t vertexcount;
|
||||
bpf *vertex;
|
||||
size_t vertexstride;
|
||||
bpf *normal;
|
||||
size_t normalstride;
|
||||
|
||||
/* Ball settings */
|
||||
bpf ballradiusmin;
|
||||
bpf ballradiusmax;
|
||||
|
||||
/* Ouput format configuration */
|
||||
int trianglewinding; /* BP_TRIANGLE_WINDING_CW or BP_TRIANGLE_WINDING_CCW */
|
||||
size_t trianglestride; /* Stride between triangles for indices */
|
||||
size_t triangleindexsize; /* Size of index integers : 1, 2, 4 or 8 ; a value of 0 defaults to 4 */
|
||||
size_t triangleoffset; /* Offset within triangle entry where to store indices sequentially */
|
||||
void *(*trianglealloc)( void *allocopaque, size_t size );
|
||||
void *allocopaque;
|
||||
|
||||
/* Vertex packing callback */
|
||||
void *packopaquepointer;
|
||||
void (*packcallback)( void *opaquepointer, long newvertexindex, long oldvertexindex );
|
||||
|
||||
/* Status callback */
|
||||
long statusmiliseconds;
|
||||
void *statusopaquepointer;
|
||||
void (*statuscallback)( void *opaquepointer, const bpStatus *status );
|
||||
|
||||
/* Advanced configuration options */
|
||||
int hashextrabits;
|
||||
int hashlockpageshift;
|
||||
bpf ballradiuspivot;
|
||||
bpf ballradiusoverride;
|
||||
bpf balldistmin; /* Minimum distance away from triangle's surface plane, 0.0 can cause glitches in very rare cases */
|
||||
bpf pivotcosphericalrange;
|
||||
bpf pivotcoplanardist;
|
||||
bpf pivotjoinradiusfactor;
|
||||
bpf pivotforceradiusfactor;
|
||||
bpf pivotoverriderange;
|
||||
bpf dupvertexdistancesoft; /* Discard any vertex closer than this distance to another vertex, stored as ratio of default ball size */
|
||||
bpf dupvertexdistancehard;
|
||||
bpf dupvertexnormalagreement;
|
||||
bpf reductionfactor;
|
||||
bpf seedballradius;
|
||||
bpf seedcoplanardist;
|
||||
bpf seednormalagreement;
|
||||
bpf seednormalagreementsum;
|
||||
bpf seedmarkradius;
|
||||
bpf hingenormalagreement;
|
||||
bpf pivotnormalagreementsoft; /* Normal agreement betwene vertices and created triangles */
|
||||
bpf pivotnormalagreementhard;
|
||||
bpf pivotnormalagreementsumsoft;
|
||||
bpf pivotnormalagreementsumhard;
|
||||
bpf filterplanecutdistance;
|
||||
long randseed;
|
||||
size_t maxmemorysize;
|
||||
|
||||
} bpOperation;
|
||||
|
||||
enum
|
||||
{
|
||||
BP_TRIANGLE_WINDING_CW,
|
||||
BP_TRIANGLE_WINDING_CCW
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t trianglecount;
|
||||
size_t vertexcount; /* Final count of used vertices, if BP_FLAGS_REBUILD_VERTICES was specified */
|
||||
|
||||
void *triangle; /* Allocated triangle data */
|
||||
|
||||
/* Process information sum */
|
||||
bpInfo info;
|
||||
|
||||
int warningcount;
|
||||
int errorcount;
|
||||
long msecs;
|
||||
|
||||
} bpOutput;
|
||||
|
||||
|
||||
#define BP_FLAGS_NORMALIZE_NORMALS (0x1)
|
||||
#define BP_FLAGS_PACK_VERTICES (0x2)
|
||||
#define BP_FLAGS_ALLOW_REDUCTION (0x4)
|
||||
#define BP_FLAGS_RECOMPUTE_NORMALS (0x8)
|
||||
#define BP_FLAGS_SKIP_STRIP_PASS (0x10)
|
||||
#define BP_FLAGS_SKIP_CONNECT_PASS (0x20)
|
||||
#define BP_FLAGS_SKIP_CLEAN_PASS (0x40)
|
||||
|
||||
|
||||
|
||||
void bpOperationInit( bpOperation *op );
|
||||
void bpOperationSetInput( bpOperation *op, size_t vertexcount, bpf *vertex, size_t vertexstride, bpf *normal, size_t normalstride );
|
||||
void bpOperationSetBall( bpOperation *op, bpf ballradius );
|
||||
void bpOperationSetBallRange( bpOperation *op, bpf ballminimum, bpf ballmaximum );
|
||||
int bpOperationSetOutput( bpOperation *op, int trianglewinding, size_t trianglestride, size_t triangleindexsize, size_t triangleoffset, void *(*trianglealloc)( void *allocopaque, size_t size ), void *allocopaque );
|
||||
void bpOperationNormalAgreement( bpOperation *op, bpf softstrictness, bpf hardstrictness );
|
||||
void bpOperationVertexPackCallback( bpOperation *op, void (*packcallback)( void *opaquepointer, long newvertexindex, long oldvertexindex ), void *packopaquepointer );
|
||||
void bpOperationStatusCallback( bpOperation *op, void (*statuscallback)( void *opaquepointer, const bpStatus *status ), void *opaquepointer, long miliseconds );
|
||||
|
||||
|
||||
void *bpConstructMesh( bpOperation *op, bpOutput *output, int threadcount, uint32_t flags );
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Minimum required version of CMake
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3)
|
||||
if(COMMAND CMAKE_POLICY)
|
||||
CMAKE_POLICY(SET CMP0003 NEW)
|
||||
CMAKE_POLICY(SET CMP0007 OLD)
|
||||
if("${CMAKE_VERSION}" VERSION_GREATER 2.8.3)
|
||||
CMAKE_POLICY(SET CMP0017 OLD)
|
||||
endif("${CMAKE_VERSION}" VERSION_GREATER 2.8.3)
|
||||
if ("${CMAKE_VERSION}" VERSION_GREATER 2.99)
|
||||
CMAKE_POLICY(SET CMP0026 OLD)
|
||||
endif ("${CMAKE_VERSION}"
|
||||
VERSION_GREATER 2.99)
|
||||
endif(COMMAND CMAKE_POLICY)
|
||||
|
||||
# set CMake project name
|
||||
project(GCT)
|
||||
|
||||
# The location in which to install executables.
|
||||
if(NOT BIN_DIR)
|
||||
set(BIN_DIR bin)
|
||||
endif(NOT BIN_DIR)
|
||||
|
||||
# The location in which to install libraries.
|
||||
if(NOT LIB_DIR)
|
||||
if(NOT WIN32)
|
||||
set(LIB_DIR lib)
|
||||
else(NOT WIN32)
|
||||
set(LIB_DIR bin)
|
||||
endif(NOT WIN32)
|
||||
endif(NOT LIB_DIR)
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
add_subdirectory(Auxiliary)
|
||||
add_subdirectory(BRLCAD)
|
||||
add_subdirectory(Sampler)
|
||||
add_subdirectory(BallPivoting)
|
||||
add_subdirectory(MeshDecimation)
|
||||
add_subdirectory(psmain)
|
||||
add_subdirectory(bpmain)
|
||||
add_subdirectory(dcmain)
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 8
|
||||
# mode: cmake
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
# ex: shiftwidth=2 tabstop=8
|
||||
@@ -0,0 +1,56 @@
|
||||
/* AppWalkerInterface.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/19/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Interface class that specifies necessary functions to walk a target.
|
||||
*/
|
||||
|
||||
#ifndef APPWALKERINTERFACE_H
|
||||
#define APPWALKERINTERFACE_H
|
||||
|
||||
class BrlcadTreeWalker; // necessary forward declaration
|
||||
|
||||
class AppWalkerInterface
|
||||
{
|
||||
public:
|
||||
virtual void comb_pre_func(struct directory *,
|
||||
BrlcadTreeWalker *) = 0;
|
||||
virtual void comb_post_func(struct directory *,
|
||||
struct rt_comb_internal *,
|
||||
BrlcadTreeWalker *) = 0;
|
||||
virtual void primitive_func(struct directory *,
|
||||
BrlcadTreeWalker *) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/* GLoaderInterface.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/20/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Interface class that specifies necessary functions to load and query
|
||||
* for possible geometry names.
|
||||
*/
|
||||
|
||||
#ifndef GLOADERINTERFACE_H
|
||||
#define GLOADERINTERFACE_H
|
||||
|
||||
/* Standard libraries */
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class GLoaderInterface
|
||||
{
|
||||
public:
|
||||
GLoaderInterface(const std::string filename)
|
||||
: m_fileName(filename)
|
||||
, m_status(true) { ; }
|
||||
|
||||
std::string getFileName() const { return m_fileName; }
|
||||
bool getStatus() { return m_status; } // true = good, false = fail
|
||||
|
||||
virtual std::vector<std::string> getGeomNames() = 0;
|
||||
virtual void startLoader() = 0;
|
||||
|
||||
protected:
|
||||
std::string m_fileName;
|
||||
bool m_status;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,154 @@
|
||||
/* IGeometryTracer.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 10/02/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Interface class that specifies necessary functions to define a
|
||||
* geometry tracer.
|
||||
*/
|
||||
|
||||
#ifndef IGEOMETRYTRACER_H
|
||||
#define IGEOMETRYTRACER_H
|
||||
|
||||
// System headers
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Local headers
|
||||
#include "INativeGeometry.h"
|
||||
|
||||
namespace GeomConversion {
|
||||
|
||||
namespace Interface {
|
||||
|
||||
//*******************************************************************
|
||||
// NAME one_hit
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Holds data used to hold a single hit (in or out) along a ray.
|
||||
//*******************************************************************
|
||||
struct one_hit
|
||||
{
|
||||
double point[3];
|
||||
double normal[3];
|
||||
// long solidNumber;
|
||||
std::string solidName;
|
||||
long solidSurface;
|
||||
};
|
||||
#define ONE_HIT_INIT(onehit) { \
|
||||
memset(onehit.point, 0, sizeof(double)*3); \
|
||||
memset(onehit.normal, 0, sizeof(double)*3); \
|
||||
onehit.solidName = ""; \
|
||||
onehit.solidSurface = 0; \
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME ray_result
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Holds data of all hits along a ray.
|
||||
//*******************************************************************
|
||||
struct ray_results
|
||||
{
|
||||
double origin[3];
|
||||
double dir[3];
|
||||
int x, y;
|
||||
std::vector<struct one_hit> hitData;
|
||||
};
|
||||
#define RAY_RESULTS_INIT(rayres) { \
|
||||
memset(rayres.origin, 0, sizeof(double)*3); \
|
||||
memset(rayres.dir, 0, sizeof(double)*3); \
|
||||
rayres.x = rayres.y = 0; \
|
||||
rayres.hitData.clear(); \
|
||||
}
|
||||
#define RAY_RESULTS_COPY(dest, src) { \
|
||||
RAY_RESULTS_INIT(dest); \
|
||||
memcpy(dest.origin, src.origin, sizeof(double)*3); \
|
||||
memcpy(dest.dir, src.dir, sizeof(double)*3); \
|
||||
dest.x = src.x; \
|
||||
dest.y = src.y; \
|
||||
dest.hitData.insert(dest.hitData.end(), src.hitData.begin(), src.hitData.end()); \
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME trace_ray_data
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Holds data info pertaining to a ray, including the results.
|
||||
//*******************************************************************
|
||||
struct trace_data
|
||||
{
|
||||
double point[3];
|
||||
double direc[3];
|
||||
double length;
|
||||
struct ray_results results;
|
||||
};
|
||||
#define TRACE_DATA_INIT(trd) { \
|
||||
memset(trd.point, 0, sizeof(double)*3); \
|
||||
memset(trd.direc, 0, sizeof(double)*3); \
|
||||
trd.length = 0; \
|
||||
RAY_RESULTS_INIT(trd.results); \
|
||||
}
|
||||
#define TRACE_DATA_COPY(dest, src) { \
|
||||
memcpy(dest.point, src.point, sizeof(double)*3); \
|
||||
memcpy(dest.direc, src.direc, sizeof(double)*3); \
|
||||
dest.length = src.length; \
|
||||
RAY_RESULTS_COPY(dest.results, src.results); \
|
||||
}
|
||||
|
||||
/**
|
||||
* IGeometryTracer
|
||||
*
|
||||
* Defines an interface that specifies necessary functions to define a
|
||||
* geometry tracer.
|
||||
*/
|
||||
class IGeometryTracer
|
||||
{
|
||||
public:
|
||||
IGeometryTracer(INativeGeometry *ng)
|
||||
: m_geometry(ng) { ; }
|
||||
virtual ~IGeometryTracer() { ; }
|
||||
|
||||
/* User must define how to shoot a ray */
|
||||
virtual void fireRay(struct trace_data*) = 0;
|
||||
|
||||
protected:
|
||||
INativeGeometry *m_geometry; /* pointer to a geometry */
|
||||
};
|
||||
|
||||
} // namespace Interface
|
||||
|
||||
} // namespace GeomConversion
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
/* INativeGeometry.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/20/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Interface class that specifies necessary functions to load and operate
|
||||
* with native geometry.
|
||||
*/
|
||||
|
||||
#ifndef INATIVEGEOMETRY_H
|
||||
#define INATIVEGEOMETRY_H
|
||||
|
||||
// System headers
|
||||
#include <string>
|
||||
|
||||
namespace GeomConversion {
|
||||
|
||||
namespace Interface {
|
||||
// geometry types -- these will increase as more types are added
|
||||
enum GeometryType { BRLCAD, UNKNOWN };
|
||||
|
||||
/**
|
||||
* INativeGeometry
|
||||
*
|
||||
* Defines an interface to load and operate with native geometry.
|
||||
*/
|
||||
class INativeGeometry
|
||||
{
|
||||
public:
|
||||
INativeGeometry(std::string filename)
|
||||
: m_filename(filename)
|
||||
, m_geometryType(UNKNOWN) { ; }
|
||||
virtual ~INativeGeometry() { ; }
|
||||
|
||||
GeometryType getGeometryType () { return m_geometryType; }
|
||||
virtual void* getGeometry() = 0;
|
||||
std::string getGeomtryFilename() { return m_filename; }
|
||||
|
||||
virtual void loadGeometry(std::string, int tcount=1) = 0;
|
||||
virtual void cleanupGeometry() {;}
|
||||
|
||||
// These are arrays of 3 elements!
|
||||
virtual double* getGeometryMin() = 0;
|
||||
virtual double* getGeometryMax() = 0;
|
||||
|
||||
// These are needed for certain geometries, ignored for others
|
||||
virtual void loadGeometry(std::string, std::string, int tcount=1) {;}
|
||||
virtual int getMode() {return 2;}
|
||||
virtual int getMaterial() {return 1;}
|
||||
virtual float getThickness() {return 1.0;}
|
||||
virtual int getPosition() {return 2;}
|
||||
|
||||
protected:
|
||||
std::string m_filename;
|
||||
GeometryType m_geometryType;
|
||||
};
|
||||
|
||||
} // namespace Interface
|
||||
|
||||
} // namespace GeomConversion
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,159 @@
|
||||
/* ISampler.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 10/09/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Interface class that specifies what is necessary to be a sampler.
|
||||
*/
|
||||
|
||||
#ifndef ISAMPLER_H
|
||||
#define ISAMPLER_H
|
||||
|
||||
// System headers
|
||||
#include <vector>
|
||||
|
||||
// Qt headers
|
||||
#if defined(COMPILE_FOR_VSL)
|
||||
#define USE_QT 1
|
||||
#else
|
||||
#define USE_QT 0
|
||||
#endif
|
||||
#if USE_QT
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#else
|
||||
/* Pthread libraries */
|
||||
#include <pthread.h>
|
||||
#if defined (_GNU_SOURCE)
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Local headers
|
||||
#include "IGeometryTracer.h"
|
||||
|
||||
// Constructor Parameters are "defined" here (based on
|
||||
// using Qt or not) so it's more readable later.
|
||||
// Also, preprocessor for other things
|
||||
#if USE_QT
|
||||
#define SAMPLER_CONST_DEF Interface::INativeGeometry *ng, \
|
||||
std::vector<Interface::IGeometryTracer *> &tracers, \
|
||||
QList<QThread *> &threads, QObject *parent = NULL
|
||||
#define SAMPLER_CONST_IMP Interface::INativeGeometry *ng, \
|
||||
std::vector<Interface::IGeometryTracer *> &tracers, \
|
||||
QList<QThread *> &threads, QObject *parent
|
||||
#define SAMPLER_CONST_PARAMS ng, tracers, threads, parent
|
||||
#define SAMPLER_CONST_INITS QObject(parent), \
|
||||
m_threads(threads), \
|
||||
m_canceled(false)
|
||||
#define SAMPLER_THREAD_EXIT() { ; }
|
||||
#else
|
||||
#define SAMPLER_CONST_DEF Interface::INativeGeometry *ng, \
|
||||
std::vector<Interface::IGeometryTracer *> &tracers
|
||||
#define SAMPLER_CONST_IMP Interface::INativeGeometry *ng, \
|
||||
std::vector<Interface::IGeometryTracer *>& tracers
|
||||
#define SAMPLER_CONST_PARAMS ng, tracers
|
||||
#define SAMPLER_THREAD_EXIT() pthread_exit(0);
|
||||
#endif
|
||||
|
||||
namespace GeomConversion {
|
||||
|
||||
namespace Interface {
|
||||
|
||||
/**
|
||||
* ISampler
|
||||
*
|
||||
* Defines an interface that specifies what is necessary to be a sampler.
|
||||
*/
|
||||
class ISampler
|
||||
#if USE_QT
|
||||
: public QObject
|
||||
#endif
|
||||
{
|
||||
#if USE_QT
|
||||
Q_OBJECT
|
||||
#endif
|
||||
|
||||
public:
|
||||
ISampler(SAMPLER_CONST_DEF)
|
||||
:
|
||||
#if USE_QT
|
||||
SAMPLER_CONST_INITS,
|
||||
#endif
|
||||
m_geometry(ng)
|
||||
, m_threadsDone(0)
|
||||
, m_tracers(tracers)
|
||||
, m_prepped(false)
|
||||
{ m_threadCount = tracers.size(); }
|
||||
virtual ~ISampler() {;}
|
||||
|
||||
virtual void setSpacing(float) = 0;
|
||||
virtual void prepSample() = 0;
|
||||
virtual void endSample() = 0;
|
||||
|
||||
#if USE_QT
|
||||
virtual void stopSampling() = 0;
|
||||
virtual float getProgress() { return 0.0; }
|
||||
virtual QString getStatusString() { return QString(); }
|
||||
virtual void updateProgress() { emit updateSamplerProgress(); }
|
||||
|
||||
signals:
|
||||
void updateSamplerProgress();
|
||||
void finished();
|
||||
void startWorkers();
|
||||
|
||||
public slots:
|
||||
virtual void workerFinished() = 0;
|
||||
#endif
|
||||
virtual void runSample() = 0;
|
||||
|
||||
protected:
|
||||
#if USE_QT
|
||||
QList<QThread *> &m_threads;
|
||||
bool m_canceled;
|
||||
#endif
|
||||
|
||||
INativeGeometry *m_geometry;
|
||||
int m_threadCount;
|
||||
int m_threadsDone;
|
||||
std::vector<IGeometryTracer *> &m_tracers;
|
||||
bool m_prepped;
|
||||
};
|
||||
|
||||
} // namespace Interface
|
||||
|
||||
} // namespace GeomConversion
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
set(GCT_DECIMATION_SRCS
|
||||
meshcorrection.c
|
||||
meshdecimation.c
|
||||
meshdecimationSSE2.c
|
||||
meshdecimationSSE3.c
|
||||
meshdecimationSSE4p1.c
|
||||
meshoptimizer.c
|
||||
meshoptimization.cpp
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../Auxiliary
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../openNURBS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../tcl/generic
|
||||
)
|
||||
|
||||
add_library(MeshDecimation SHARED ${GCT_DECIMATION_SRCS})
|
||||
target_link_libraries(MeshDecimation AUX ${CMAKE_THREAD_LIBS_INIT})
|
||||
set_target_properties(MeshDecimation PROPERTIES VERSION 1.1.0 SOVERSION 1)
|
||||
|
||||
install(TARGETS MeshDecimation
|
||||
RUNTIME DESTINATION ${BIN_DIR}
|
||||
LIBRARY DESTINATION ${LIB_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_DIR})
|
||||
|
||||
if(MSVC)
|
||||
set_property(TARGET MeshDecimation APPEND PROPERTY COMPILE_DEFINITIONS "DECIMATION_DLL_EXPORTS")
|
||||
endif(MSVC)
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 8
|
||||
# mode: cmake
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
# ex: shiftwidth=2 tabstop=8
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
int mcMeshCorrection( size_t vertexcount, void *vertex, int vertexwidth, size_t vertexstride, size_t tricount, void *indices, int indiceswidth, size_t indicesstride, long attemptcount, int flags )
|
||||
;
|
||||
|
||||
#define MC_FLAGS_TRIANGLE_WINDING_CW (0x1)
|
||||
#define MC_FLAGS_TRIANGLE_WINDING_CCW (0x2)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define MD_ATTRIB_MAX (16)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *base;
|
||||
int width;
|
||||
size_t count;
|
||||
size_t stride;
|
||||
int flags;
|
||||
} mdOpAttrib;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double progress;
|
||||
int stage;
|
||||
const char *stagename;
|
||||
long trianglecount;
|
||||
} mdStatus;
|
||||
|
||||
enum
|
||||
{
|
||||
MD_STATUS_STAGE_INIT,
|
||||
MD_STATUS_STAGE_BUILDVERTICES,
|
||||
MD_STATUS_STAGE_BUILDTRIANGLES,
|
||||
MD_STATUS_STAGE_BUILDTRIREFS,
|
||||
MD_STATUS_STAGE_BUILDQUEUE,
|
||||
MD_STATUS_STAGE_DECIMATION,
|
||||
MD_STATUS_STAGE_STORE,
|
||||
MD_STATUS_STAGE_DONE,
|
||||
|
||||
MD_STATUS_STAGE_COUNT
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t vertexcount;
|
||||
void *vertex;
|
||||
int vertexwidth;
|
||||
size_t vertexstride;
|
||||
size_t vertexalloc;
|
||||
|
||||
void *indices;
|
||||
int indiceswidth;
|
||||
size_t indicesstride;
|
||||
size_t tricount;
|
||||
|
||||
double decimationstrength;
|
||||
int decimationcount;
|
||||
|
||||
int attribcount;
|
||||
mdOpAttrib attrib[MD_ATTRIB_MAX];
|
||||
mdOpAttrib normalattrib;
|
||||
|
||||
long msecs;
|
||||
|
||||
/* Status callback */
|
||||
long statusmiliseconds;
|
||||
void *statusopaquepointer;
|
||||
void (*statuscallback)( void *opaquepointer, const mdStatus *status );
|
||||
|
||||
/* Advanced configuration options */
|
||||
double compactnesstarget;
|
||||
double compactnesspenalty;
|
||||
int syncstepcount;
|
||||
double normalsearchangle;
|
||||
size_t maxmemorysize;
|
||||
|
||||
} mdOperation;
|
||||
|
||||
|
||||
/*
|
||||
* This function exists only to read CPUID and NUMA information once in a thread safe
|
||||
* manner, in case you want to launch multiple mdMeshDecimation() simultaneously.
|
||||
*/
|
||||
void mdInit();
|
||||
|
||||
|
||||
/*
|
||||
* Set up the mdOperation struct to configure a mesh decimation task.
|
||||
*/
|
||||
void mdOperationInit( mdOperation *op );
|
||||
void mdOperationData( mdOperation *op, size_t vertexcount, void *vertex, int vertexwidth, size_t vertexstride, size_t tricount, void *indices, int indiceswidth, size_t indicesstride );
|
||||
int mdOperationAddAttrib( mdOperation *op, void *base, int width, size_t count, size_t stride, int flags );
|
||||
void mdOperationStrength( mdOperation *op, double decimationstrength );
|
||||
void mdOperationStatusCallback( mdOperation *op, void (*statuscallback)( void *opaquepointer, const mdStatus *status ), void *opaquepointer, long miliseconds );
|
||||
|
||||
#define MD_ATTRIB_FLAGS_NORMALIZE (0x1)
|
||||
#define MD_ATTRIB_FLAGS_COMPUTE_NORMALS (0x2)
|
||||
|
||||
|
||||
/*
|
||||
* Decimate the mesh specifed by the mdOperation struct.
|
||||
*/
|
||||
int mdMeshDecimation( mdOperation *operation, int threadcount, int flags );
|
||||
|
||||
/* Slightly increases the quality of the mesh decimation */
|
||||
#define MD_FLAGS_CONTINUOUS_UPDATE (0x1)
|
||||
/* Do not pack vertices */
|
||||
#define MD_FLAGS_NO_VERTEX_PACKING (0x2)
|
||||
/* Allow cloning/splitting of vertices with diverging normals when recomputing normals */
|
||||
#define MD_FLAGS_NORMAL_VERTEX_SPLITTING (0x4)
|
||||
/* Define orientation of triangles when rebuilding normals */
|
||||
#define MD_FLAGS_TRIANGLE_WINDING_CW (0x8)
|
||||
#define MD_FLAGS_TRIANGLE_WINDING_CCW (0x10)
|
||||
/* Do not actually do any decimation, in case all you actually want to do is to recompute normals */
|
||||
#define MD_FLAGS_NO_DECIMATION (0x20)
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
|
||||
#include "cpuconfig.h"
|
||||
|
||||
#include "cpuinfo.h"
|
||||
|
||||
#include "cc.h"
|
||||
#include "mm.h"
|
||||
#include "mmhash.h"
|
||||
#include "math3d.h"
|
||||
|
||||
#include "mmbinsort.h"
|
||||
#include "meshdecimation.h"
|
||||
|
||||
|
||||
#ifdef __SSE__
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE2__
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE3__
|
||||
#include <pmmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSSE3__
|
||||
#include <tmmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE4A__
|
||||
#include <ammintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE4_1__
|
||||
#include <smmintrin.h>
|
||||
#endif
|
||||
|
||||
|
||||
/****/
|
||||
|
||||
|
||||
#ifdef __SSE2__
|
||||
#define MD_CONFIG_SSE2_SUPPORT
|
||||
#else
|
||||
#warning "SSE2 wasn't enabled to compile this file."
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
|
||||
#define RF_ALIGN16 __attribute__((aligned(16)))
|
||||
#elif defined(_MSC_VER)
|
||||
#define RF_ALIGN16 __declspec(align(16))
|
||||
#else
|
||||
#define RF_ALIGN16
|
||||
#warning "SSE Disabled: Unsupported Compiler."
|
||||
#ifdef MD_CONFIG_SSE2_SUPPORT
|
||||
#undef MD_CONFIG_SSE2_SUPPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define MD_CONFIG_SSE_APPROX
|
||||
|
||||
|
||||
|
||||
#ifdef MD_CONFIG_SSE2_SUPPORT
|
||||
|
||||
typedef union
|
||||
{
|
||||
__m128 v;
|
||||
float f[4];
|
||||
} m128f;
|
||||
|
||||
int mdPathSSE2 = 0x1 | 0x2;
|
||||
|
||||
|
||||
#define MD_COMPACTNESS_NORMALIZATION_FACTOR (0.5*4.0*1.732050808)
|
||||
|
||||
float mdEdgeCollapsePenaltyTriangleSSE2f( float *newpoint, float *oldpoint, float *leftpoint, float *rightpoint, int *denyflag, float compactnesstarget )
|
||||
{
|
||||
float penalty, compactness, oldcompactness, newcompactness, vectadp, norm;
|
||||
__m128 left;
|
||||
m128f vecta, oldvectb, oldvectc, newvectb, newvectc, oldnormal, newnormal;
|
||||
|
||||
/* Normal of old triangle */
|
||||
left = _mm_load_ps( leftpoint );
|
||||
vecta.v = _mm_sub_ps( _mm_load_ps( rightpoint ), left );
|
||||
oldvectb.v = _mm_sub_ps( _mm_load_ps( oldpoint ), left );
|
||||
oldnormal.v = _mm_sub_ps(
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta.v, vecta.v, _MM_SHUFFLE(3,0,2,1) ), _mm_shuffle_ps( oldvectb.v, oldvectb.v, _MM_SHUFFLE(3,1,0,2) ) ),
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta.v, vecta.v, _MM_SHUFFLE(3,1,0,2) ), _mm_shuffle_ps( oldvectb.v, oldvectb.v, _MM_SHUFFLE(3,0,2,1) ) )
|
||||
);
|
||||
|
||||
/* Normal of new triangle */
|
||||
newvectb.v = _mm_sub_ps( _mm_load_ps( newpoint ), left );
|
||||
newnormal.v = _mm_sub_ps(
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta.v, vecta.v, _MM_SHUFFLE(3,0,2,1) ), _mm_shuffle_ps( newvectb.v, newvectb.v, _MM_SHUFFLE(3,1,0,2) ) ),
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta.v, vecta.v, _MM_SHUFFLE(3,1,0,2) ), _mm_shuffle_ps( newvectb.v, newvectb.v, _MM_SHUFFLE(3,0,2,1) ) )
|
||||
);
|
||||
|
||||
/* Detect normal inversion */
|
||||
if( M3D_VectorDotProduct( oldnormal.f, newnormal.f ) < 0.0 )
|
||||
{
|
||||
*denyflag = 1;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* Penalize long thin triangles */
|
||||
penalty = 0.0;
|
||||
vectadp = M3D_VectorDotProduct( vecta.f, vecta.f );
|
||||
newvectc.v = _mm_sub_ps( _mm_load_ps( newpoint ), _mm_load_ps( rightpoint ) );
|
||||
#ifdef MD_CONFIG_SSE_APPROX
|
||||
norm = vectadp + M3D_VectorDotProduct( newvectb.f, newvectb.f ) + M3D_VectorDotProduct( newvectc.f, newvectc.f );
|
||||
newcompactness = _mm_cvtss_f32( _mm_mul_ss( _mm_set_ss( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_rcp_ss( _mm_mul_ss( _mm_rsqrt_ss( _mm_set_ss( M3D_VectorDotProduct( newnormal.f, newnormal.f ) ) ), _mm_set_ss( norm ) ) ) ) );
|
||||
if( newcompactness < compactnesstarget )
|
||||
{
|
||||
#else
|
||||
newcompactness = MD_COMPACTNESS_NORMALIZATION_FACTOR * sqrtf( M3D_VectorDotProduct( newnormal.f, newnormal.f ) );
|
||||
norm = vectadp + M3D_VectorDotProduct( newvectb.f, newvectb.f ) + M3D_VectorDotProduct( newvectc.f, newvectc.f );
|
||||
if( newcompactness < ( compactnesstarget * norm ) )
|
||||
{
|
||||
newcompactness /= norm;
|
||||
#endif
|
||||
oldvectc.v = _mm_sub_ps( _mm_load_ps( oldpoint ), _mm_load_ps( rightpoint ) );
|
||||
#ifdef MD_CONFIG_SSE_APPROX
|
||||
norm = vectadp + M3D_VectorDotProduct( oldvectb.f, oldvectb.f ) + M3D_VectorDotProduct( oldvectc.f, oldvectc.f );
|
||||
oldcompactness = _mm_cvtss_f32( _mm_mul_ss( _mm_set_ss( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_rcp_ss( _mm_mul_ss( _mm_rsqrt_ss( _mm_set_ss( M3D_VectorDotProduct( oldnormal.f, oldnormal.f ) ) ), _mm_set_ss( norm ) ) ) ) );
|
||||
#else
|
||||
oldcompactness = ( MD_COMPACTNESS_NORMALIZATION_FACTOR * sqrtf( M3D_VectorDotProduct( oldnormal.f, oldnormal.f ) ) ) / ( vectadp + M3D_VectorDotProduct( oldvectb.f, oldvectb.f ) + M3D_VectorDotProduct( oldvectc.f, oldvectc.f ) );
|
||||
#endif
|
||||
compactness = fmin( compactnesstarget, oldcompactness ) - newcompactness;
|
||||
if( compactness > 0.0 )
|
||||
penalty = compactness;
|
||||
}
|
||||
|
||||
return penalty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
double mdEdgeCollapsePenaltyTriangleSSE2d( double *newpoint, double *oldpoint, double *leftpoint, double *rightpoint, int *denyflag, double compactnesstarget )
|
||||
{
|
||||
__m128d vecta0, vecta1, oldvectb0, oldvectb1, oldvectc0, oldvectc1, newvectb0, newvectb1, newvectc0, newvectc1;
|
||||
__m128d oldnormal0, oldnormal1, newnormal0, newnormal1;
|
||||
__m128d dotprsum;
|
||||
__m128d left0, left1;
|
||||
double newcompactness, oldcompactness, compactness, penalty, norm;
|
||||
static double zero = 0.0;
|
||||
|
||||
/* Normal of old triangle */
|
||||
left0 = _mm_load_pd( leftpoint+0 );
|
||||
left1 = _mm_load_sd( leftpoint+2 );
|
||||
vecta0 = _mm_sub_pd( _mm_load_pd( rightpoint+0 ), left0 );
|
||||
vecta1 = _mm_sub_pd( _mm_load_pd( rightpoint+2 ), left1 );
|
||||
oldvectb0 = _mm_sub_pd( _mm_load_pd( oldpoint+0 ), left0 );
|
||||
oldvectb1 = _mm_sub_pd( _mm_load_pd( oldpoint+2 ), left1 );
|
||||
oldnormal0 = _mm_sub_pd(
|
||||
_mm_mul_pd( _mm_shuffle_pd( vecta0, vecta1, _MM_SHUFFLE2(0,1) ), _mm_unpacklo_pd( oldvectb1, oldvectb0 ) ),
|
||||
_mm_mul_pd( _mm_unpacklo_pd( vecta1, vecta0 ), _mm_shuffle_pd( oldvectb0, oldvectb1, _MM_SHUFFLE2(0,1) ) )
|
||||
);
|
||||
oldnormal1 = _mm_sub_sd(
|
||||
_mm_mul_sd( vecta0, _mm_unpackhi_pd( oldvectb0, oldvectb0 ) ),
|
||||
_mm_mul_sd( _mm_unpackhi_pd( vecta0, vecta0 ), oldvectb0 )
|
||||
);
|
||||
|
||||
/* Normal of new triangle */
|
||||
newvectb0 = _mm_sub_pd( _mm_load_pd( newpoint+0 ), left0 );
|
||||
newvectb1 = _mm_sub_pd( _mm_load_pd( newpoint+2 ), left1 );
|
||||
newnormal0 = _mm_sub_pd(
|
||||
_mm_mul_pd( _mm_shuffle_pd( vecta0, vecta1, _MM_SHUFFLE2(0,1) ), _mm_unpacklo_pd( newvectb1, newvectb0 ) ),
|
||||
_mm_mul_pd( _mm_unpacklo_pd( vecta1, vecta0 ), _mm_shuffle_pd( newvectb0, newvectb1, _MM_SHUFFLE2(0,1) ) )
|
||||
);
|
||||
newnormal1 = _mm_sub_sd(
|
||||
_mm_mul_sd( vecta0, _mm_unpackhi_pd( newvectb0, newvectb0 ) ),
|
||||
_mm_mul_sd( _mm_unpackhi_pd( vecta0, vecta0 ), newvectb0 )
|
||||
);
|
||||
|
||||
/* Detect normal inversion */
|
||||
dotprsum = _mm_mul_pd( oldnormal0, newnormal0 );
|
||||
dotprsum = _mm_add_sd( _mm_add_sd( dotprsum, _mm_unpackhi_pd( dotprsum, dotprsum ) ), _mm_mul_sd( oldnormal1, newnormal1 ) );
|
||||
if( _mm_comilt_sd( dotprsum, _mm_load_sd( &zero ) ) )
|
||||
{
|
||||
*denyflag = 1;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* Penalize long thin triangles */
|
||||
penalty = 0.0;
|
||||
vecta0 = _mm_mul_pd( vecta0, vecta0 );
|
||||
vecta0 = _mm_add_sd( _mm_add_sd( vecta0, _mm_unpackhi_pd( vecta0, vecta0 ) ), _mm_mul_sd( vecta1, vecta1 ) );
|
||||
newvectc0 = _mm_sub_pd( _mm_load_pd( newpoint+0 ), _mm_load_pd( rightpoint+0 ) );
|
||||
newvectc1 = _mm_sub_sd( _mm_load_sd( newpoint+2 ), _mm_load_sd( rightpoint+2 ) );
|
||||
newnormal0 = _mm_mul_pd( newnormal0, newnormal0 );
|
||||
newnormal0 = _mm_add_sd( _mm_add_sd( newnormal0, _mm_unpackhi_pd( newnormal0, newnormal0 ) ), _mm_mul_sd( newnormal1, newnormal1 ) );
|
||||
newvectb0 = _mm_mul_pd( newvectb0, newvectb0 );
|
||||
newvectb0 = _mm_add_sd( _mm_add_sd( newvectb0, _mm_unpackhi_pd( newvectb0, newvectb0 ) ), _mm_mul_sd( newvectb1, newvectb1 ) );
|
||||
newvectc0 = _mm_mul_pd( newvectc0, newvectc0 );
|
||||
newvectc0 = _mm_add_sd( _mm_add_sd( newvectc0, _mm_unpackhi_pd( newvectc0, newvectc0 ) ), _mm_mul_sd( newvectc1, newvectc1 ) );
|
||||
norm = _mm_cvtsd_f64( _mm_add_sd( vecta0, _mm_add_sd( newvectb0, newvectc0 ) ) );
|
||||
newcompactness = _mm_cvtsd_f64( _mm_mul_sd( _mm_set_sd( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_sqrt_sd( newnormal0, newnormal0 ) ) );
|
||||
if( newcompactness < ( compactnesstarget * norm ) )
|
||||
{
|
||||
newcompactness /= norm;
|
||||
oldvectc0 = _mm_sub_pd( _mm_load_pd( oldpoint+0 ), _mm_load_pd( rightpoint+0 ) );
|
||||
oldvectc1 = _mm_sub_sd( _mm_load_sd( oldpoint+2 ), _mm_load_sd( rightpoint+2 ) );
|
||||
oldnormal0 = _mm_mul_pd( oldnormal0, oldnormal0 );
|
||||
oldnormal0 = _mm_add_sd( _mm_add_sd( oldnormal0, _mm_unpackhi_pd( oldnormal0, oldnormal0 ) ), _mm_mul_sd( oldnormal1, oldnormal1 ) );
|
||||
oldvectb0 = _mm_mul_pd( oldvectb0, oldvectb0 );
|
||||
oldvectb0 = _mm_add_sd( _mm_add_sd( oldvectb0, _mm_unpackhi_pd( oldvectb0, oldvectb0 ) ), _mm_mul_sd( oldvectb1, oldvectb1 ) );
|
||||
oldvectc0 = _mm_mul_pd( oldvectc0, oldvectc0 );
|
||||
oldvectc0 = _mm_add_sd( _mm_add_sd( oldvectc0, _mm_unpackhi_pd( oldvectc0, oldvectc0 ) ), _mm_mul_sd( oldvectc1, oldvectc1 ) );
|
||||
oldcompactness = _mm_cvtsd_f64( _mm_div_sd( _mm_mul_sd( _mm_set_sd( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_sqrt_sd( oldnormal0, oldnormal0 ) ), _mm_add_sd( vecta0, _mm_add_sd( oldvectb0, oldvectc0 ) ) ) );
|
||||
compactness = fmin( compactnesstarget, oldcompactness ) - newcompactness;
|
||||
if( compactness > 0.0 )
|
||||
penalty = compactness;
|
||||
}
|
||||
|
||||
return penalty;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
int mdPathSSE2 = 0x0;
|
||||
|
||||
float mdEdgeCollapsePenaltyTriangleSSE2f( float *newpoint, float *oldpoint, float *leftpoint, float *rightpoint, int *denyflag )
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double mdEdgeCollapsePenaltyTriangleSSE2d( double *newpoint, double *oldpoint, double *leftpoint, double *rightpoint, int *denyflag )
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
|
||||
#include "cpuconfig.h"
|
||||
|
||||
#include "cpuinfo.h"
|
||||
|
||||
#include "cc.h"
|
||||
#include "mm.h"
|
||||
#include "mmhash.h"
|
||||
#include "math3d.h"
|
||||
|
||||
#include "mmbinsort.h"
|
||||
#include "meshdecimation.h"
|
||||
|
||||
|
||||
#ifdef __SSE__
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE2__
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE3__
|
||||
#include <pmmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSSE3__
|
||||
#include <tmmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE4A__
|
||||
#include <ammintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE4_1__
|
||||
#include <smmintrin.h>
|
||||
#endif
|
||||
|
||||
|
||||
/****/
|
||||
|
||||
|
||||
#ifdef __SSE3__
|
||||
#define MD_CONFIG_SSE3_SUPPORT
|
||||
#else
|
||||
#warning "SSE3 wasn't enabled to compile this file."
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
|
||||
#define RF_ALIGN16 __attribute__((aligned(16)))
|
||||
#elif defined(_MSC_VER)
|
||||
#define RF_ALIGN16 __declspec(align(16))
|
||||
#else
|
||||
#define RF_ALIGN16
|
||||
#warning "SSE Disabled: Unsupported Compiler."
|
||||
#ifdef MD_CONFIG_SSE3_SUPPORT
|
||||
#undef MD_CONFIG_SSE3_SUPPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define MD_CONFIG_SSE_APPROX
|
||||
|
||||
|
||||
|
||||
#ifdef MD_CONFIG_SSE3_SUPPORT
|
||||
|
||||
|
||||
int mdPathSSE3 = 0x1 | 0x2;
|
||||
|
||||
|
||||
#define MD_COMPACTNESS_NORMALIZATION_FACTOR (0.5*4.0*1.732050808)
|
||||
|
||||
float mdEdgeCollapsePenaltyTriangleSSE3f( float *newpoint, float *oldpoint, float *leftpoint, float *rightpoint, int *denyflag, float compactnesstarget )
|
||||
{
|
||||
float penalty, compactness, oldcompactness, newcompactness;
|
||||
static float zero = 0.0;
|
||||
__m128 left, vecta, oldvectb, oldvectc, newvectb, newvectc, oldnormal, newnormal, dotproduct;
|
||||
|
||||
/* Normal of old triangle */
|
||||
left = _mm_load_ps( leftpoint );
|
||||
vecta = _mm_sub_ps( _mm_load_ps( rightpoint ), left );
|
||||
oldvectb = _mm_sub_ps( _mm_load_ps( oldpoint ), left );
|
||||
oldnormal = _mm_sub_ps(
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta, vecta, _MM_SHUFFLE(3,0,2,1) ), _mm_shuffle_ps( oldvectb, oldvectb, _MM_SHUFFLE(3,1,0,2) ) ),
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta, vecta, _MM_SHUFFLE(3,1,0,2) ), _mm_shuffle_ps( oldvectb, oldvectb, _MM_SHUFFLE(3,0,2,1) ) )
|
||||
);
|
||||
|
||||
/* Normal of new triangle */
|
||||
newvectb = _mm_sub_ps( _mm_load_ps( newpoint ), left );
|
||||
newnormal = _mm_sub_ps(
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta, vecta, _MM_SHUFFLE(3,0,2,1) ), _mm_shuffle_ps( newvectb, newvectb, _MM_SHUFFLE(3,1,0,2) ) ),
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta, vecta, _MM_SHUFFLE(3,1,0,2) ), _mm_shuffle_ps( newvectb, newvectb, _MM_SHUFFLE(3,0,2,1) ) )
|
||||
);
|
||||
|
||||
/* Detect normal inversion */
|
||||
dotproduct = _mm_mul_ps( oldnormal, newnormal );
|
||||
dotproduct = _mm_hadd_ps( dotproduct, dotproduct );
|
||||
dotproduct = _mm_hadd_ps( dotproduct, dotproduct );
|
||||
if( _mm_comilt_ss( dotproduct, _mm_load_ss( &zero ) ) )
|
||||
{
|
||||
*denyflag = 1;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* Penalize long thin triangles */
|
||||
penalty = 0.0;
|
||||
vecta = _mm_mul_ps( vecta, vecta );
|
||||
vecta = _mm_hadd_ps( vecta, vecta );
|
||||
vecta = _mm_hadd_ps( vecta, vecta );
|
||||
newvectc = _mm_sub_ps( _mm_load_ps( newpoint ), _mm_load_ps( rightpoint ) );
|
||||
newnormal = _mm_mul_ps( newnormal, newnormal );
|
||||
newnormal = _mm_hadd_ps( newnormal, newnormal );
|
||||
newnormal = _mm_hadd_ps( newnormal, newnormal );
|
||||
newvectb = _mm_mul_ps( newvectb, newvectb );
|
||||
newvectb = _mm_hadd_ps( newvectb, newvectb );
|
||||
newvectb = _mm_hadd_ps( newvectb, newvectb );
|
||||
newvectc = _mm_mul_ps( newvectc, newvectc );
|
||||
newvectc = _mm_hadd_ps( newvectc, newvectc );
|
||||
newvectc = _mm_hadd_ps( newvectc, newvectc );
|
||||
#ifdef MD_CONFIG_SSE_APPROX
|
||||
newcompactness = _mm_cvtss_f32( _mm_mul_ss( _mm_set_ss( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_rcp_ss( _mm_mul_ss( _mm_rsqrt_ss( newnormal ), _mm_add_ss( _mm_add_ss( vecta, newvectb ), newvectc ) ) ) ) );
|
||||
#else
|
||||
newcompactness = _mm_cvtss_f32( _mm_div_ss( _mm_mul_ss( _mm_set_ss( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_sqrt_ss( newnormal ) ), _mm_add_ss( _mm_add_ss( vecta, newvectb ), newvectc ) ) );
|
||||
#endif
|
||||
if( newcompactness < compactnesstarget )
|
||||
{
|
||||
oldvectc = _mm_sub_ps( _mm_load_ps( oldpoint ), _mm_load_ps( rightpoint ) );
|
||||
oldnormal = _mm_mul_ps( oldnormal, oldnormal );
|
||||
oldnormal = _mm_hadd_ps( oldnormal, oldnormal );
|
||||
oldnormal = _mm_hadd_ps( oldnormal, oldnormal );
|
||||
oldvectb = _mm_mul_ps( oldvectb, oldvectb );
|
||||
oldvectb = _mm_hadd_ps( oldvectb, oldvectb );
|
||||
oldvectb = _mm_hadd_ps( oldvectb, oldvectb );
|
||||
oldvectc = _mm_mul_ps( oldvectc, oldvectc );
|
||||
oldvectc = _mm_hadd_ps( oldvectc, oldvectc );
|
||||
oldvectc = _mm_hadd_ps( oldvectc, oldvectc );
|
||||
#ifdef MD_CONFIG_SSE_APPROX
|
||||
oldcompactness = _mm_cvtss_f32( _mm_mul_ss( _mm_set_ss( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_rcp_ss( _mm_mul_ss( _mm_rsqrt_ss( oldnormal ), _mm_add_ss( _mm_add_ss( vecta, oldvectb ), oldvectc ) ) ) ) );
|
||||
#else
|
||||
oldcompactness = _mm_cvtss_f32( _mm_div_ss( _mm_mul_ss( _mm_set_ss( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_sqrt_ss( oldnormal ) ), _mm_add_ss( _mm_add_ss( vecta, oldvectb ), oldvectc ) ) );
|
||||
#endif
|
||||
compactness = fmin( compactnesstarget, oldcompactness ) - newcompactness;
|
||||
if( compactness > 0.0 )
|
||||
penalty = compactness;
|
||||
}
|
||||
|
||||
return penalty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double mdEdgeCollapsePenaltyTriangleSSE3d( double *newpoint, double *oldpoint, double *leftpoint, double *rightpoint, int *denyflag, double compactnesstarget )
|
||||
{
|
||||
__m128d vecta0, vecta1, oldvectb0, oldvectb1, oldvectc0, oldvectc1, newvectb0, newvectb1, newvectc0, newvectc1;
|
||||
__m128d oldnormal0, oldnormal1, newnormal0, newnormal1;
|
||||
__m128d dotprsum;
|
||||
__m128d left0, left1;
|
||||
double newcompactness, oldcompactness, compactness, penalty, norm;
|
||||
static double zero = 0.0;
|
||||
|
||||
/* Normal of old triangle */
|
||||
left0 = _mm_load_pd( leftpoint+0 );
|
||||
left1 = _mm_load_sd( leftpoint+2 );
|
||||
vecta0 = _mm_sub_pd( _mm_load_pd( rightpoint+0 ), left0 );
|
||||
vecta1 = _mm_sub_pd( _mm_load_pd( rightpoint+2 ), left1 );
|
||||
oldvectb0 = _mm_sub_pd( _mm_load_pd( oldpoint+0 ), left0 );
|
||||
oldvectb1 = _mm_sub_pd( _mm_load_pd( oldpoint+2 ), left1 );
|
||||
oldnormal0 = _mm_sub_pd(
|
||||
_mm_mul_pd( _mm_shuffle_pd( vecta0, vecta1, _MM_SHUFFLE2(0,1) ), _mm_unpacklo_pd( oldvectb1, oldvectb0 ) ),
|
||||
_mm_mul_pd( _mm_unpacklo_pd( vecta1, vecta0 ), _mm_shuffle_pd( oldvectb0, oldvectb1, _MM_SHUFFLE2(0,1) ) )
|
||||
);
|
||||
oldnormal1 = _mm_sub_sd(
|
||||
_mm_mul_sd( vecta0, _mm_unpackhi_pd( oldvectb0, oldvectb0 ) ),
|
||||
_mm_mul_sd( _mm_unpackhi_pd( vecta0, vecta0 ), oldvectb0 )
|
||||
);
|
||||
|
||||
/* Normal of new triangle */
|
||||
newvectb0 = _mm_sub_pd( _mm_load_pd( newpoint+0 ), left0 );
|
||||
newvectb1 = _mm_sub_pd( _mm_load_pd( newpoint+2 ), left1 );
|
||||
newnormal0 = _mm_sub_pd(
|
||||
_mm_mul_pd( _mm_shuffle_pd( vecta0, vecta1, _MM_SHUFFLE2(0,1) ), _mm_unpacklo_pd( newvectb1, newvectb0 ) ),
|
||||
_mm_mul_pd( _mm_unpacklo_pd( vecta1, vecta0 ), _mm_shuffle_pd( newvectb0, newvectb1, _MM_SHUFFLE2(0,1) ) )
|
||||
);
|
||||
newnormal1 = _mm_sub_sd(
|
||||
_mm_mul_sd( vecta0, _mm_unpackhi_pd( newvectb0, newvectb0 ) ),
|
||||
_mm_mul_sd( _mm_unpackhi_pd( vecta0, vecta0 ), newvectb0 )
|
||||
);
|
||||
|
||||
/* Detect normal inversion */
|
||||
dotprsum = _mm_mul_pd( oldnormal0, newnormal0 );
|
||||
dotprsum = _mm_add_sd( _mm_hadd_pd( dotprsum, dotprsum ), _mm_mul_sd( oldnormal1, newnormal1 ) );
|
||||
if( _mm_comilt_sd( dotprsum, _mm_load_sd( &zero ) ) )
|
||||
{
|
||||
*denyflag = 1;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* Penalize long thin triangles */
|
||||
penalty = 0.0;
|
||||
vecta0 = _mm_mul_pd( vecta0, vecta0 );
|
||||
vecta0 = _mm_add_sd( _mm_hadd_pd( vecta0, vecta0 ), _mm_mul_sd( vecta1, vecta1 ) );
|
||||
newvectc0 = _mm_sub_pd( _mm_load_pd( newpoint+0 ), _mm_load_pd( rightpoint+0 ) );
|
||||
newvectc1 = _mm_sub_sd( _mm_load_sd( newpoint+2 ), _mm_load_sd( rightpoint+2 ) );
|
||||
newnormal0 = _mm_mul_pd( newnormal0, newnormal0 );
|
||||
newnormal0 = _mm_add_sd( _mm_hadd_pd( newnormal0, newnormal0 ), _mm_mul_sd( newnormal1, newnormal1 ) );
|
||||
newvectb0 = _mm_mul_pd( newvectb0, newvectb0 );
|
||||
newvectb0 = _mm_add_sd( _mm_hadd_pd( newvectb0, newvectb0 ), _mm_mul_sd( newvectb1, newvectb1 ) );
|
||||
newvectc0 = _mm_mul_pd( newvectc0, newvectc0 );
|
||||
newvectc0 = _mm_add_sd( _mm_hadd_pd( newvectc0, newvectc0 ), _mm_mul_sd( newvectc1, newvectc1 ) );
|
||||
norm = _mm_cvtsd_f64( _mm_add_sd( vecta0, _mm_add_sd( newvectb0, newvectc0 ) ) );
|
||||
newcompactness = _mm_cvtsd_f64( _mm_mul_sd( _mm_set_sd( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_sqrt_sd( newnormal0, newnormal0 ) ) );
|
||||
if( newcompactness < ( compactnesstarget * norm ) )
|
||||
{
|
||||
newcompactness /= norm;
|
||||
oldvectc0 = _mm_sub_pd( _mm_load_pd( oldpoint+0 ), _mm_load_pd( rightpoint+0 ) );
|
||||
oldvectc1 = _mm_sub_sd( _mm_load_sd( oldpoint+2 ), _mm_load_sd( rightpoint+2 ) );
|
||||
oldnormal0 = _mm_mul_pd( oldnormal0, oldnormal0 );
|
||||
oldnormal0 = _mm_add_sd( _mm_hadd_pd( oldnormal0, oldnormal0 ), _mm_mul_sd( oldnormal1, oldnormal1 ) );
|
||||
oldvectb0 = _mm_mul_pd( oldvectb0, oldvectb0 );
|
||||
oldvectb0 = _mm_add_sd( _mm_hadd_pd( oldvectb0, oldvectb0 ), _mm_mul_sd( oldvectb1, oldvectb1 ) );
|
||||
oldvectc0 = _mm_mul_pd( oldvectc0, oldvectc0 );
|
||||
oldvectc0 = _mm_add_sd( _mm_hadd_pd( oldvectc0, oldvectc0 ), _mm_mul_sd( oldvectc1, oldvectc1 ) );
|
||||
oldcompactness = _mm_cvtsd_f64( _mm_div_sd( _mm_mul_sd( _mm_set_sd( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_sqrt_sd( oldnormal0, oldnormal0 ) ), _mm_add_sd( vecta0, _mm_add_sd( oldvectb0, oldvectc0 ) ) ) );
|
||||
compactness = fmin( compactnesstarget, oldcompactness ) - newcompactness;
|
||||
if( compactness > 0.0 )
|
||||
penalty = compactness;
|
||||
}
|
||||
|
||||
return penalty;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
int mdPathSSE3 = 0x0;
|
||||
|
||||
float mdEdgeCollapsePenaltyTriangleSSE3f( float *newpoint, float *oldpoint, float *leftpoint, float *rightpoint, int *denyflag )
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double mdEdgeCollapsePenaltyTriangleSSE3d( double *newpoint, double *oldpoint, double *leftpoint, double *rightpoint, int *denyflag )
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
|
||||
#include "cpuconfig.h"
|
||||
|
||||
#include "cpuinfo.h"
|
||||
|
||||
#include "cc.h"
|
||||
#include "mm.h"
|
||||
#include "mmhash.h"
|
||||
#include "math3d.h"
|
||||
|
||||
#include "mmbinsort.h"
|
||||
#include "meshdecimation.h"
|
||||
|
||||
|
||||
#ifdef __SSE__
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE2__
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE3__
|
||||
#include <pmmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSSE3__
|
||||
#include <tmmintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE4A__
|
||||
#include <ammintrin.h>
|
||||
#endif
|
||||
#ifdef __SSE4_1__
|
||||
#include <smmintrin.h>
|
||||
#endif
|
||||
|
||||
|
||||
/****/
|
||||
|
||||
|
||||
#ifdef __SSE4_1__
|
||||
#define MD_CONFIG_SSE4_1_SUPPORT
|
||||
#else
|
||||
#warning "SSE4.1 wasn't enabled to compile this file."
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
|
||||
#define RF_ALIGN16 __attribute__((aligned(16)))
|
||||
#elif defined(_MSC_VER)
|
||||
#define RF_ALIGN16 __declspec(align(16))
|
||||
#else
|
||||
#define RF_ALIGN16
|
||||
#warning "SSE Disabled: Unsupported Compiler."
|
||||
#ifdef MD_CONFIG_SSE4_1_SUPPORT
|
||||
#undef MD_CONFIG_SSE4_1_SUPPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define MD_CONFIG_SSE_APPROX
|
||||
|
||||
|
||||
|
||||
#ifdef MD_CONFIG_SSE4_1_SUPPORT
|
||||
|
||||
|
||||
int mdPathSSE4p1 = 0x1 | 0x2;
|
||||
|
||||
|
||||
#define MD_COMPACTNESS_NORMALIZATION_FACTOR (0.5*4.0*1.732050808)
|
||||
|
||||
float mdEdgeCollapsePenaltyTriangleSSE4p1f( float *newpoint, float *oldpoint, float *leftpoint, float *rightpoint, int *denyflag, float compactnesstarget )
|
||||
{
|
||||
float penalty, compactness, oldcompactness, newcompactness;
|
||||
static float zero = 0.0;
|
||||
__m128 left, vecta, oldvectb, oldvectc, newvectb, newvectc, oldnormal, newnormal;
|
||||
|
||||
/* Normal of old triangle */
|
||||
left = _mm_load_ps( leftpoint );
|
||||
vecta = _mm_sub_ps( _mm_load_ps( rightpoint ), left );
|
||||
oldvectb = _mm_sub_ps( _mm_load_ps( oldpoint ), left );
|
||||
oldnormal = _mm_sub_ps(
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta, vecta, _MM_SHUFFLE(3,0,2,1) ), _mm_shuffle_ps( oldvectb, oldvectb, _MM_SHUFFLE(3,1,0,2) ) ),
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta, vecta, _MM_SHUFFLE(3,1,0,2) ), _mm_shuffle_ps( oldvectb, oldvectb, _MM_SHUFFLE(3,0,2,1) ) )
|
||||
);
|
||||
|
||||
/* Normal of new triangle */
|
||||
newvectb = _mm_sub_ps( _mm_load_ps( newpoint ), left );
|
||||
newnormal = _mm_sub_ps(
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta, vecta, _MM_SHUFFLE(3,0,2,1) ), _mm_shuffle_ps( newvectb, newvectb, _MM_SHUFFLE(3,1,0,2) ) ),
|
||||
_mm_mul_ps( _mm_shuffle_ps( vecta, vecta, _MM_SHUFFLE(3,1,0,2) ), _mm_shuffle_ps( newvectb, newvectb, _MM_SHUFFLE(3,0,2,1) ) )
|
||||
);
|
||||
|
||||
/* Detect normal inversion */
|
||||
if( _mm_comilt_ss( _mm_dp_ps( oldnormal, newnormal, 0x1 | 0x70 ), _mm_load_ss( &zero ) ) )
|
||||
{
|
||||
*denyflag = 1;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* Penalize long thin triangles */
|
||||
penalty = 0.0;
|
||||
vecta = _mm_dp_ps( vecta, vecta, 0x1 | 0x70 );
|
||||
newvectc = _mm_sub_ps( _mm_load_ps( newpoint ), _mm_load_ps( rightpoint ) );
|
||||
newnormal = _mm_dp_ps( newnormal, newnormal, 0x1 | 0x70 );
|
||||
newvectb = _mm_dp_ps( newvectb, newvectb, 0x1 | 0x70 );
|
||||
newvectc = _mm_dp_ps( newvectc, newvectc, 0x1 | 0x70 );
|
||||
#ifdef MD_CONFIG_SSE_APPROX
|
||||
newcompactness = _mm_cvtss_f32( _mm_mul_ss( _mm_set_ss( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_rcp_ss( _mm_mul_ss( _mm_rsqrt_ss( newnormal ), _mm_add_ss( _mm_add_ss( vecta, newvectb ), newvectc ) ) ) ) );
|
||||
#else
|
||||
newcompactness = _mm_cvtss_f32( _mm_div_ss( _mm_mul_ss( _mm_set_ss( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_sqrt_ss( newnormal ) ), _mm_add_ss( _mm_add_ss( vecta, newvectb ), newvectc ) ) );
|
||||
#endif
|
||||
if( newcompactness < compactnesstarget )
|
||||
{
|
||||
oldvectc = _mm_sub_ps( _mm_load_ps( oldpoint ), _mm_load_ps( rightpoint ) );
|
||||
oldnormal = _mm_dp_ps( oldnormal, oldnormal, 0x1 | 0x70 );
|
||||
oldvectb = _mm_dp_ps( oldvectb, oldvectb, 0x1 | 0x70 );
|
||||
oldvectc = _mm_dp_ps( oldvectc, oldvectc, 0x1 | 0x70 );
|
||||
#ifdef MD_CONFIG_SSE_APPROX
|
||||
oldcompactness = _mm_cvtss_f32( _mm_mul_ss( _mm_set_ss( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_rcp_ss( _mm_mul_ss( _mm_rsqrt_ss( oldnormal ), _mm_add_ss( _mm_add_ss( vecta, oldvectb ), oldvectc ) ) ) ) );
|
||||
#else
|
||||
oldcompactness = _mm_cvtss_f32( _mm_div_ss( _mm_mul_ss( _mm_set_ss( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_sqrt_ss( oldnormal ) ), _mm_add_ss( _mm_add_ss( vecta, oldvectb ), oldvectc ) ) );
|
||||
#endif
|
||||
compactness = fmin( compactnesstarget, oldcompactness ) - newcompactness;
|
||||
if( compactness > 0.0 )
|
||||
penalty = compactness;
|
||||
}
|
||||
|
||||
return penalty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double mdEdgeCollapsePenaltyTriangleSSE4p1d( double *newpoint, double *oldpoint, double *leftpoint, double *rightpoint, int *denyflag, double compactnesstarget )
|
||||
{
|
||||
__m128d vecta0, vecta1, oldvectb0, oldvectb1, oldvectc0, oldvectc1, newvectb0, newvectb1, newvectc0, newvectc1;
|
||||
__m128d oldnormal0, oldnormal1, newnormal0, newnormal1;
|
||||
__m128d dotprsum;
|
||||
__m128d left0, left1;
|
||||
double newcompactness, oldcompactness, compactness, penalty, norm;
|
||||
static double zero = 0.0;
|
||||
|
||||
/* Normal of old triangle */
|
||||
left0 = _mm_load_pd( leftpoint+0 );
|
||||
left1 = _mm_load_sd( leftpoint+2 );
|
||||
vecta0 = _mm_sub_pd( _mm_load_pd( rightpoint+0 ), left0 );
|
||||
vecta1 = _mm_sub_pd( _mm_load_pd( rightpoint+2 ), left1 );
|
||||
oldvectb0 = _mm_sub_pd( _mm_load_pd( oldpoint+0 ), left0 );
|
||||
oldvectb1 = _mm_sub_pd( _mm_load_pd( oldpoint+2 ), left1 );
|
||||
oldnormal0 = _mm_sub_pd(
|
||||
_mm_mul_pd( _mm_shuffle_pd( vecta0, vecta1, _MM_SHUFFLE2(0,1) ), _mm_unpacklo_pd( oldvectb1, oldvectb0 ) ),
|
||||
_mm_mul_pd( _mm_unpacklo_pd( vecta1, vecta0 ), _mm_shuffle_pd( oldvectb0, oldvectb1, _MM_SHUFFLE2(0,1) ) )
|
||||
);
|
||||
oldnormal1 = _mm_sub_sd(
|
||||
_mm_mul_sd( vecta0, _mm_unpackhi_pd( oldvectb0, oldvectb0 ) ),
|
||||
_mm_mul_sd( _mm_unpackhi_pd( vecta0, vecta0 ), oldvectb0 )
|
||||
);
|
||||
|
||||
/* Normal of new triangle */
|
||||
newvectb0 = _mm_sub_pd( _mm_load_pd( newpoint+0 ), left0 );
|
||||
newvectb1 = _mm_sub_pd( _mm_load_pd( newpoint+2 ), left1 );
|
||||
newnormal0 = _mm_sub_pd(
|
||||
_mm_mul_pd( _mm_shuffle_pd( vecta0, vecta1, _MM_SHUFFLE2(0,1) ), _mm_unpacklo_pd( newvectb1, newvectb0 ) ),
|
||||
_mm_mul_pd( _mm_unpacklo_pd( vecta1, vecta0 ), _mm_shuffle_pd( newvectb0, newvectb1, _MM_SHUFFLE2(0,1) ) )
|
||||
);
|
||||
newnormal1 = _mm_sub_sd(
|
||||
_mm_mul_sd( vecta0, _mm_unpackhi_pd( newvectb0, newvectb0 ) ),
|
||||
_mm_mul_sd( _mm_unpackhi_pd( vecta0, vecta0 ), newvectb0 )
|
||||
);
|
||||
|
||||
/* Detect normal inversion */
|
||||
dotprsum = _mm_add_sd( _mm_dp_pd( oldnormal0, oldnormal0, 0x1 | 0x30 ), _mm_mul_sd( oldnormal1, newnormal1 ) );
|
||||
if( _mm_comilt_sd( dotprsum, _mm_load_sd( &zero ) ) )
|
||||
{
|
||||
*denyflag = 1;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/* Penalize long thin triangles */
|
||||
penalty = 0.0;
|
||||
vecta0 = _mm_add_sd( _mm_dp_pd( vecta0, vecta0, 0x1 | 0x30 ), _mm_mul_sd( vecta1, vecta1 ) );
|
||||
newvectc0 = _mm_sub_pd( _mm_load_pd( newpoint+0 ), _mm_load_pd( rightpoint+0 ) );
|
||||
newvectc1 = _mm_sub_sd( _mm_load_sd( newpoint+2 ), _mm_load_sd( rightpoint+2 ) );
|
||||
newnormal0 = _mm_add_sd( _mm_dp_pd( newnormal0, newnormal0, 0x1 | 0x30 ), _mm_mul_sd( newnormal1, newnormal1 ) );
|
||||
newvectb0 = _mm_add_sd( _mm_dp_pd( newvectb0, newvectb0, 0x1 | 0x30 ), _mm_mul_sd( newvectb1, newvectb1 ) );
|
||||
newvectc0 = _mm_add_sd( _mm_dp_pd( newvectc0, newvectc0, 0x1 | 0x30 ), _mm_mul_sd( newvectc1, newvectc1 ) );
|
||||
norm = _mm_cvtsd_f64( _mm_add_sd( vecta0, _mm_add_sd( newvectb0, newvectc0 ) ) );
|
||||
newcompactness = _mm_cvtsd_f64( _mm_mul_sd( _mm_set_sd( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_sqrt_sd( newnormal0, newnormal0 ) ) );
|
||||
if( newcompactness < ( compactnesstarget * norm ) )
|
||||
{
|
||||
newcompactness /= norm;
|
||||
oldvectc0 = _mm_sub_pd( _mm_load_pd( oldpoint+0 ), _mm_load_pd( rightpoint+0 ) );
|
||||
oldvectc1 = _mm_sub_sd( _mm_load_sd( oldpoint+2 ), _mm_load_sd( rightpoint+2 ) );
|
||||
oldnormal0 = _mm_add_sd( _mm_dp_pd( oldnormal0, oldnormal0, 0x1 | 0x30 ), _mm_mul_sd( oldnormal1, oldnormal1 ) );
|
||||
oldvectb0 = _mm_add_sd( _mm_dp_pd( oldvectb0, oldvectb0, 0x1 | 0x30 ), _mm_mul_sd( oldvectb1, oldvectb1 ) );
|
||||
oldvectc0 = _mm_add_sd( _mm_dp_pd( oldvectc0, oldvectc0, 0x1 | 0x30 ), _mm_mul_sd( oldvectc1, oldvectc1 ) );
|
||||
oldcompactness = _mm_cvtsd_f64( _mm_div_sd( _mm_mul_sd( _mm_set_sd( MD_COMPACTNESS_NORMALIZATION_FACTOR ), _mm_sqrt_sd( oldnormal0, oldnormal0 ) ), _mm_add_sd( vecta0, _mm_add_sd( oldvectb0, oldvectc0 ) ) ) );
|
||||
compactness = fmin( compactnesstarget, oldcompactness ) - newcompactness;
|
||||
if( compactness > 0.0 )
|
||||
penalty = compactness;
|
||||
}
|
||||
|
||||
return penalty;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
int mdPathSSE4p1 = 0x0;
|
||||
|
||||
float mdEdgeCollapsePenaltyTriangleSSE4p1f( float *newpoint, float *oldpoint, float *leftpoint, float *rightpoint, int *denyflag )
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double mdEdgeCollapsePenaltyTriangleSSE4p1d( double *newpoint, double *oldpoint, double *leftpoint, double *rightpoint, int *denyflag )
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/* meshoptimization.cpp
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/26/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Mesh optimization routine.
|
||||
*
|
||||
*/
|
||||
|
||||
// System headers
|
||||
#include <stdio.h>
|
||||
|
||||
// Local headers
|
||||
#include "meshoptimization.h"
|
||||
|
||||
void
|
||||
mesh_optimization (long vertexcount,
|
||||
long tricount,
|
||||
void *indices,
|
||||
int indiceswidth,
|
||||
int threadcount,
|
||||
int optimizationlevel
|
||||
#if DEBUG_MESH_OPTIMIZATION_VERBOSE
|
||||
, std::string rname
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int depth, flags, maxthreadcount;
|
||||
switch( optimizationlevel )
|
||||
{
|
||||
case 3:
|
||||
depth = 32;
|
||||
flags = 0;
|
||||
break;
|
||||
case 2:
|
||||
depth = 32;
|
||||
flags = OPTIMIZATION_FLAGS;
|
||||
break;
|
||||
case 1:
|
||||
depth = 16;
|
||||
flags = OPTIMIZATION_FLAGS;
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
return;
|
||||
}
|
||||
maxthreadcount = tricount / 16384;
|
||||
if( threadcount > maxthreadcount )
|
||||
threadcount = maxthreadcount;
|
||||
#if DEBUG_MESH_OPTIMIZATION_VERBOSE
|
||||
fprintf (stderr, "Optimizing %s...", rname.c_str());
|
||||
#endif
|
||||
moOptimizeMesh (vertexcount,
|
||||
tricount,
|
||||
indices, indiceswidth,
|
||||
3*indiceswidth, 0, 0,
|
||||
depth,
|
||||
threadcount,
|
||||
flags);
|
||||
#if DEBUG_MESH_OPTIMIZATION_VERBOSE
|
||||
fprintf (stderr, "Done.\n");
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/* meshoptimization.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/26/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Mesh optimization routine.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MESHOPTIMIZATION_H
|
||||
#define MESHOPTIMIZATION_H
|
||||
|
||||
// Standard headers
|
||||
#include <string>
|
||||
|
||||
// Local headers
|
||||
#include "meshoptimizer.h"
|
||||
|
||||
#define OPTIMIZATION_FLAGS MO_FLAGS_DISABLE_LOOK_AHEAD | \
|
||||
MO_FLAGS_ENABLE_LAZY_SEARCH | \
|
||||
MO_FLAGS_FAST_SEED_SELECT
|
||||
#define DEBUG_MESH_OPTIMIZATION_VERBOSE 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void
|
||||
mesh_optimization (long vertexcount,
|
||||
long tricount,
|
||||
void *indices,
|
||||
int indiceswidth,
|
||||
int threadcount,
|
||||
int optimizationlevel
|
||||
#if DEBUG_MESH_OPTIMIZATION_VERBOSE
|
||||
, std::string rname
|
||||
#endif
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
/* *****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2014 Alexis Naveros. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* *****************************************************************************
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
int moOptimizeMesh( size_t vertexcount, size_t tricount, void *indices, int indiceswidth, size_t indicesstride, void (*shufflecallback)( void *opaquepointer, long newvertexindex, long oldvertexindex ), void *shuffleopaquepointer, int vertexcachesize, int threadcount, int flags );
|
||||
|
||||
#define MO_FLAGS_FIXED_CACHE_SIZE (0x1)
|
||||
#define MO_FLAGS_DISABLE_LOOK_AHEAD (0x2)
|
||||
#define MO_FLAGS_ENABLE_LAZY_SEARCH (0x4)
|
||||
#define MO_FLAGS_FAST_SEED_SELECT (0x8)
|
||||
|
||||
|
||||
double moEvaluateMesh( size_t tricount, void *indices, int indiceswidth, size_t indicesstride, int vertexcachesize, int flags );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
set(GCT_SAMPLER_SRCS
|
||||
PointSampler.cpp
|
||||
MarchingCubesSampler.cpp
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../openNURBS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../tcl/generic
|
||||
)
|
||||
|
||||
add_library(Sampler SHARED ${GCT_SAMPLER_SRCS})
|
||||
set_target_properties(Sampler PROPERTIES VERSION 1.1.0 SOVERSION 1)
|
||||
|
||||
install(TARGETS Sampler
|
||||
RUNTIME DESTINATION ${BIN_DIR}
|
||||
LIBRARY DESTINATION ${LIB_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_DIR})
|
||||
|
||||
if(MSVC)
|
||||
set_property(TARGET Sampler APPEND PROPERTY COMPILE_DEFINITIONS "SAMPLER_DLL_EXPORTS")
|
||||
endif(MSVC)
|
||||
|
||||
# Local Variables:
|
||||
# tab-width: 8
|
||||
# mode: cmake
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
# ex: shiftwidth=2 tabstop=8
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,204 @@
|
||||
/* MarchingCubesSampler.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/22/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Implements a marching cubes technique to create a faceted representation
|
||||
* of a piece of geometry.
|
||||
*/
|
||||
|
||||
#ifndef MARCHINGCUBESSAMPLER_H
|
||||
#define MARCHINGCUBESSAMPLER_H
|
||||
|
||||
// System headers
|
||||
#include <vector>
|
||||
|
||||
// Local headers
|
||||
#include "Interface/ISampler.h"
|
||||
|
||||
namespace GeomConversion {
|
||||
|
||||
namespace Sampler {
|
||||
|
||||
// Structures
|
||||
struct edge_int
|
||||
{
|
||||
float pt[3];
|
||||
float norm[3];
|
||||
int set;
|
||||
};
|
||||
|
||||
struct cube_def
|
||||
{
|
||||
int ll[2], lr[2], ul[2], ur[2];
|
||||
double ymin, ymax;
|
||||
|
||||
/* output lists */
|
||||
std::vector<float> points;
|
||||
std::vector<float> normals;
|
||||
};
|
||||
|
||||
struct mc_thread_data
|
||||
{
|
||||
double cellsize;
|
||||
|
||||
/* intermediate data */
|
||||
Interface::trace_data **rayGrid;
|
||||
int rowCount, colCount, rayCount;
|
||||
int currRow, currCol, doneRays;
|
||||
#if USE_QT
|
||||
QMutex threadMutex;
|
||||
#else
|
||||
pthread_mutex_t threadMutex;
|
||||
#endif
|
||||
|
||||
std::vector<struct cube_def> cubes;
|
||||
int currCube;
|
||||
};
|
||||
|
||||
//*******************************************************************
|
||||
// NAME MarchingCubesWorker
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Holds data used/created on a per thread basis.
|
||||
//
|
||||
// NOTE
|
||||
// Glorified structure declared as a class for Qt threading model.
|
||||
//*******************************************************************
|
||||
class MarchingCubesWorker
|
||||
#if USE_QT
|
||||
: public QObject
|
||||
#endif
|
||||
{
|
||||
#if USE_QT
|
||||
Q_OBJECT
|
||||
#endif
|
||||
|
||||
public:
|
||||
MarchingCubesWorker(struct mc_thread_data *td
|
||||
#if USE_QT
|
||||
, QObject *parent = NULL) : QObject(parent) ,
|
||||
#else
|
||||
) :
|
||||
#endif
|
||||
m_threadData(td)
|
||||
{
|
||||
#if USE_QT
|
||||
m_keepGoing = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* thread data */
|
||||
unsigned long m_ID;
|
||||
struct mc_thread_data *m_threadData;
|
||||
|
||||
/* input data */
|
||||
Interface::IGeometryTracer *tracer;
|
||||
|
||||
void incrementStep()
|
||||
{
|
||||
#if USE_QT
|
||||
emit doneStep();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USE_QT
|
||||
bool m_keepGoing;
|
||||
void pleaseStop() { m_keepGoing = false; }
|
||||
|
||||
signals:
|
||||
void doneStep();
|
||||
void finished();
|
||||
|
||||
public slots:
|
||||
void run();
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* MarchingCubesSampler
|
||||
*
|
||||
* Implements a marching cubes technique to create a faceted representation
|
||||
* of a piece of geometry.
|
||||
*/
|
||||
class MarchingCubesSampler : public Interface::ISampler
|
||||
{
|
||||
#if USE_QT
|
||||
Q_OBJECT
|
||||
#endif
|
||||
|
||||
public:
|
||||
MarchingCubesSampler(SAMPLER_CONST_DEF);
|
||||
~MarchingCubesSampler();
|
||||
|
||||
virtual void setSpacing(float s) { m_threadData.cellsize = s; }
|
||||
virtual void prepSample();
|
||||
virtual void endSample();
|
||||
|
||||
std::vector<float> getVertices() { return m_vertex; }
|
||||
std::vector<float> getNormals() { return m_normal; }
|
||||
std::vector<int> getIndices() { return m_index; }
|
||||
|
||||
#if USE_QT
|
||||
virtual void stopSampling();
|
||||
virtual float getProgress();
|
||||
virtual QString getStatusString() { return m_statusStr; }
|
||||
|
||||
public slots:
|
||||
void incrementStep() { m_doneSteps++; updateProgress(); }
|
||||
virtual void workerFinished();
|
||||
#endif
|
||||
virtual void runSample();
|
||||
|
||||
private:
|
||||
/* threading data */
|
||||
std::vector<MarchingCubesWorker *> m_workers;
|
||||
struct mc_thread_data m_threadData;
|
||||
|
||||
/* output storage */
|
||||
std::vector<float> m_vertex;
|
||||
std::vector<float> m_normal;
|
||||
std::vector<int> m_index;
|
||||
|
||||
#if USE_QT
|
||||
long m_doneSteps;
|
||||
long m_totalSteps;
|
||||
QString m_statusStr;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace Sampler
|
||||
|
||||
} // namespace GeomConversion
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,692 @@
|
||||
/* PointSampler.cpp
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/21/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
* LB
|
||||
*
|
||||
* Description:
|
||||
* Implements a point sample technique to get (x, y, z) locations on
|
||||
* a piece of geometry.
|
||||
*/
|
||||
|
||||
// System headers
|
||||
#include <math.h>
|
||||
|
||||
// Local headers
|
||||
#include "PointSampler.h"
|
||||
#include "Auxiliary/gctcommon.h"
|
||||
|
||||
namespace GeomConversion {
|
||||
|
||||
namespace Sampler {
|
||||
|
||||
#if USE_QT
|
||||
#define PS_CHECK_CANCEL() (! twd->m_keepGoing)
|
||||
#else
|
||||
#define PS_CHECK_CANCEL() (0)
|
||||
#endif
|
||||
|
||||
//*******************************************************************
|
||||
// NAME ray_results_differ
|
||||
//
|
||||
// INPUTS
|
||||
// previousRayResults, currentRayResults - the ray results for the rays
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Check to see if the results of two rays are different.
|
||||
// true = different.
|
||||
//*******************************************************************
|
||||
bool
|
||||
ray_results_differ(const Interface::ray_results &previousRayResults,
|
||||
const Interface::ray_results ¤tRayResults)
|
||||
{
|
||||
// If the list sizes differ that is a dead give-away
|
||||
if (previousRayResults.hitData.size() != currentRayResults.hitData.size())
|
||||
return true;
|
||||
|
||||
for (unsigned i=0 ; i < previousRayResults.hitData.size() ; i++)
|
||||
{
|
||||
const Interface::one_hit &prevHit = previousRayResults.hitData[i];
|
||||
const Interface::one_hit &currHit = currentRayResults.hitData[i];
|
||||
|
||||
// compare things in relative order of difficulty of the comparison
|
||||
|
||||
if (prevHit.solidSurface != currHit.solidSurface )
|
||||
return true;
|
||||
|
||||
if (prevHit.solidName.compare(currHit.solidName))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME sub_sample
|
||||
//
|
||||
// INPUTS
|
||||
// thisThreadResults - all the ray results for the current thread
|
||||
// twd - pointer to the current thread's thread_worker_data
|
||||
// prevResults - results from the previously shot ray
|
||||
// currResults - results from the current ray
|
||||
// depth, limit - variables to control depth of recursion
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Function performs sub sampling to determine if/where an edge occurs
|
||||
// between 2 rays.
|
||||
//*******************************************************************
|
||||
void
|
||||
sub_sample (std::vector<Interface::ray_results> &thisThreadResults,
|
||||
const PointSamplerWorker *twd,
|
||||
const Interface::ray_results &prevResults,
|
||||
const Interface::ray_results &currResults,
|
||||
const int depth, const int limit)
|
||||
{
|
||||
if (depth >= limit)
|
||||
return;
|
||||
|
||||
Interface::trace_data middle_ray;
|
||||
TRACE_DATA_INIT(middle_ray);
|
||||
|
||||
VADD2(middle_ray.point, currResults.origin, prevResults.origin);
|
||||
VSCALE(middle_ray.point, middle_ray.point, 0.5);
|
||||
VMOVE(middle_ray.direc, currResults.dir);
|
||||
middle_ray.results.x = -1; // note that this is a sub-sampling ray
|
||||
middle_ray.results.y = -1;
|
||||
VMOVE(middle_ray.results.origin, middle_ray.point);
|
||||
VMOVE(middle_ray.results.dir, middle_ray.direc);
|
||||
|
||||
twd->tracer->fireRay(&middle_ray);
|
||||
|
||||
bool diffLeft = ray_results_differ(prevResults, middle_ray.results);
|
||||
bool diffRight = ray_results_differ(middle_ray.results, currResults);
|
||||
unsigned remember = thisThreadResults.size();
|
||||
|
||||
if (diffLeft && diffRight)
|
||||
{
|
||||
sub_sample(thisThreadResults, twd,
|
||||
prevResults, middle_ray.results,
|
||||
depth+1, limit);
|
||||
sub_sample(thisThreadResults, twd,
|
||||
middle_ray.results, currResults,
|
||||
depth+1, limit);
|
||||
thisThreadResults.push_back(middle_ray.results);
|
||||
}
|
||||
else if (diffLeft)
|
||||
{
|
||||
sub_sample(thisThreadResults, twd,
|
||||
prevResults, middle_ray.results,
|
||||
depth+1, limit);
|
||||
for (unsigned pos=remember; pos < thisThreadResults.size(); pos++)
|
||||
{
|
||||
Interface::ray_results &newerResults = thisThreadResults[pos];
|
||||
if (!ray_results_differ(newerResults, currResults))
|
||||
{
|
||||
// somethig to my left also matches right so I am not needed
|
||||
goto rightFound;
|
||||
}
|
||||
}
|
||||
thisThreadResults.push_back(middle_ray.results);
|
||||
|
||||
rightFound:
|
||||
;
|
||||
}
|
||||
else if (diffRight)
|
||||
{
|
||||
sub_sample(thisThreadResults, twd,
|
||||
middle_ray.results, currResults,
|
||||
depth+1, limit);
|
||||
for (unsigned pos=remember ; pos < thisThreadResults.size() ; pos++)
|
||||
{
|
||||
Interface::ray_results &newerResults = thisThreadResults[pos];
|
||||
if (!ray_results_differ(newerResults, prevResults))
|
||||
{
|
||||
// somethig to my right also matches left so I am not needed
|
||||
goto leftFound;
|
||||
}
|
||||
}
|
||||
thisThreadResults.push_back(middle_ray.results);
|
||||
leftFound:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME check_subsample
|
||||
//
|
||||
// INPUTS
|
||||
// twd - pointer to the current thread's thread_worker_data
|
||||
// j - ???
|
||||
// currResults - results from the current ray
|
||||
// prevResults - results from the previously shot ray
|
||||
// thisThreadResults - all the ray results for the current thread
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Check whether there is any sub-sampling needed and perform it if so.
|
||||
//*******************************************************************
|
||||
void
|
||||
check_subsample(const PointSamplerWorker *twd,
|
||||
const int j,
|
||||
const Interface::ray_results &currResults,
|
||||
const Interface::ray_results &prevResults,
|
||||
std::vector<Interface::ray_results> &thisThreadResults)
|
||||
{
|
||||
Interface::ray_results lowerRowRayResults, diagonalRayResults;
|
||||
|
||||
RAY_RESULTS_INIT(lowerRowRayResults);
|
||||
RAY_RESULTS_INIT(diagonalRayResults);
|
||||
|
||||
// look to see if we crossed a physical boundary
|
||||
// along the i_axis and should sub-sample
|
||||
if (ray_results_differ(prevResults, currResults))
|
||||
{
|
||||
sub_sample(thisThreadResults, twd,
|
||||
prevResults, currResults,
|
||||
0, twd->model->sub_division);
|
||||
}
|
||||
|
||||
// look to see if we crossed a physical boundary
|
||||
// along the j_axis and should sub-sample
|
||||
if (j == 0)
|
||||
return;
|
||||
|
||||
// look backwards for matching x,y-1 entry
|
||||
for (int prevIdx=thisThreadResults.size()-1; prevIdx >= 0; prevIdx--)
|
||||
{
|
||||
if (thisThreadResults.at(prevIdx).x == currResults.x &&
|
||||
thisThreadResults.at(prevIdx).y ==(currResults.y-1))
|
||||
{
|
||||
// found it
|
||||
RAY_RESULTS_COPY(lowerRowRayResults, thisThreadResults[prevIdx]);
|
||||
if (ray_results_differ(lowerRowRayResults, currResults))
|
||||
{
|
||||
sub_sample(thisThreadResults, twd,
|
||||
lowerRowRayResults, currResults,
|
||||
0, twd->model->sub_division);
|
||||
}
|
||||
|
||||
// sample diagonally across the "cell"
|
||||
if (ray_results_differ(prevResults, lowerRowRayResults))
|
||||
{
|
||||
sub_sample(thisThreadResults, twd,
|
||||
prevResults, lowerRowRayResults,
|
||||
0, twd->model->sub_division);
|
||||
}
|
||||
|
||||
// now go looking back for the x-1,y-1 entry
|
||||
// so we can sample along the other diagonal
|
||||
for (int diagIdx=thisThreadResults.size()-1; diagIdx >= 0;
|
||||
diagIdx--)
|
||||
{
|
||||
if (thisThreadResults.at(diagIdx).x ==(currResults.x-1) &&
|
||||
thisThreadResults.at(diagIdx).y ==(currResults.y-1))
|
||||
{
|
||||
// found it
|
||||
RAY_RESULTS_COPY(diagonalRayResults,
|
||||
thisThreadResults[diagIdx]);
|
||||
if (ray_results_differ(diagonalRayResults, currResults))
|
||||
{
|
||||
sub_sample(thisThreadResults, twd,
|
||||
diagonalRayResults, currResults,
|
||||
0, twd->model->sub_division);
|
||||
}
|
||||
|
||||
break;
|
||||
} // found x-1, y-1
|
||||
}
|
||||
break;
|
||||
} // found x, y-1
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME pointsample_worker
|
||||
//
|
||||
// INPUTS
|
||||
// td - pointer to PointSamplerWorker
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Function called to perform work for each thread.
|
||||
//*******************************************************************
|
||||
void *
|
||||
pointsample_worker (void *td)
|
||||
{
|
||||
PointSamplerWorker *twd = (PointSamplerWorker *) td;
|
||||
Interface::trace_data prevRay, currentRay;
|
||||
std::vector<Interface::ray_results> thisViewResults; // the results for the current view
|
||||
std::vector<Interface::ray_results> thisThreadResults; // the total results for this thread
|
||||
|
||||
// make sure everythign is clear
|
||||
thisThreadResults.clear();
|
||||
TRACE_DATA_INIT(prevRay);
|
||||
|
||||
/* We shoot rays in the shootAxis direction,
|
||||
* we step from bounding box min..max along the i_axis.
|
||||
* we step from slabStartLineNumber..slabEndLineNumber along j_axis
|
||||
*
|
||||
* Conceptually, the bounding box of the object is divided into slabs
|
||||
* along the j_axis. Each thread of computation handles one
|
||||
* slab. Within a slab, the thread shoots rays along the individal
|
||||
* lines (rows) stepping from mdl_min[i_axis]..mdl_max[i_axis].
|
||||
*/
|
||||
for (int shootAxis = 0; shootAxis < 3; shootAxis++)
|
||||
{
|
||||
if (PS_CHECK_CANCEL()) goto endWorker;
|
||||
|
||||
// make sure everything is clear
|
||||
thisViewResults.clear();
|
||||
TRACE_DATA_INIT(currentRay);
|
||||
|
||||
/* set direction vector */
|
||||
int i_axis = (shootAxis + 1) % 3; // the axis we step between rays
|
||||
int j_axis = (shootAxis + 2) % 3; // the slab axis
|
||||
|
||||
currentRay.point[shootAxis] = twd->model->model_min[shootAxis];
|
||||
currentRay.direc[shootAxis] = 1.0;
|
||||
currentRay.direc[i_axis] = 0.0;
|
||||
currentRay.direc[j_axis] = 0.0;
|
||||
|
||||
// compute the dimensions of the slab along the j_axis dimension
|
||||
float slabBottom = twd->cpuID * twd->model->perCpuSlabWidth[j_axis];
|
||||
float slabTop = (twd->cpuID+1) * twd->model->perCpuSlabWidth[j_axis];
|
||||
|
||||
int slabStartLineNumber = ceil(slabBottom / twd->model->spacing);
|
||||
int slabEndLineNumber = ceil(slabTop / twd->model->spacing);
|
||||
|
||||
for (long j=slabStartLineNumber ; j <= slabEndLineNumber ; j++)
|
||||
{
|
||||
if (PS_CHECK_CANCEL()) goto endWorker;
|
||||
currentRay.point[j_axis] = twd->model->model_min[j_axis] + (j * twd->model->spacing);
|
||||
|
||||
prevRay.results.hitData.clear();
|
||||
prevRay.results.x = -1;
|
||||
prevRay.results.y = -1;
|
||||
|
||||
long iAxisSteps = ceil(twd->model->model_span[i_axis] / twd->model->spacing);
|
||||
|
||||
for (long i=0 ; i <= iAxisSteps ; i++)
|
||||
{
|
||||
if (PS_CHECK_CANCEL()) goto endWorker;
|
||||
currentRay.point[i_axis] = twd->model->model_min[i_axis] + (i * twd->model->spacing);
|
||||
|
||||
currentRay.results.x = i;
|
||||
currentRay.results.y = j;
|
||||
VMOVE(currentRay.results.origin, currentRay.point);
|
||||
VMOVE(currentRay.results.dir, currentRay.direc);
|
||||
currentRay.results.hitData.clear();
|
||||
|
||||
// fire the ray
|
||||
twd->tracer->fireRay(¤tRay);
|
||||
|
||||
if (j < slabEndLineNumber || (twd->cpuID+1) == twd->model->total_threads)
|
||||
{
|
||||
// record results
|
||||
thisViewResults.push_back(currentRay.results);
|
||||
}
|
||||
|
||||
if (twd->model->do_subsample && twd->model->sub_division > 0)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
check_subsample(twd, j, currentRay.results,
|
||||
prevRay.results, thisViewResults);
|
||||
}
|
||||
}
|
||||
|
||||
twd->completedRays++;
|
||||
TRACE_DATA_COPY(prevRay, currentRay);
|
||||
}
|
||||
}
|
||||
|
||||
// copy the view results to the overall results
|
||||
thisThreadResults.insert(thisThreadResults.end(),
|
||||
thisViewResults.begin(),
|
||||
thisViewResults.end());
|
||||
}
|
||||
|
||||
thisViewResults.clear(); // not needed anymore
|
||||
|
||||
if (PS_CHECK_CANCEL()) goto endWorker;
|
||||
|
||||
// move all points to proper lists
|
||||
for (unsigned i = 0; i < thisThreadResults.size(); i++)
|
||||
{
|
||||
std::vector<float> *points = &(twd->points);
|
||||
std::vector<float> *normals = &(twd->normals);
|
||||
std::vector<std::string> *solNumber = &(twd->solidNumber);
|
||||
std::vector<long> *surfNumber = &(twd->surfNumber);
|
||||
|
||||
for (unsigned j = 0; j < thisThreadResults[i].hitData.size(); j++)
|
||||
{
|
||||
Interface::one_hit &hit = thisThreadResults[i].hitData[j];
|
||||
|
||||
/* save points and normals */
|
||||
for (int a=0; a<3; a++)
|
||||
{
|
||||
points->push_back(hit.point[a]);
|
||||
normals->push_back(hit.normal[a]);
|
||||
}
|
||||
|
||||
/* save surface numbers and solid numbers */
|
||||
solNumber->push_back(hit.solidName);
|
||||
surfNumber->push_back(hit.solidSurface);
|
||||
}
|
||||
}
|
||||
|
||||
endWorker:
|
||||
thisThreadResults.clear();
|
||||
|
||||
//fprintf (stderr, "Ending CPU %d\n", twd->cpuID);
|
||||
SAMPLER_THREAD_EXIT();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if USE_QT
|
||||
//*******************************************************************
|
||||
// NAME run
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Start the worker.
|
||||
//*******************************************************************
|
||||
void PointSamplerWorker::run()
|
||||
{
|
||||
pointsample_worker((void *) this);
|
||||
emit finished();
|
||||
}
|
||||
#endif
|
||||
|
||||
//*******************************************************************
|
||||
// NAME constructor
|
||||
//
|
||||
// INPUTS
|
||||
// ti - pointer to a target
|
||||
// tracers - list of tracer objects
|
||||
// threads - list of already instantiated QThreads (Qt only)
|
||||
// parent - parent QObject (Qt only, should be NULL)
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Construct the object.
|
||||
//*******************************************************************
|
||||
PointSampler::PointSampler(SAMPLER_CONST_IMP)
|
||||
: Interface::ISampler(SAMPLER_CONST_PARAMS)
|
||||
, m_spacing(1.0)
|
||||
, m_subdivision(4)
|
||||
{
|
||||
m_points.clear();
|
||||
m_normals.clear();
|
||||
m_surfNumber.clear();
|
||||
m_solidNumber.clear();
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME destructor
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Cleanup the object.
|
||||
//*******************************************************************
|
||||
PointSampler::~PointSampler()
|
||||
{
|
||||
m_points.clear();
|
||||
m_normals.clear();
|
||||
m_surfNumber.clear();
|
||||
m_solidNumber.clear();
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME prepSample
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Preps data used across the entire model.
|
||||
//*******************************************************************
|
||||
void PointSampler::prepSample()
|
||||
{
|
||||
memset (&m_model, 0, sizeof (struct thread_model_data));
|
||||
|
||||
// load geometry and determine overall model data
|
||||
VMOVE(m_model.model_min, m_geometry->getGeometryMin());
|
||||
VMOVE(m_model.model_max, m_geometry->getGeometryMax());
|
||||
VSUB2(m_model.model_span, m_model.model_max, m_model.model_min);
|
||||
m_model.total_threads = m_threadCount;
|
||||
m_model.sub_division = m_subdivision;
|
||||
m_model.do_subsample = true; // always set to true
|
||||
m_model.spacing = m_spacing;
|
||||
|
||||
for (int currentAxis = 0; currentAxis < 3; currentAxis++)
|
||||
{
|
||||
m_model.perCpuSlabWidth[currentAxis] = m_model.model_span[currentAxis] / m_threadCount;
|
||||
m_model.ray_total += m_model.model_span[currentAxis] / m_spacing;
|
||||
}
|
||||
|
||||
for (int i=0; i<m_threadCount; i++)
|
||||
{
|
||||
PointSamplerWorker *worker = new PointSamplerWorker();
|
||||
|
||||
// assign tracer object
|
||||
worker->tracer = m_tracers[i];
|
||||
|
||||
// set pointer to model data
|
||||
worker->model = &m_model;
|
||||
|
||||
// set completed rays
|
||||
worker->completedRays = 0;
|
||||
|
||||
// set cpu ID
|
||||
worker->cpuID = i;
|
||||
|
||||
// make sure output vectors are empty
|
||||
worker->points.clear();
|
||||
worker->normals.clear();
|
||||
worker->surfNumber.clear();
|
||||
worker->solidNumber.clear();
|
||||
|
||||
m_workers.push_back(worker);
|
||||
|
||||
#if USE_QT
|
||||
// move the worker to it's thread
|
||||
worker->moveToThread(m_threads.at(i));
|
||||
|
||||
// connect signals
|
||||
connect(worker, SIGNAL(finished()),
|
||||
this, SLOT(workerFinished()),
|
||||
Qt::QueuedConnection);
|
||||
connect(this, SIGNAL(startWorkers()),
|
||||
worker, SLOT(run()),
|
||||
Qt::QueuedConnection);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_threadsDone = 0;
|
||||
m_prepped = true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME runSample
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Does the work to perform the point sampling, including subdividing
|
||||
// the work amongst a desired number of threads.
|
||||
//*******************************************************************
|
||||
void PointSampler::runSample()
|
||||
{
|
||||
if (m_prepped)
|
||||
{
|
||||
#if USE_QT
|
||||
emit startWorkers();
|
||||
#else
|
||||
// set up threading data
|
||||
pthread_attr_t attr;
|
||||
pthread_t *ptid = NULL;
|
||||
|
||||
pthread_attr_init (&attr);
|
||||
ptid = (pthread_t *) malloc (sizeof (pthread_t) * m_threadCount);
|
||||
memset (ptid, 0, sizeof (pthread_t) * m_threadCount);
|
||||
|
||||
/* start threading */
|
||||
for (int i=0; i<m_threadCount; i++)
|
||||
pthread_create (&ptid[i], &attr, pointsample_worker, (void*) (m_workers.at(i)));
|
||||
|
||||
/* thread join */
|
||||
for (int i=0; i<m_threadCount; i++)
|
||||
pthread_join(ptid[i], NULL);
|
||||
|
||||
/* get output data */
|
||||
endSample();
|
||||
|
||||
if (ptid) free (ptid);
|
||||
pthread_attr_destroy (&attr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME endSample
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Move all the worker data to the main lists.
|
||||
//*******************************************************************
|
||||
void PointSampler::endSample()
|
||||
{
|
||||
/* get output data */
|
||||
for (int i=0; i<m_threadCount; i++)
|
||||
{
|
||||
// if (i != 1) continue;
|
||||
|
||||
PointSamplerWorker *worker = m_workers.at(i);
|
||||
|
||||
std::vector<float> *points = &(worker->points);
|
||||
std::vector<float> *normals = &(worker->normals);
|
||||
|
||||
m_points.insert(m_points.end(), points->begin(), points->end());
|
||||
m_normals.insert(m_normals.end(), normals->begin(), normals->end());
|
||||
|
||||
std::vector<std::string> *solNum = &(worker->solidNumber);
|
||||
std::vector<long> *surfNum = &(worker->surfNumber);
|
||||
|
||||
m_surfNumber.insert(m_surfNumber.end(), surfNum->begin(), surfNum->end());
|
||||
m_solidNumber.insert(m_solidNumber.end(), solNum->begin(), solNum->end());
|
||||
|
||||
/* cleanup */
|
||||
worker->tracer = NULL;
|
||||
worker->points.clear();
|
||||
worker->normals.clear();
|
||||
worker->surfNumber.clear();
|
||||
worker->solidNumber.clear();
|
||||
delete worker;
|
||||
}
|
||||
m_workers.clear();
|
||||
m_prepped = false;
|
||||
}
|
||||
|
||||
#if USE_QT
|
||||
//*******************************************************************
|
||||
// NAME workerFinished
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Returns here when a worker is done it's part. Once all are done it
|
||||
// does the finishing work.
|
||||
//*******************************************************************
|
||||
void PointSampler::workerFinished()
|
||||
{
|
||||
// wait for the threads to finish
|
||||
m_threadsDone++;
|
||||
updateProgress();
|
||||
if (m_threadsDone < m_threadCount)
|
||||
return;
|
||||
|
||||
if (!m_canceled)
|
||||
endSample();
|
||||
emit finished();
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME getProgress
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Return the overall progress of the workers
|
||||
//*******************************************************************
|
||||
float PointSampler::getProgress()
|
||||
{
|
||||
int done_rays = 0;
|
||||
float progress = 0.0;
|
||||
|
||||
for (unsigned i=0; i < m_workers.size(); i++)
|
||||
done_rays += (m_workers[i])->completedRays;
|
||||
|
||||
if (m_model.ray_total)
|
||||
progress = (float) done_rays / (float) m_model.ray_total;
|
||||
if( progress > 100.0 )
|
||||
progress = 100.0;
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// NAME stopSampling
|
||||
//
|
||||
// INPUTS
|
||||
// none
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Tell all the workers to stop
|
||||
//*******************************************************************
|
||||
void PointSampler::stopSampling()
|
||||
{
|
||||
m_canceled = true;
|
||||
for (unsigned i=0; i<m_workers.size(); i++)
|
||||
{
|
||||
PointSamplerWorker *worker = m_workers.at(i);
|
||||
worker->pleaseStop();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Sampler
|
||||
|
||||
} // namespace GeomConversion
|
||||
@@ -0,0 +1,179 @@
|
||||
/* PointSampler.h
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/21/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* Implements a point sample technique to get (x, y, z) locations on
|
||||
* a piece of geometry.
|
||||
*/
|
||||
|
||||
#ifndef POINTSAMPLER_H
|
||||
#define POINTSAMPLER_H
|
||||
|
||||
// System headers
|
||||
#include <vector>
|
||||
|
||||
// Local headers
|
||||
#include "Interface/ISampler.h"
|
||||
|
||||
namespace GeomConversion {
|
||||
|
||||
namespace Sampler {
|
||||
|
||||
// Structures
|
||||
|
||||
//*******************************************************************
|
||||
// NAME thread_model_data
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Holds data used across the entire geometric model.
|
||||
//*******************************************************************
|
||||
struct thread_model_data
|
||||
{
|
||||
int total_threads;
|
||||
int sub_division;
|
||||
bool do_subsample;
|
||||
double spacing;
|
||||
double model_min[3];
|
||||
double model_max[3];
|
||||
double model_span[3];
|
||||
double perCpuSlabWidth[3];
|
||||
int ray_total;
|
||||
};
|
||||
|
||||
//*******************************************************************
|
||||
// NAME PointSamplerWorker
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Holds data used/created on a per thread basis.
|
||||
//
|
||||
// NOTE
|
||||
// Glorified structure declared as a class for Qt threading model.
|
||||
//*******************************************************************
|
||||
class PointSamplerWorker
|
||||
#if USE_QT
|
||||
: public QObject
|
||||
#endif
|
||||
{
|
||||
#if USE_QT
|
||||
Q_OBJECT
|
||||
#endif
|
||||
|
||||
public:
|
||||
#if USE_QT
|
||||
PointSamplerWorker(QObject *parent = NULL) : QObject(parent) { m_keepGoing = true; }
|
||||
#endif
|
||||
|
||||
/* input data */
|
||||
Interface::IGeometryTracer *tracer;
|
||||
struct thread_model_data *model;
|
||||
int cpuID;
|
||||
|
||||
/* intermediate data */
|
||||
int completedRays;
|
||||
|
||||
/* output data */
|
||||
std::vector<float> points;
|
||||
std::vector<float> normals;
|
||||
std::vector<std::string> solidNumber;
|
||||
std::vector<long> surfNumber;
|
||||
|
||||
#if USE_QT
|
||||
bool m_keepGoing;
|
||||
|
||||
void pleaseStop() { m_keepGoing = false; }
|
||||
|
||||
signals:
|
||||
void finished();
|
||||
|
||||
public slots:
|
||||
void run();
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* PointSampler
|
||||
*
|
||||
* Implements a point sample technique to get (x, y, z) locations on
|
||||
* a piece of geometry.
|
||||
*/
|
||||
class PointSampler : public Interface::ISampler
|
||||
{
|
||||
#if USE_QT
|
||||
Q_OBJECT
|
||||
#endif
|
||||
|
||||
public:
|
||||
PointSampler(SAMPLER_CONST_DEF);
|
||||
~PointSampler();
|
||||
|
||||
void setSubdivisionDepth(int d) { m_subdivision = d; }
|
||||
|
||||
virtual void setSpacing(float s) { m_spacing = s; }
|
||||
virtual void prepSample();
|
||||
virtual void endSample();
|
||||
|
||||
std::vector<float> getPoints() { return m_points; }
|
||||
std::vector<float> getNormals() { return m_normals; }
|
||||
std::vector<std::string> getSolidNumbers() { return m_solidNumber; }
|
||||
std::vector<long> getSurfNumbers() { return m_surfNumber; }
|
||||
|
||||
#if USE_QT
|
||||
virtual void stopSampling();
|
||||
virtual float getProgress();
|
||||
|
||||
public slots:
|
||||
virtual void workerFinished();
|
||||
#endif
|
||||
virtual void runSample();
|
||||
|
||||
private:
|
||||
/* necessary inputs */
|
||||
float m_spacing;
|
||||
int m_subdivision;
|
||||
struct thread_model_data m_model;
|
||||
std::vector<PointSamplerWorker *> m_workers;
|
||||
|
||||
/* output storage */
|
||||
std::vector<float> m_points;
|
||||
std::vector<float> m_normals;
|
||||
std::vector<std::string> m_solidNumber;
|
||||
std::vector<long> m_surfNumber;
|
||||
};
|
||||
|
||||
} // namespace Sampler
|
||||
|
||||
} // namespace GeomConversion
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../openNURBS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../tcl/generic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../Auxiliary
|
||||
)
|
||||
|
||||
add_executable(bpmain main.cpp)
|
||||
target_link_libraries(bpmain librt libbu libbn AUX BallPivoting
|
||||
${M_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
@@ -0,0 +1,349 @@
|
||||
/* main.cpp
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/22/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* This is the standalone ball pivoting application.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard C/C++ libraries */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/* BRL-CAD libraries */
|
||||
/* needed to set uint32_t in ballpivoting.h */
|
||||
#include "bu.h"
|
||||
|
||||
/* Custom libraries */
|
||||
#include "gctcommon.h"
|
||||
#include "BallPivoting/ballpivoting.h"
|
||||
|
||||
/* defines */
|
||||
#define DEBUG_BALL_PIVOTING_VERBOSE 0
|
||||
|
||||
/* structures */
|
||||
typedef struct
|
||||
{
|
||||
float *vertex;
|
||||
float *normal;
|
||||
} BallPivotingPack;
|
||||
|
||||
/* globals */
|
||||
std::vector<float> gVertex;
|
||||
std::vector<float> gNormal;
|
||||
std::vector<long> gVIndex;
|
||||
std::vector<std::string> gGeom;
|
||||
std::vector<long> gOffset;
|
||||
|
||||
/*============ STATIC FUNCTIONS ============*/
|
||||
|
||||
//******************************************************************************
|
||||
// NAME ballpivoting_pack_callback
|
||||
//
|
||||
// INPUTS
|
||||
// ???
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Callback from ball pivoting code to repack vertices.
|
||||
//******************************************************************************
|
||||
static void
|
||||
ballpivoting_pack_callback( void *opaquepointer,
|
||||
long newvertexindex,
|
||||
long oldvertexindex )
|
||||
{
|
||||
BallPivotingPack *bppack;
|
||||
float *src, *dst;
|
||||
|
||||
bppack = (BallPivotingPack *)opaquepointer;
|
||||
src = &bppack->vertex[3*oldvertexindex];
|
||||
dst = &bppack->vertex[3*newvertexindex];
|
||||
memcpy( dst, src, 3*sizeof(float) );
|
||||
|
||||
src = &bppack->normal[3*oldvertexindex];
|
||||
dst = &bppack->normal[3*newvertexindex];
|
||||
memcpy( dst, src, 3*sizeof(float) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
// NAME ball_pivot
|
||||
//
|
||||
// INPUTS
|
||||
// points - list of 3D points
|
||||
// normals - list of normals for the points
|
||||
// ballrange - ball range ratio
|
||||
// spacing - cell spacing that was used to get points
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Function that actually performs the ball pivoting routines.
|
||||
//******************************************************************************
|
||||
static void
|
||||
ball_pivot(std::vector<float> &points,
|
||||
std::vector<float> &normals,
|
||||
float ballrange,
|
||||
float spacing)
|
||||
{
|
||||
int threadcount;
|
||||
int pointcount = points.size() / 3;
|
||||
float *vertex = &points[0];
|
||||
float *normal = &normals[0];
|
||||
bpOperation bp;
|
||||
bpOutput output;
|
||||
BallPivotingPack bppack;
|
||||
int *bpindices;
|
||||
int *triindices;
|
||||
long bptricount, bpvertexcount;
|
||||
|
||||
bpOperationInit( &bp );
|
||||
bpOperationSetInput( &bp,
|
||||
pointcount,
|
||||
vertex, 3*sizeof(float),
|
||||
normal, 3*sizeof(float) );
|
||||
if( ballrange <= 1.0 )
|
||||
bpOperationSetBall( &bp, spacing );
|
||||
else
|
||||
bpOperationSetBallRange( &bp, spacing, ballrange * spacing );
|
||||
bpOperationSetOutput( &bp,
|
||||
BP_TRIANGLE_WINDING_CCW,
|
||||
3*sizeof(int),
|
||||
sizeof(int),
|
||||
0, 0, 0 );
|
||||
bpOperationNormalAgreement( &bp, 0.5, 0.5 );
|
||||
|
||||
/* Set up callback to pack vertices */
|
||||
bppack.vertex = vertex;
|
||||
bppack.normal = normal;
|
||||
bpOperationVertexPackCallback( &bp, ballpivoting_pack_callback, &bppack );
|
||||
|
||||
threadcount = (int) ideal_thread_count ();
|
||||
|
||||
/*
|
||||
* Note from Alexis:
|
||||
* It could be a good idea to expose memory consumption limits...
|
||||
* By default, it's set to 50% of system RAM.
|
||||
* Indirectly, it acts to reduce the sampling rate when it's excessive for large parts.
|
||||
*
|
||||
* bp.maxmemorysize = 1*1024*1024*1024;
|
||||
*
|
||||
* Or, what about an adaptive sampling rate? 0.25mm is great for a truck's
|
||||
* engine, not so much for the hood.
|
||||
*/
|
||||
|
||||
#if DEBUG_BALL_PIVOTING_VERBOSE
|
||||
fprintf( stderr, "Ball Pivoting Start, %d points, %f spacing, %d threads\n",
|
||||
(int)pointcount, spacing, threadcount );
|
||||
#endif
|
||||
bpindices = (int *)bpConstructMesh( &bp,
|
||||
&output,
|
||||
threadcount,
|
||||
BP_FLAGS_PACK_VERTICES | BP_FLAGS_ALLOW_REDUCTION );
|
||||
#if DEBUG_BALL_PIVOTING_VERBOSE
|
||||
fprintf( stderr, "Ball Pivoting End, %d vertices, %d triangles, %.3f seconds ( %d warnings, %d errors )\n",
|
||||
(int)output.vertexcount, (int)output.trianglecount,
|
||||
(double)output.msecs / 1000.0, output.warningcount,
|
||||
output.errorcount );
|
||||
#endif
|
||||
|
||||
bptricount = output.trianglecount;
|
||||
bpvertexcount = output.vertexcount;
|
||||
long offset = gVertex.size()/3; /* indices need to be offset by the vertices already present */
|
||||
|
||||
for( long i = bpvertexcount, j = 0 ; i ; i--, j += 3 )
|
||||
{
|
||||
gVertex.push_back(vertex[j+0]);
|
||||
gVertex.push_back(vertex[j+1]);
|
||||
gVertex.push_back(vertex[j+2]);
|
||||
|
||||
gNormal.push_back(normal[j+0]);
|
||||
gNormal.push_back(normal[j+1]);
|
||||
gNormal.push_back(normal[j+2]);
|
||||
}
|
||||
|
||||
triindices = bpindices;
|
||||
for( long i = bptricount ; i ; i--, triindices += 3 )
|
||||
{
|
||||
gVIndex.push_back( triindices[0] + offset );
|
||||
gVIndex.push_back( triindices[1] + offset );
|
||||
gVIndex.push_back( triindices[2] + offset );
|
||||
}
|
||||
|
||||
free( bpindices );
|
||||
}
|
||||
|
||||
/*============ MAIN FUNCTION ============*/
|
||||
|
||||
//******************************************************************************
|
||||
// NAME main
|
||||
//
|
||||
// INPUTS
|
||||
// argc - commandline argument count
|
||||
// argv - array of commandline arguments
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Perform ball pivoting on a ".psamp" file generated from the
|
||||
// pointsampler application.
|
||||
//******************************************************************************
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
FILE *fp1 = NULL, *fp2 = NULL;
|
||||
char buffer[255], ch, gname[100];
|
||||
float csize = 0.0;
|
||||
float ballrange = 1.0;
|
||||
std::vector<float> points, normals;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s pointfile objfile [ballrange]\n", argv[0]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (argc == 4)
|
||||
ballrange = (float) atof (argv[3]);
|
||||
|
||||
if (!(fp1 = fopen (argv[1], "r")))
|
||||
{
|
||||
fprintf (stderr, "Error opening Point file(%s).\n", argv[1]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
memset (gname, 0, sizeof (gname));
|
||||
|
||||
/* read cellsize */
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
fgets (buffer, 255, fp1);
|
||||
csize = (float) atof (buffer);
|
||||
|
||||
points.clear();
|
||||
normals.clear();
|
||||
|
||||
gVIndex.clear();
|
||||
gOffset.clear();
|
||||
gGeom.clear();
|
||||
gVertex.clear();
|
||||
gNormal.clear();
|
||||
|
||||
/* read points */
|
||||
ch = fgetc (fp1);
|
||||
while (!feof(fp1))
|
||||
{
|
||||
ungetc (ch, fp1);
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
fgets (buffer, 255, fp1);
|
||||
|
||||
if (buffer[0] == '#')
|
||||
{
|
||||
if (points.size() > 0)
|
||||
{
|
||||
/* set grouping info */
|
||||
gOffset.push_back(gVIndex.size());
|
||||
gGeom.push_back(gname);
|
||||
|
||||
#if DEBUG
|
||||
fprintf (stdout, "Ball Pivoting %s...\n", gname);
|
||||
#endif
|
||||
/* perform ball pivoting */
|
||||
ball_pivot (points, normals, ballrange, csize);
|
||||
}
|
||||
|
||||
/* empty points & normals */
|
||||
points.clear();
|
||||
normals.clear();
|
||||
|
||||
/* read geometry name */
|
||||
char *tok = strtok (buffer, " \n\r"); /* eat '#' */
|
||||
tok = strtok (NULL, " \n\r");
|
||||
sprintf (gname, "%s", tok);
|
||||
}
|
||||
else
|
||||
{
|
||||
float px, py, pz;
|
||||
float dx, dy, dz;
|
||||
|
||||
sscanf (buffer, "%f %f %f %f %f %f",
|
||||
&px, &py, &pz, &dx, &dy, &dz);
|
||||
|
||||
points.push_back (px);
|
||||
points.push_back (py);
|
||||
points.push_back (pz);
|
||||
|
||||
normals.push_back (dx);
|
||||
normals.push_back (dy);
|
||||
normals.push_back (dz);
|
||||
}
|
||||
|
||||
ch = fgetc (fp1);
|
||||
while (ch == '\n' || ch == '\r') ch = fgetc (fp1);
|
||||
}
|
||||
|
||||
/* close point file */
|
||||
fclose (fp1);
|
||||
fp1 = NULL;
|
||||
|
||||
if (points.size() > 0)
|
||||
{
|
||||
/* set grouping info */
|
||||
gOffset.push_back(gVIndex.size());
|
||||
gGeom.push_back(gname);
|
||||
|
||||
#if DEBUG
|
||||
fprintf (stdout, "Ball Pivoting %s...\n", gname);
|
||||
#endif
|
||||
/* perform ball pivoting */
|
||||
ball_pivot (points, normals, ballrange, csize);
|
||||
}
|
||||
|
||||
/* output obj file */
|
||||
if (!(fp2 = fopen (argv[2], "w")))
|
||||
{
|
||||
fprintf (stderr, "Error opening OBJ file(%s).\n", argv[2]);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
fprintf (stdout, "Outputting OBJ file.\n", gname);
|
||||
#endif
|
||||
/* output OBJ file */
|
||||
output_obj (fp2, gVertex, gNormal, gVIndex, gGeom, gOffset);
|
||||
|
||||
/* close mesh file */
|
||||
fclose (fp2);
|
||||
fp2 = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../openNURBS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../tcl/generic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../Auxiliary
|
||||
)
|
||||
|
||||
add_executable(dcmain main.cpp)
|
||||
target_link_libraries(dcmain librt libbu libbn AUX MeshDecimation ${M_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
/* main.cpp
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/26/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* This is the standalone mesh decimation application.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard C/C++ libraries */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/* Custom libraries */
|
||||
#include "gctcommon.h"
|
||||
#include "MeshDecimation/meshdecimation.h"
|
||||
#include "MeshDecimation/meshoptimizer.h"
|
||||
#include "MeshDecimation/meshoptimization.h"
|
||||
|
||||
#if 0
|
||||
#define DECIMATION_FLAGS MD_ATTRIB_FLAGS_NORMALIZE
|
||||
#else
|
||||
#define DECIMATION_FLAGS MD_ATTRIB_FLAGS_COMPUTE_NORMALS
|
||||
#endif
|
||||
#define OPTLEVEL 3 // 0=none, 1=low, 2=medium, 3=high
|
||||
|
||||
/* globals */
|
||||
std::vector<float> gVertex;
|
||||
std::vector<float> gNormal;
|
||||
std::vector<float> gNewVertex;
|
||||
std::vector<float> gNewNormal;
|
||||
std::vector<long> gNewVIndex;
|
||||
std::vector<std::string> gGeom;
|
||||
std::vector<long> gOffset;
|
||||
|
||||
/*============ STATIC FUNCTIONS ============*/
|
||||
|
||||
//******************************************************************************
|
||||
// NAME mesh_decimate
|
||||
//
|
||||
// INPUTS
|
||||
// points - initial list of non-decimated vertices
|
||||
// normals - initial list of non-decimated normals
|
||||
// indexes - initial list of non-decimated indices
|
||||
// featuresize - the smallest feature size to keep undecimated
|
||||
// optlevel - optimization level
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Function that actually performs the mesh decimation routines.
|
||||
//******************************************************************************
|
||||
static void
|
||||
mesh_decimate(std::vector<float> &points,
|
||||
std::vector<float> &normals,
|
||||
std::vector<int> &indexes,
|
||||
float featuresize,
|
||||
int optlevel)
|
||||
{
|
||||
int threadcount;
|
||||
long pointcount = points.size() / 3;
|
||||
long tricount = indexes.size() / 3;
|
||||
float *vertex = &points[0];
|
||||
float *normal = &normals[0];
|
||||
int *indices = &indexes[0];
|
||||
int *triindices, isize = (int) sizeof(int);
|
||||
mdOperation mdop;
|
||||
|
||||
if (points.size() < 1) return;
|
||||
|
||||
threadcount = (int) ideal_thread_count ();
|
||||
|
||||
mdOperationInit(&mdop);
|
||||
mdOperationData(&mdop, pointcount, vertex, sizeof(float), 3*sizeof(float),
|
||||
tricount, indices, isize, 3*isize);
|
||||
mdOperationStrength(&mdop, featuresize);
|
||||
mdOperationAddAttrib(&mdop, normal, sizeof(float), 3, 3*sizeof(float), DECIMATION_FLAGS);
|
||||
|
||||
#if DEBUG_MESH_DECIMATION_VERBOSE
|
||||
fprintf( stderr, "Mesh Decimation Start, %d vertices, %d triangles, %f featuresize\n",
|
||||
(int)pointcount, (int)tricount, featuresize );
|
||||
#endif
|
||||
mdMeshDecimation(&mdop, threadcount,
|
||||
MD_FLAGS_NORMAL_VERTEX_SPLITTING|MD_FLAGS_TRIANGLE_WINDING_CCW);
|
||||
#if DEBUG_MESH_DECIMATION_VERBOSE
|
||||
fprintf( stderr, "Mesh Decimation End, %d vertices, %d triangles, %.3f seconds\n",
|
||||
(int)mdop.vertexcount, (int)mdop.tricount, (double)mdop.msecs / 1000.0 );
|
||||
#endif
|
||||
|
||||
pointcount = mdop.vertexcount;
|
||||
tricount = mdop.tricount;
|
||||
|
||||
mesh_optimization (pointcount, tricount, indices, isize, threadcount, optlevel);
|
||||
|
||||
/* indices need to be offset by the vertices already present */
|
||||
long offset = gNewVertex.size()/3;
|
||||
|
||||
for( long i = pointcount, j = 0 ; i ; i--, j += 3 )
|
||||
{
|
||||
gNewVertex.push_back(vertex[j+0]);
|
||||
gNewVertex.push_back(vertex[j+1]);
|
||||
gNewVertex.push_back(vertex[j+2]);
|
||||
|
||||
gNewNormal.push_back(normal[j+0]);
|
||||
gNewNormal.push_back(normal[j+1]);
|
||||
gNewNormal.push_back(normal[j+2]);
|
||||
}
|
||||
|
||||
triindices = indices;
|
||||
for( long i = tricount ; i ; i--, triindices += 3 )
|
||||
{
|
||||
gNewVIndex.push_back( triindices[0] + offset );
|
||||
gNewVIndex.push_back( triindices[1] + offset );
|
||||
gNewVIndex.push_back( triindices[2] + offset );
|
||||
}
|
||||
}
|
||||
|
||||
/*============ MAIN FUNCTION ============*/
|
||||
|
||||
//******************************************************************************
|
||||
// NAME main
|
||||
//
|
||||
// INPUTS
|
||||
// argc - commandline argument count
|
||||
// argv - array of commandline arguments
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Perform mesh decimation on an ".obj" file generated from the
|
||||
// ballpivot (Ball Pivoting) or march (Marching Cubes) application.
|
||||
//******************************************************************************
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
FILE *fp1 = NULL, *fp2 = NULL;
|
||||
char buffer[255], ch, gname[100];
|
||||
float fsize = 0.25;
|
||||
std::vector<int> indexes;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf (stderr, "Usage: %s infile outfile [featuresize]\n", argv[0]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (argc == 4)
|
||||
fsize = (float) atof (argv[3]);
|
||||
|
||||
if (!(fp1 = fopen (argv[1], "r")))
|
||||
{
|
||||
fprintf (stderr, "Error opening infile(%s).\n", argv[1]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
memset (gname, 0, sizeof (gname));
|
||||
|
||||
long low = 0;
|
||||
long high = 0;
|
||||
long offset = 0;
|
||||
|
||||
ch = fgetc (fp1);
|
||||
while (!feof(fp1))
|
||||
{
|
||||
ungetc (ch, fp1);
|
||||
memset (buffer, 0, sizeof (buffer));
|
||||
fgets (buffer, 255, fp1);
|
||||
|
||||
int len = strlen(buffer);
|
||||
if (buffer[len-1] == '\n') buffer[len-1] = '\0';
|
||||
|
||||
if (buffer[0] == 'g')
|
||||
{
|
||||
if (buffer[1] != '\0')
|
||||
{
|
||||
if (low > 0 && high > 0)
|
||||
{
|
||||
std::vector<float> points, normals;
|
||||
|
||||
/* set grouping info */
|
||||
gOffset.push_back(gNewVIndex.size());
|
||||
gGeom.push_back(gname);
|
||||
|
||||
#if DEBUG
|
||||
fprintf (stdout, "Decimating %s...\n", gname);
|
||||
#endif
|
||||
|
||||
/* stick current element's points into temp vectors */
|
||||
for (long i = (low -1); i <= (high -1); i++)
|
||||
{
|
||||
long idx = i*3;
|
||||
|
||||
points.push_back (gVertex[idx+0]);
|
||||
points.push_back (gVertex[idx+1]);
|
||||
points.push_back (gVertex[idx+2]);
|
||||
|
||||
normals.push_back (gNormal[idx+0]);
|
||||
normals.push_back (gNormal[idx+1]);
|
||||
normals.push_back (gNormal[idx+2]);
|
||||
}
|
||||
|
||||
/* do the mesh decimation */
|
||||
mesh_decimate(points, normals, indexes, fsize, OPTLEVEL);
|
||||
|
||||
/* reset indices */
|
||||
offset = high;
|
||||
low = high = -1;
|
||||
}
|
||||
|
||||
/* grab region name */
|
||||
char *tok = strtok (buffer, " \n\r"); /* eat 'g' */
|
||||
tok = strtok (NULL, " \n\r");
|
||||
sprintf (gname, "%s", tok);
|
||||
|
||||
indexes.clear();
|
||||
}
|
||||
}
|
||||
else if (buffer[0] == 'v')
|
||||
{
|
||||
if (buffer[1] == ' ') /* vertex */
|
||||
{
|
||||
float x, y, z;
|
||||
sscanf (buffer+2, "%f %f %f", &x, &y, &z);
|
||||
gVertex.push_back (x);
|
||||
gVertex.push_back (y);
|
||||
gVertex.push_back (z);
|
||||
}
|
||||
else if (buffer[1] == 'n') /* normal */
|
||||
{
|
||||
float x, y, z;
|
||||
sscanf (buffer+3, "%f %f %f", &x, &y, &z);
|
||||
gNormal.push_back (x);
|
||||
gNormal.push_back (y);
|
||||
gNormal.push_back (z);
|
||||
}
|
||||
}
|
||||
else if (buffer[0] == 'f')
|
||||
{
|
||||
long idx[3];
|
||||
char *tok = strtok(buffer, " \n");
|
||||
tok = strtok(NULL, " \n"); sscanf(tok, "%ld", &idx[0]);
|
||||
tok = strtok(NULL, " \n"); sscanf(tok, "%ld", &idx[1]);
|
||||
tok = strtok(NULL, " \n"); sscanf(tok, "%ld", &idx[2]);
|
||||
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
int j = idx[i];
|
||||
if (low < 1) low = j;
|
||||
else if (j < low) low = j;
|
||||
|
||||
if (high < 1) high = j;
|
||||
else if (j > high) high = j;
|
||||
|
||||
indexes.push_back (idx[i] - offset - 1);
|
||||
}
|
||||
}
|
||||
|
||||
ch = fgetc (fp1);
|
||||
while (ch == '\n' || ch == '\r') ch = fgetc (fp1);
|
||||
}
|
||||
fclose (fp1);
|
||||
fp1 = NULL;
|
||||
|
||||
if (low > 0 && high > 0)
|
||||
{
|
||||
std::vector<float> points, normals;
|
||||
|
||||
/* set grouping info */
|
||||
gOffset.push_back(gNewVIndex.size());
|
||||
gGeom.push_back(gname);
|
||||
|
||||
#if DEBUG
|
||||
fprintf (stdout, "Decimating %s...\n", gname);
|
||||
#endif
|
||||
|
||||
/* stick current element's points into temp vectors */
|
||||
for (long i = (low -1); i <= (high -1); i++)
|
||||
{
|
||||
long idx = i*3;
|
||||
|
||||
points.push_back (gVertex[idx+0]);
|
||||
points.push_back (gVertex[idx+1]);
|
||||
points.push_back (gVertex[idx+2]);
|
||||
|
||||
normals.push_back (gNormal[idx+0]);
|
||||
normals.push_back (gNormal[idx+1]);
|
||||
normals.push_back (gNormal[idx+2]);
|
||||
}
|
||||
|
||||
/* do the mesh decimation */
|
||||
mesh_decimate(points, normals, indexes, fsize, OPTLEVEL);
|
||||
}
|
||||
|
||||
/* output obj file */
|
||||
if (!(fp2 = fopen (argv[2], "w")))
|
||||
{
|
||||
fprintf (stderr, "Error opening OBJ file(%s).\n", argv[2]);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
fprintf (stdout, "Outputting OBJ file.\n", gname);
|
||||
#endif
|
||||
/* output OBJ file */
|
||||
output_obj (fp2, gNewVertex, gNewNormal, gNewVIndex, gGeom, gOffset);
|
||||
|
||||
/* close mesh file */
|
||||
fclose (fp2);
|
||||
fp2 = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../../include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../openNURBS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../tcl/generic
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../Auxiliary
|
||||
)
|
||||
|
||||
add_executable(psmain main.cpp)
|
||||
target_link_libraries(psmain librt libbu libbn AUX Sampler BrlcadGCT ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/* main.cpp
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2014 SURVICE Engineering. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Revision Date:
|
||||
* 08/22/13
|
||||
*
|
||||
* Authors(s):
|
||||
* DRH
|
||||
*
|
||||
* Description:
|
||||
* This is the standalone point sampling application.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard C/C++ libraries */
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
/* BRL-CAD libraries */
|
||||
#include "bu.h"
|
||||
|
||||
/* Custom libraries */
|
||||
#include "BRLCAD/BrlcadLoader.h"
|
||||
#include "BRLCAD/DbGeometry.h"
|
||||
#include "BRLCAD/DbTracer.h"
|
||||
#include "Sampler/PointSampler.h"
|
||||
|
||||
#include <gctcommon.h> // this has to be behind the brlcad headers!!!
|
||||
|
||||
/*============ MAIN FUNCTION ============*/
|
||||
|
||||
//******************************************************************************
|
||||
// NAME main
|
||||
//
|
||||
// INPUTS
|
||||
// argc - commandline argument count
|
||||
// argv - array of commandline arguments
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Perform point sampling on BRL-CAD geometry.
|
||||
//******************************************************************************
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int i, thread_count = (int) ideal_thread_count();
|
||||
float csize = 0.0;
|
||||
GLoaderInterface *loader = NULL;
|
||||
std::vector<std::string> gnames;
|
||||
|
||||
if (argc < 3)
|
||||
bu_exit(1, "Usage: %s model.g cellsize [item0 ...]\n", argv[0]);
|
||||
|
||||
/* get the cube size */
|
||||
csize = (float) atof (argv[2]);
|
||||
if (csize <= 0.0)
|
||||
bu_exit(2, "Cube size (%s) needs to be a float greater than 0.0.", argv[2]);
|
||||
|
||||
if (argc > 3)
|
||||
{
|
||||
/* user specified piece(s) of geometry */
|
||||
for (i=3; i<argc; i++)
|
||||
gnames.push_back(argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no geometry specified... convert them all */
|
||||
|
||||
/* create loader and start loading -- right now assume BRLCAD */
|
||||
loader = new BrlcadLoader(argv[1]);
|
||||
loader->startLoader();
|
||||
|
||||
if (loader->getStatus())
|
||||
{
|
||||
/* get region names */
|
||||
gnames = loader->getGeomNames();
|
||||
}
|
||||
|
||||
/* cleanup loader */
|
||||
delete loader;
|
||||
loader = NULL;
|
||||
}
|
||||
|
||||
FILE *fp = NULL;
|
||||
char fname[100];
|
||||
memset (fname, 0, sizeof (char) * 100);
|
||||
sprintf (fname, "%s.psamp", argv[1]);
|
||||
if (!(fp = fopen (fname, "w")))
|
||||
bu_exit(5, "Opening output PSAMP file failed.\n");
|
||||
|
||||
/* print cellsize */
|
||||
fprintf (fp, "%.4f\n", csize);
|
||||
|
||||
/* create target & tracers -- right now assume BRLCAD */
|
||||
GeomConversion::Interface::INativeGeometry *target = new GeomConversion::BRLCAD::DbGeometry(argv[1]);
|
||||
std::vector<GeomConversion::Interface::IGeometryTracer *> tracers;
|
||||
for (i=0; i<thread_count; i++)
|
||||
tracers.push_back(new GeomConversion::BRLCAD::DbTracer(target, i));
|
||||
|
||||
for (i=0; i<gnames.size(); i++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf (stdout, "Processing %s...\n", gnames.at(i).c_str());
|
||||
#endif
|
||||
|
||||
/* create the point sampler, set details, and start running */
|
||||
GeomConversion::Sampler::PointSampler *psamp = new GeomConversion::Sampler::PointSampler(target, tracers);
|
||||
target->loadGeometry(gnames.at(i), thread_count);
|
||||
psamp->setSpacing(csize);
|
||||
psamp->prepSample();
|
||||
psamp->runSample();
|
||||
target->cleanupGeometry();
|
||||
|
||||
/* Get points and normals for this geometry */
|
||||
std::vector<float> points = psamp->getPoints();
|
||||
std::vector<float> normals = psamp->getNormals();
|
||||
#if SURF_SOL_CAPTURE
|
||||
std::vector<std::string> sols = psamp->getSolidNumbers();
|
||||
std::vector<int> surfs = psamp->getSurfNumbers();
|
||||
#endif
|
||||
|
||||
/* cleanup sampler */
|
||||
delete psamp;
|
||||
psamp = NULL;
|
||||
|
||||
/* output points & normals */
|
||||
fprintf (fp, "# %s\n", gnames.at(i).c_str());
|
||||
for (int j=0; j<points.size(); j+=3)
|
||||
{
|
||||
fprintf (fp, "%.4f %.4f %.4f %.4f %.4f %.4f",
|
||||
points[j], points[j+1], points[j+2],
|
||||
normals[j], normals[j+1], normals[j+2]);
|
||||
#if SURF_SOL_CAPTURE
|
||||
fprintf (fp, " %s %d", sols[j/3].c_str(), surfs[j/3]);
|
||||
#endif
|
||||
|
||||
fprintf (fp, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
|
||||
/* cleanup target & tracers */
|
||||
while (tracers.size() > 0)
|
||||
{
|
||||
GeomConversion::Interface::IGeometryTracer *ti = tracers.back();
|
||||
tracers.pop_back();
|
||||
delete ti;
|
||||
}
|
||||
delete target;
|
||||
target = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
Regular → Executable
Reference in New Issue
Block a user