remove LOD_Decimator (c++ decimator), now replaced by bmesh decimator. also remove CTR c++ classes that are no longer used.
This commit is contained in:
@@ -188,7 +188,6 @@ unset(PLATFORM_DEFAULT)
|
|||||||
# Modifiers
|
# Modifiers
|
||||||
option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON)
|
option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON)
|
||||||
option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON)
|
option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON)
|
||||||
option(WITH_MOD_DECIMATE "Enable Decimate Modifier" ON)
|
|
||||||
option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON)
|
option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON)
|
||||||
option(WITH_MOD_REMESH "Enable Remesh Modifier" ON)
|
option(WITH_MOD_REMESH "Enable Remesh Modifier" ON)
|
||||||
option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF)
|
option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF)
|
||||||
@@ -2126,7 +2125,6 @@ if(FIRST_RUN)
|
|||||||
info_cfg_text("Modifiers:")
|
info_cfg_text("Modifiers:")
|
||||||
info_cfg_option(WITH_MOD_BOOLEAN)
|
info_cfg_option(WITH_MOD_BOOLEAN)
|
||||||
info_cfg_option(WITH_MOD_REMESH)
|
info_cfg_option(WITH_MOD_REMESH)
|
||||||
info_cfg_option(WITH_MOD_DECIMATE)
|
|
||||||
info_cfg_option(WITH_MOD_FLUID)
|
info_cfg_option(WITH_MOD_FLUID)
|
||||||
info_cfg_option(WITH_MOD_OCEANSIM)
|
info_cfg_option(WITH_MOD_OCEANSIM)
|
||||||
|
|
||||||
|
@@ -264,7 +264,6 @@ if 'blenderlite' in B.targets:
|
|||||||
target_env_defs['WITH_BF_FLUID'] = False
|
target_env_defs['WITH_BF_FLUID'] = False
|
||||||
target_env_defs['WITH_BF_OCEANSIM'] = False
|
target_env_defs['WITH_BF_OCEANSIM'] = False
|
||||||
target_env_defs['WITH_BF_SMOKE'] = False
|
target_env_defs['WITH_BF_SMOKE'] = False
|
||||||
target_env_defs['WITH_BF_DECIMATE'] = False
|
|
||||||
target_env_defs['WITH_BF_BOOLEAN'] = False
|
target_env_defs['WITH_BF_BOOLEAN'] = False
|
||||||
target_env_defs['WITH_BF_REMESH'] = False
|
target_env_defs['WITH_BF_REMESH'] = False
|
||||||
target_env_defs['WITH_BF_PYTHON'] = False
|
target_env_defs['WITH_BF_PYTHON'] = False
|
||||||
|
@@ -2,11 +2,9 @@ import os
|
|||||||
|
|
||||||
IGNORE = (
|
IGNORE = (
|
||||||
"/test/",
|
"/test/",
|
||||||
"/decimate_glut_test/",
|
|
||||||
"/BSP_GhostTest/",
|
"/BSP_GhostTest/",
|
||||||
"/release/",
|
"/release/",
|
||||||
"/xembed/",
|
"/xembed/",
|
||||||
"/decimation/intern/future/",
|
|
||||||
"/TerraplayNetwork/",
|
"/TerraplayNetwork/",
|
||||||
"/ik_glut_test/",
|
"/ik_glut_test/",
|
||||||
|
|
||||||
|
@@ -35,7 +35,6 @@ set(WITH_JACK OFF CACHE FORCE BOOL)
|
|||||||
set(WITH_LZMA OFF CACHE FORCE BOOL)
|
set(WITH_LZMA OFF CACHE FORCE BOOL)
|
||||||
set(WITH_LZO OFF CACHE FORCE BOOL)
|
set(WITH_LZO OFF CACHE FORCE BOOL)
|
||||||
set(WITH_MOD_BOOLEAN OFF CACHE FORCE BOOL)
|
set(WITH_MOD_BOOLEAN OFF CACHE FORCE BOOL)
|
||||||
set(WITH_MOD_DECIMATE OFF CACHE FORCE BOOL)
|
|
||||||
set(WITH_MOD_FLUID OFF CACHE FORCE BOOL)
|
set(WITH_MOD_FLUID OFF CACHE FORCE BOOL)
|
||||||
set(WITH_MOD_REMESH OFF CACHE FORCE BOOL)
|
set(WITH_MOD_REMESH OFF CACHE FORCE BOOL)
|
||||||
set(WITH_MOD_SMOKE OFF CACHE FORCE BOOL)
|
set(WITH_MOD_SMOKE OFF CACHE FORCE BOOL)
|
||||||
|
@@ -152,7 +152,6 @@ def validate_arguments(args, bc):
|
|||||||
'WITH_BF_RAYOPTIMIZATION',
|
'WITH_BF_RAYOPTIMIZATION',
|
||||||
'BF_RAYOPTIMIZATION_SSE_FLAGS',
|
'BF_RAYOPTIMIZATION_SSE_FLAGS',
|
||||||
'WITH_BF_FLUID',
|
'WITH_BF_FLUID',
|
||||||
'WITH_BF_DECIMATE',
|
|
||||||
'WITH_BF_BOOLEAN',
|
'WITH_BF_BOOLEAN',
|
||||||
'WITH_BF_REMESH',
|
'WITH_BF_REMESH',
|
||||||
'WITH_BF_OCEANSIM',
|
'WITH_BF_OCEANSIM',
|
||||||
@@ -265,7 +264,6 @@ def read_opts(env, cfg, args):
|
|||||||
('BF_PYTHON_ABI_FLAGS', 'Python ABI flags (suffix in library version: m, mu, etc)', ''),
|
('BF_PYTHON_ABI_FLAGS', 'Python ABI flags (suffix in library version: m, mu, etc)', ''),
|
||||||
|
|
||||||
(BoolVariable('WITH_BF_FLUID', 'Build with Fluid simulation (Elbeem)', True)),
|
(BoolVariable('WITH_BF_FLUID', 'Build with Fluid simulation (Elbeem)', True)),
|
||||||
(BoolVariable('WITH_BF_DECIMATE', 'Build with decimate modifier', True)),
|
|
||||||
(BoolVariable('WITH_BF_BOOLEAN', 'Build with boolean modifier', True)),
|
(BoolVariable('WITH_BF_BOOLEAN', 'Build with boolean modifier', True)),
|
||||||
(BoolVariable('WITH_BF_REMESH', 'Build with remesh modifier', True)),
|
(BoolVariable('WITH_BF_REMESH', 'Build with remesh modifier', True)),
|
||||||
(BoolVariable('WITH_BF_OCEANSIM', 'Build with ocean simulation', False)),
|
(BoolVariable('WITH_BF_OCEANSIM', 'Build with ocean simulation', False)),
|
||||||
|
@@ -49,11 +49,6 @@ if(WITH_MOD_SMOKE)
|
|||||||
add_subdirectory(smoke)
|
add_subdirectory(smoke)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_MOD_DECIMATE)
|
|
||||||
add_subdirectory(container)
|
|
||||||
add_subdirectory(decimation)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_MOD_BOOLEAN)
|
if(WITH_MOD_BOOLEAN)
|
||||||
add_subdirectory(bsp)
|
add_subdirectory(bsp)
|
||||||
endif()
|
endif()
|
||||||
|
@@ -6,9 +6,7 @@ SConscript(['audaspace/SConscript',
|
|||||||
'ghost/SConscript',
|
'ghost/SConscript',
|
||||||
'guardedalloc/SConscript',
|
'guardedalloc/SConscript',
|
||||||
'moto/SConscript',
|
'moto/SConscript',
|
||||||
'container/SConscript',
|
|
||||||
'memutil/SConscript/',
|
'memutil/SConscript/',
|
||||||
'decimation/SConscript',
|
|
||||||
'iksolver/SConscript',
|
'iksolver/SConscript',
|
||||||
'itasc/SConscript',
|
'itasc/SConscript',
|
||||||
'opencolorio/SConscript',
|
'opencolorio/SConscript',
|
||||||
@@ -17,6 +15,9 @@ SConscript(['audaspace/SConscript',
|
|||||||
'smoke/SConscript',
|
'smoke/SConscript',
|
||||||
'raskter/SConscript'])
|
'raskter/SConscript'])
|
||||||
|
|
||||||
|
# currently only contains headers
|
||||||
|
# SConscript('container/SConscript')
|
||||||
|
|
||||||
if env ['WITH_BF_REMESH']:
|
if env ['WITH_BF_REMESH']:
|
||||||
SConscript(['dualcon/SConscript'])
|
SConscript(['dualcon/SConscript'])
|
||||||
|
|
||||||
|
@@ -33,14 +33,9 @@ set(INC_SYS
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(SRC
|
set(SRC
|
||||||
intern/CTR_List.cpp
|
|
||||||
|
|
||||||
CTR_HashedPtr.h
|
CTR_HashedPtr.h
|
||||||
CTR_List.h
|
|
||||||
CTR_Map.h
|
CTR_Map.h
|
||||||
CTR_TaggedIndex.h
|
|
||||||
CTR_TaggedSetOps.h
|
|
||||||
CTR_UHeap.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# infact nothing to compile!
|
||||||
blender_add_lib(bf_intern_ctr "${SRC}" "${INC}" "${INC_SYS}")
|
blender_add_lib(bf_intern_ctr "${SRC}" "${INC}" "${INC_SYS}")
|
||||||
|
@@ -30,8 +30,8 @@
|
|||||||
* \ingroup ctr
|
* \ingroup ctr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CTR_HASHEDPTR_H
|
#ifndef __CTR_HASHEDPTR_H__
|
||||||
#define CTR_HASHEDPTR_H
|
#define __CTR_HASHEDPTR_H__
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -51,5 +51,5 @@ public:
|
|||||||
void *getValue() const { return m_valptr; }
|
void *getValue() const { return m_valptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //CTR_HASHEDPTR_H
|
#endif /* __CTR_HASHEDPTR_H__ */
|
||||||
|
|
||||||
|
@@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file container/CTR_List.h
|
|
||||||
* \ingroup ctr
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef CTR_LIST_H
|
|
||||||
#define CTR_LIST_H
|
|
||||||
|
|
||||||
class CTR_Link {
|
|
||||||
public:
|
|
||||||
CTR_Link(
|
|
||||||
);
|
|
||||||
|
|
||||||
CTR_Link(
|
|
||||||
CTR_Link *next,
|
|
||||||
CTR_Link *prev
|
|
||||||
);
|
|
||||||
|
|
||||||
CTR_Link *
|
|
||||||
getNext(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
CTR_Link *
|
|
||||||
getPrev(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
bool
|
|
||||||
isHead(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
bool
|
|
||||||
isTail(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void
|
|
||||||
insertBefore(
|
|
||||||
CTR_Link *link
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
insertAfter(
|
|
||||||
CTR_Link *link
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
remove(
|
|
||||||
);
|
|
||||||
|
|
||||||
private:
|
|
||||||
CTR_Link *m_next;
|
|
||||||
CTR_Link *m_prev;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CTR_List {
|
|
||||||
public:
|
|
||||||
|
|
||||||
CTR_List(
|
|
||||||
);
|
|
||||||
|
|
||||||
CTR_Link *
|
|
||||||
getHead(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
CTR_Link *
|
|
||||||
getTail(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void
|
|
||||||
addHead(
|
|
||||||
CTR_Link *link
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
addTail(
|
|
||||||
CTR_Link *link
|
|
||||||
);
|
|
||||||
|
|
||||||
private:
|
|
||||||
CTR_Link m_head;
|
|
||||||
CTR_Link m_tail;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -29,9 +29,8 @@
|
|||||||
* \ingroup ctr
|
* \ingroup ctr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef __CTR_MAP_H__
|
||||||
#ifndef CTR_MAP_H
|
#define __CTR_MAP_H__
|
||||||
#define CTR_MAP_H
|
|
||||||
|
|
||||||
template <class Key, class Value>
|
template <class Key, class Value>
|
||||||
class CTR_Map {
|
class CTR_Map {
|
||||||
@@ -177,5 +176,4 @@ private:
|
|||||||
Entry **m_buckets;
|
Entry **m_buckets;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif /* __CTR_MAP_H__ */
|
||||||
|
|
||||||
|
@@ -1,219 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file container/CTR_TaggedIndex.h
|
|
||||||
* \ingroup ctr
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
* Copyright (C) 2001 NaN Technologies B.V.
|
|
||||||
* Simple tagged index class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __CTR_TAGGEDINDEX_H__
|
|
||||||
#define __CTR_TAGGEDINDEX_H__
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is supposed to be a simple tagged index class. If these
|
|
||||||
* were indices into a mesh then we would never need 32 bits for such indices.
|
|
||||||
* It is often handy to have a few extra bits around to mark objects etc. We
|
|
||||||
* steal a few bits of CTR_TaggedIndex objects for this purpose. From the outside
|
|
||||||
* it will behave like a standard unsigned int but just carry the extra tag
|
|
||||||
* information around with it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "MEM_sys_types.h"
|
|
||||||
|
|
||||||
enum {
|
|
||||||
|
|
||||||
empty_tag = 0x0,
|
|
||||||
empty_index = 0xffffffff
|
|
||||||
};
|
|
||||||
|
|
||||||
template <
|
|
||||||
int tag_shift,
|
|
||||||
int index_mask
|
|
||||||
> class CTR_TaggedIndex {
|
|
||||||
public:
|
|
||||||
CTR_TaggedIndex(
|
|
||||||
) :
|
|
||||||
m_val ((empty_tag << tag_shift) | (empty_index & index_mask))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CTR_TaggedIndex(
|
|
||||||
const int val
|
|
||||||
) :
|
|
||||||
m_val ((val & index_mask) | ((empty_tag << tag_shift) & (~index_mask))) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CTR_TaggedIndex(
|
|
||||||
const unsigned int val
|
|
||||||
) :
|
|
||||||
m_val ((val & index_mask) | ((empty_tag << tag_shift) & (~index_mask))) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CTR_TaggedIndex(
|
|
||||||
const long int val
|
|
||||||
) :
|
|
||||||
m_val ( ((long int) val & index_mask)
|
|
||||||
| ( (empty_tag << tag_shift)
|
|
||||||
& (~index_mask)) ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CTR_TaggedIndex(
|
|
||||||
const long unsigned int val
|
|
||||||
) :
|
|
||||||
m_val ( ((long unsigned int)val & index_mask)
|
|
||||||
| ( (empty_tag << tag_shift)
|
|
||||||
& (~index_mask) ) ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(_WIN64)
|
|
||||||
CTR_TaggedIndex(
|
|
||||||
const uint64_t val
|
|
||||||
) :
|
|
||||||
m_val ( ((uint64_t)val & index_mask)
|
|
||||||
| ( (empty_tag << tag_shift)
|
|
||||||
& (~index_mask) ) ) {
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CTR_TaggedIndex(
|
|
||||||
const CTR_TaggedIndex &my_index
|
|
||||||
):
|
|
||||||
m_val(my_index.m_val)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
operator == (
|
|
||||||
const CTR_TaggedIndex& rhs
|
|
||||||
) const {
|
|
||||||
|
|
||||||
return ((this->m_val & index_mask) == (rhs.m_val & index_mask));
|
|
||||||
}
|
|
||||||
|
|
||||||
operator unsigned int () const {
|
|
||||||
return m_val & index_mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator unsigned long int () const {
|
|
||||||
return (unsigned long int)(m_val & index_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator int () const {
|
|
||||||
return int(m_val & index_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator long int () const {
|
|
||||||
return (long int)(m_val & index_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_WIN64)
|
|
||||||
operator uint64_t () const {
|
|
||||||
return (uint64_t)(m_val & index_mask);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool
|
|
||||||
IsEmpty(
|
|
||||||
) const {
|
|
||||||
return ((m_val & index_mask) == (empty_index & index_mask));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
CTR_TaggedIndex
|
|
||||||
Empty(
|
|
||||||
) {
|
|
||||||
return CTR_TaggedIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Invalidate(
|
|
||||||
) {
|
|
||||||
m_val = (empty_tag << tag_shift) | (empty_index & index_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
Tag (
|
|
||||||
) const {
|
|
||||||
return m_val >> tag_shift;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SetTag(
|
|
||||||
unsigned int tag
|
|
||||||
) {
|
|
||||||
m_val = (m_val & index_mask) | ((tag << tag_shift) & (~index_mask));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
EmptyTag(
|
|
||||||
) {
|
|
||||||
m_val = (m_val & index_mask) | ((empty_tag << tag_shift) & (~index_mask));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
IsEmptyTag(
|
|
||||||
) const {
|
|
||||||
return (Tag() == Empty().Tag());
|
|
||||||
}
|
|
||||||
|
|
||||||
// functionals
|
|
||||||
|
|
||||||
struct greater : std::binary_function<CTR_TaggedIndex, CTR_TaggedIndex, bool>
|
|
||||||
{
|
|
||||||
bool
|
|
||||||
operator()(
|
|
||||||
const CTR_TaggedIndex& a,
|
|
||||||
const CTR_TaggedIndex& b
|
|
||||||
) const {
|
|
||||||
return (int(a) > int(b));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
private :
|
|
||||||
CTR_TaggedIndex(
|
|
||||||
const CTR_TaggedIndex *index
|
|
||||||
) {};
|
|
||||||
|
|
||||||
unsigned int m_val;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,301 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file container/CTR_TaggedSetOps.h
|
|
||||||
* \ingroup ctr
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __CTR_TAGGEDSETOPS_H__
|
|
||||||
#define __CTR_TAGGEDSETOPS_H__
|
|
||||||
|
|
||||||
#include "MEM_NonCopyable.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class contains some utility functions for finding the intersection,
|
|
||||||
* union, and difference of a collection of stl vector of indices into
|
|
||||||
* a set of primitives.
|
|
||||||
*
|
|
||||||
* These are mainly used as helper functions in the decimation and bsp
|
|
||||||
* libraries.
|
|
||||||
*
|
|
||||||
* This template class assumes that each value of type IndexType encountered
|
|
||||||
* in the list is a valid index into an array of primitives. This is not
|
|
||||||
* checked at run-time and is left to the user to insure. Prmitives of
|
|
||||||
* type ObjectType must have the following public methods to be used by
|
|
||||||
* this template class:
|
|
||||||
*
|
|
||||||
* int
|
|
||||||
* OpenTag(void) --- return a persistent tag value for the primitive
|
|
||||||
*
|
|
||||||
* void
|
|
||||||
* SetOpenTag(int bla) --- set the persistent tag value for this primitive to bla.
|
|
||||||
*
|
|
||||||
* bool
|
|
||||||
* SelectTag() --- return a persistent boolean tag for this primitive
|
|
||||||
*
|
|
||||||
* void
|
|
||||||
* SetSelectTag(bool bla) --- set the persistent boolean tag for this primitive to bla.
|
|
||||||
*
|
|
||||||
* Here persistent means that the tag should be associated with the object for the
|
|
||||||
* entire lifetime of the primitive. Again none of this stuff is enforced you have
|
|
||||||
* to make sure that your primitives do the right thing. Often these tags can be
|
|
||||||
* cunningly stowed away inside some of the spare bits in the primitive. See
|
|
||||||
* CTR_TaggedIndex for such a class.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
template
|
|
||||||
<class IndexType, class ObjectType>
|
|
||||||
class CTR_TaggedSetOps : public MEM_NonCopyable {
|
|
||||||
|
|
||||||
public :
|
|
||||||
|
|
||||||
static
|
|
||||||
void
|
|
||||||
Intersect(
|
|
||||||
const std::vector< std::vector<IndexType> > &index_list,
|
|
||||||
std::vector<ObjectType> &primitives,
|
|
||||||
std::vector<IndexType> &output,
|
|
||||||
unsigned int mask,
|
|
||||||
unsigned int shift
|
|
||||||
) {
|
|
||||||
|
|
||||||
// iterate through vectors in index_list
|
|
||||||
// iterate through individual members of each vector
|
|
||||||
// mark each obejct that the index points to
|
|
||||||
|
|
||||||
typename std::vector< std::vector<IndexType> >::const_iterator
|
|
||||||
last_vector = index_list.end();
|
|
||||||
typename std::vector< std::vector<IndexType> >::const_iterator
|
|
||||||
start_vector = index_list.begin();
|
|
||||||
|
|
||||||
// FIXME some temporary space
|
|
||||||
|
|
||||||
std::vector<IndexType> temp_union;
|
|
||||||
temp_union.reserve(64);
|
|
||||||
|
|
||||||
int tag_num = 0;
|
|
||||||
|
|
||||||
for (; start_vector != last_vector; ++start_vector) {
|
|
||||||
|
|
||||||
typename std::vector<IndexType>::const_iterator
|
|
||||||
last_index = start_vector->end();
|
|
||||||
typename std::vector<IndexType>::const_iterator
|
|
||||||
start_index = start_vector->begin();
|
|
||||||
|
|
||||||
for (; start_index != last_index; ++start_index) {
|
|
||||||
|
|
||||||
ObjectType & prim = primitives[*start_index];
|
|
||||||
|
|
||||||
if (!prim.OpenTag()) {
|
|
||||||
// compute the union
|
|
||||||
temp_union.push_back(*start_index);
|
|
||||||
}
|
|
||||||
int tag = prim.OpenTag();
|
|
||||||
tag = (tag & mask) >> shift;
|
|
||||||
tag += 1;
|
|
||||||
prim.SetOpenTag((prim.OpenTag() & ~mask)| ((tag << shift) & mask));
|
|
||||||
}
|
|
||||||
|
|
||||||
++tag_num;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now iterate through the union and pull out all those with the right tag
|
|
||||||
|
|
||||||
typename std::vector<IndexType>::const_iterator last_index =
|
|
||||||
temp_union.end();
|
|
||||||
typename std::vector<IndexType>::const_iterator start_index =
|
|
||||||
temp_union.begin();
|
|
||||||
|
|
||||||
for (; start_index != last_index; ++start_index) {
|
|
||||||
|
|
||||||
ObjectType & prim = primitives[*start_index];
|
|
||||||
|
|
||||||
if (prim.OpenTag() == tag_num) {
|
|
||||||
//it's part of the intersection!
|
|
||||||
|
|
||||||
output.push_back(*start_index);
|
|
||||||
// because we're iterating through the union
|
|
||||||
// it's safe to remove the tag at this point
|
|
||||||
|
|
||||||
prim.SetOpenTag(prim.OpenTag() & ~mask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// note not a strict set intersection!
|
|
||||||
// if x appears twice in b and is part of the intersection
|
|
||||||
// it will appear twice in the intersection
|
|
||||||
|
|
||||||
static
|
|
||||||
void
|
|
||||||
IntersectPair(
|
|
||||||
const std::vector<IndexType> &a,
|
|
||||||
const std::vector<IndexType> &b,
|
|
||||||
std::vector<ObjectType> &primitives,
|
|
||||||
std::vector<IndexType> &output
|
|
||||||
) {
|
|
||||||
|
|
||||||
typename std::vector<IndexType>::const_iterator last_index =
|
|
||||||
a.end();
|
|
||||||
typename std::vector<IndexType>::const_iterator start_index =
|
|
||||||
a.begin();
|
|
||||||
|
|
||||||
for (; start_index != last_index; ++start_index) {
|
|
||||||
ObjectType & prim = primitives[*start_index];
|
|
||||||
prim.SetSelectTag(true);
|
|
||||||
}
|
|
||||||
last_index = b.end();
|
|
||||||
start_index = b.begin();
|
|
||||||
|
|
||||||
for (; start_index != last_index; ++start_index) {
|
|
||||||
ObjectType & prim = primitives[*start_index];
|
|
||||||
if (prim.SelectTag()) {
|
|
||||||
output.push_back(*start_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// deselect
|
|
||||||
last_index = a.end();
|
|
||||||
start_index = a.begin();
|
|
||||||
|
|
||||||
for (; start_index != last_index; ++start_index) {
|
|
||||||
ObjectType & prim = primitives[*start_index];
|
|
||||||
prim.SetSelectTag(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
void
|
|
||||||
Union(
|
|
||||||
std::vector< std::vector<IndexType> > &index_list,
|
|
||||||
std::vector<ObjectType> &primitives,
|
|
||||||
std::vector<IndexType> &output
|
|
||||||
) {
|
|
||||||
|
|
||||||
// iterate through vectors in index_list
|
|
||||||
// iterate through individual members of each vector
|
|
||||||
// mark each obejct that the index points to
|
|
||||||
|
|
||||||
typename std::vector< std::vector<IndexType> >::const_iterator
|
|
||||||
last_vector = index_list.end();
|
|
||||||
typename std::vector< std::vector<IndexType> >::iterator
|
|
||||||
start_vector = index_list.begin();
|
|
||||||
|
|
||||||
for (; start_vector != last_vector; ++start_vector) {
|
|
||||||
|
|
||||||
typename std::vector<IndexType>::const_iterator
|
|
||||||
last_index = start_vector->end();
|
|
||||||
typename std::vector<IndexType>::iterator
|
|
||||||
start_index = start_vector->begin();
|
|
||||||
|
|
||||||
for (; start_index != last_index; ++start_index) {
|
|
||||||
|
|
||||||
ObjectType & prim = primitives[*start_index];
|
|
||||||
|
|
||||||
if (!prim.SelectTag()) {
|
|
||||||
// compute the union
|
|
||||||
output.push_back(*start_index);
|
|
||||||
prim.SetSelectTag(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now iterate through the union and reset the tags
|
|
||||||
|
|
||||||
typename std::vector<IndexType>::const_iterator last_index =
|
|
||||||
output.end();
|
|
||||||
typename std::vector<IndexType>::iterator start_index =
|
|
||||||
output.begin();
|
|
||||||
|
|
||||||
for (; start_index != last_index; ++start_index) {
|
|
||||||
|
|
||||||
ObjectType & prim = primitives[*start_index];
|
|
||||||
prim.SetSelectTag(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
void
|
|
||||||
Difference(
|
|
||||||
std::vector< IndexType> &a,
|
|
||||||
std::vector< IndexType> &b,
|
|
||||||
std::vector<ObjectType> &primitives,
|
|
||||||
std::vector< IndexType> &output
|
|
||||||
) {
|
|
||||||
|
|
||||||
// iterate through b mark all
|
|
||||||
// iterate through a and add to output all unmarked
|
|
||||||
|
|
||||||
typename std::vector<IndexType>::const_iterator last_index =
|
|
||||||
b.end();
|
|
||||||
typename std::vector<IndexType>::iterator start_index =
|
|
||||||
b.begin();
|
|
||||||
|
|
||||||
for (; start_index != last_index; ++start_index) {
|
|
||||||
|
|
||||||
ObjectType & prim = primitives[*start_index];
|
|
||||||
prim.SetSelectTag(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
last_index = a.end();
|
|
||||||
start_index = a.begin();
|
|
||||||
|
|
||||||
for (; start_index != last_index; ++start_index) {
|
|
||||||
|
|
||||||
ObjectType & prim = primitives[*start_index];
|
|
||||||
if (!prim.SelectTag()) {
|
|
||||||
output.push_back(*start_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// clean up the tags
|
|
||||||
|
|
||||||
last_index = b.end();
|
|
||||||
start_index = b.begin();
|
|
||||||
|
|
||||||
for (; start_index != last_index; ++start_index) {
|
|
||||||
|
|
||||||
ObjectType & prim = primitives[*start_index];
|
|
||||||
prim.SetSelectTag(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
// private constructor - this class is not meant for
|
|
||||||
// instantiation
|
|
||||||
|
|
||||||
CTR_TaggedSetOps();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,307 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file container/CTR_UHeap.h
|
|
||||||
* \ingroup ctr
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
* Copyright (C) 2001 NaN Technologies B.V.
|
|
||||||
*
|
|
||||||
* @author Laurence
|
|
||||||
* @mainpage CTR_UHeap an updatable heap template class (also
|
|
||||||
* known as an updatable priority queue)
|
|
||||||
*
|
|
||||||
* Todo: Make CTR_UHeapable a template class with m_key the
|
|
||||||
* template parameter, so that arbitrary value types with
|
|
||||||
* operators (=,>) defined can be used.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __CTR_UHEAP_H__
|
|
||||||
#define __CTR_UHEAP_H__
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "MEM_NonCopyable.h"
|
|
||||||
|
|
||||||
class CTR_UHeapable {
|
|
||||||
|
|
||||||
public:
|
|
||||||
int &
|
|
||||||
HeapPos(
|
|
||||||
) {
|
|
||||||
return m_ind;
|
|
||||||
};
|
|
||||||
float &
|
|
||||||
HeapKey(
|
|
||||||
) {
|
|
||||||
return m_key;
|
|
||||||
};
|
|
||||||
|
|
||||||
const
|
|
||||||
float &
|
|
||||||
HeapKey(
|
|
||||||
) const {
|
|
||||||
return m_key;
|
|
||||||
};
|
|
||||||
|
|
||||||
const
|
|
||||||
int &
|
|
||||||
HeapPos(
|
|
||||||
) const {
|
|
||||||
return m_ind;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
float m_key;
|
|
||||||
int m_ind;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
CTR_UHeapable(
|
|
||||||
) : m_key(0),
|
|
||||||
m_ind(0)
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
~CTR_UHeapable(
|
|
||||||
) {
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class HeapType>
|
|
||||||
class CTR_UHeap : public MEM_NonCopyable
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
static
|
|
||||||
CTR_UHeap *
|
|
||||||
New(
|
|
||||||
) {
|
|
||||||
return new CTR_UHeap();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MakeHeap(
|
|
||||||
HeapType *base
|
|
||||||
) {
|
|
||||||
int i;
|
|
||||||
int start = Parent(m_vector.size() - 1);
|
|
||||||
for (i = start; i >= 0; --i) {
|
|
||||||
DownHeap(base, i);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
Insert(
|
|
||||||
HeapType *base,
|
|
||||||
int elem
|
|
||||||
) {
|
|
||||||
// add element to vector
|
|
||||||
m_vector.push_back(elem);
|
|
||||||
base[elem].HeapPos() = m_vector.size() - 1;
|
|
||||||
|
|
||||||
// push the element up the heap
|
|
||||||
UpHeap(base, m_vector.size() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// access to the vector for initial loading of elements
|
|
||||||
|
|
||||||
std::vector<int> &
|
|
||||||
HeapVector(
|
|
||||||
) {
|
|
||||||
return m_vector;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Remove(
|
|
||||||
HeapType *base,
|
|
||||||
int i
|
|
||||||
) {
|
|
||||||
|
|
||||||
// exchange with last element - pop last
|
|
||||||
// element and move up or down the heap as appropriate
|
|
||||||
if (m_vector.empty()) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i != int(m_vector.size()) - 1) {
|
|
||||||
|
|
||||||
Swap(base, i, m_vector.size() - 1);
|
|
||||||
m_vector.pop_back();
|
|
||||||
|
|
||||||
if (!m_vector.empty()) {
|
|
||||||
UpHeap(base, i);
|
|
||||||
DownHeap(base, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_vector.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
Top(
|
|
||||||
) const {
|
|
||||||
if (m_vector.empty()) return -1;
|
|
||||||
return m_vector[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
SC_Heap(
|
|
||||||
HeapType *base
|
|
||||||
) {
|
|
||||||
int i;
|
|
||||||
for (i = 1; i < int(m_vector.size()); i++) {
|
|
||||||
|
|
||||||
CTR_UHeapable *elem = base + m_vector[i];
|
|
||||||
CTR_UHeapable *p_elem = base + m_vector[Parent(i)];
|
|
||||||
|
|
||||||
assert(p_elem->HeapKey() >= elem->HeapKey());
|
|
||||||
assert(elem->HeapPos() == i);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
~CTR_UHeap(
|
|
||||||
) {
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
CTR_UHeap(
|
|
||||||
) {
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<int> m_vector;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void
|
|
||||||
Swap(
|
|
||||||
HeapType *base,
|
|
||||||
int i,
|
|
||||||
int j
|
|
||||||
) {
|
|
||||||
std::swap(m_vector[i], m_vector[j]);
|
|
||||||
|
|
||||||
CTR_UHeapable *heap_i = base + m_vector[i];
|
|
||||||
CTR_UHeapable *heap_j = base + m_vector[j];
|
|
||||||
|
|
||||||
// Exchange heap positions
|
|
||||||
heap_i->HeapPos() = i;
|
|
||||||
heap_j->HeapPos() = j;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
Parent(
|
|
||||||
unsigned int i
|
|
||||||
) {
|
|
||||||
return (i - 1) >> 1;
|
|
||||||
}
|
|
||||||
int
|
|
||||||
Left(
|
|
||||||
int i
|
|
||||||
) {
|
|
||||||
return (i << 1) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
Right(
|
|
||||||
int i
|
|
||||||
) {
|
|
||||||
return (i << 1) + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
|
||||||
HeapVal(
|
|
||||||
HeapType *base,
|
|
||||||
int i
|
|
||||||
) {
|
|
||||||
return base[m_vector[i]].HeapKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DownHeap(
|
|
||||||
HeapType *base,
|
|
||||||
int i
|
|
||||||
) {
|
|
||||||
int heap_size = m_vector.size();
|
|
||||||
|
|
||||||
int l = Left(i);
|
|
||||||
int r = Right(i);
|
|
||||||
|
|
||||||
int largest;
|
|
||||||
if (l < heap_size && HeapVal(base, l) > HeapVal(base, i)) {
|
|
||||||
largest = l;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
largest = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r < heap_size && HeapVal(base, r) > HeapVal(base, largest)) {
|
|
||||||
largest = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (largest != i) {
|
|
||||||
// exchange i and largest
|
|
||||||
Swap(base, i, largest);
|
|
||||||
DownHeap(base, largest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
UpHeap(
|
|
||||||
HeapType *base,
|
|
||||||
int i
|
|
||||||
) {
|
|
||||||
|
|
||||||
// swap parents untill it's found a place in the heap < it's parent or
|
|
||||||
// top of heap
|
|
||||||
|
|
||||||
while (i > 0) {
|
|
||||||
int p = Parent(i);
|
|
||||||
if (HeapVal(base, i) < HeapVal(base, p)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Swap(base, p, i);
|
|
||||||
i = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,127 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file container/intern/CTR_List.cpp
|
|
||||||
* \ingroup ctr
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "CTR_List.h"
|
|
||||||
|
|
||||||
|
|
||||||
CTR_Link::CTR_Link() :
|
|
||||||
m_next(0),
|
|
||||||
m_prev(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CTR_Link::CTR_Link(CTR_Link *next, CTR_Link *prev) :
|
|
||||||
m_next(next),
|
|
||||||
m_prev(prev)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CTR_Link *
|
|
||||||
CTR_Link::getNext() const
|
|
||||||
{
|
|
||||||
return m_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
CTR_Link *
|
|
||||||
CTR_Link::getPrev() const
|
|
||||||
{
|
|
||||||
return m_prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CTR_Link::isHead() const
|
|
||||||
{
|
|
||||||
return m_prev == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
CTR_Link::isTail() const
|
|
||||||
{
|
|
||||||
return m_next == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CTR_Link::insertBefore(CTR_Link *link)
|
|
||||||
{
|
|
||||||
m_next = link;
|
|
||||||
m_prev = link->m_prev;
|
|
||||||
m_next->m_prev = this;
|
|
||||||
m_prev->m_next = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CTR_Link::insertAfter(CTR_Link *link)
|
|
||||||
{
|
|
||||||
m_next = link->m_next;
|
|
||||||
m_prev = link;
|
|
||||||
m_next->m_prev = this;
|
|
||||||
m_prev->m_next = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CTR_Link::remove()
|
|
||||||
{
|
|
||||||
m_next->m_prev = m_prev;
|
|
||||||
m_prev->m_next = m_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CTR_List::CTR_List() :
|
|
||||||
m_head(&m_tail, 0),
|
|
||||||
m_tail(0, &m_head)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CTR_Link *
|
|
||||||
CTR_List:: getHead() const
|
|
||||||
{
|
|
||||||
return m_head.getNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
CTR_Link *
|
|
||||||
CTR_List::getTail() const
|
|
||||||
{
|
|
||||||
return m_tail.getPrev();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CTR_List::addHead(CTR_Link *link)
|
|
||||||
{
|
|
||||||
link->insertAfter(&m_head);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CTR_List::addTail(CTR_Link *link)
|
|
||||||
{
|
|
||||||
link->insertBefore(&m_tail);
|
|
||||||
}
|
|
||||||
|
|
@@ -1,63 +0,0 @@
|
|||||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
#
|
|
||||||
# The Original Code is Copyright (C) 2006, Blender Foundation
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# The Original Code is: all of this file.
|
|
||||||
#
|
|
||||||
# Contributor(s): Jacques Beaurain.
|
|
||||||
#
|
|
||||||
# ***** END GPL LICENSE BLOCK *****
|
|
||||||
|
|
||||||
set(INC
|
|
||||||
.
|
|
||||||
../container
|
|
||||||
../guardedalloc
|
|
||||||
../memutil
|
|
||||||
../moto/include
|
|
||||||
)
|
|
||||||
|
|
||||||
set(INC_SYS
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
set(SRC
|
|
||||||
intern/LOD_EdgeCollapser.cpp
|
|
||||||
intern/LOD_ExternNormalEditor.cpp
|
|
||||||
intern/LOD_FaceNormalEditor.cpp
|
|
||||||
intern/LOD_ManMesh2.cpp
|
|
||||||
intern/LOD_MeshPrimitives.cpp
|
|
||||||
intern/LOD_QSDecimator.cpp
|
|
||||||
intern/LOD_QuadricEditor.cpp
|
|
||||||
intern/LOD_decimation.cpp
|
|
||||||
|
|
||||||
extern/LOD_decimation.h
|
|
||||||
intern/LOD_DecimationClass.h
|
|
||||||
intern/LOD_EdgeCollapser.h
|
|
||||||
intern/LOD_ExternBufferEditor.h
|
|
||||||
intern/LOD_ExternNormalEditor.h
|
|
||||||
intern/LOD_FaceNormalEditor.h
|
|
||||||
intern/LOD_ManMesh2.h
|
|
||||||
intern/LOD_MeshBounds.h
|
|
||||||
intern/LOD_MeshException.h
|
|
||||||
intern/LOD_MeshPrimitives.h
|
|
||||||
intern/LOD_QSDecimator.h
|
|
||||||
intern/LOD_Quadric.h
|
|
||||||
intern/LOD_QuadricEditor.h
|
|
||||||
)
|
|
||||||
|
|
||||||
blender_add_lib(bf_intern_decimate "${SRC}" "${INC}" "${INC_SYS}")
|
|
@@ -1,8 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
Import ('env')
|
|
||||||
|
|
||||||
sources = env.Glob('intern/*.cpp')
|
|
||||||
|
|
||||||
incs = '. ../moto/include ../container ../memutil ../guardedalloc'
|
|
||||||
|
|
||||||
env.BlenderLib ('bf_intern_decimate', sources, Split(incs) , [], libtype=['core', 'player'], priority = [200, 100] )
|
|
117
intern/decimation/extern/LOD_decimation.h
vendored
117
intern/decimation/extern/LOD_decimation.h
vendored
@@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/extern/LOD_decimation.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
* @author Laurence Bourn
|
|
||||||
* @date 6/7/2001
|
|
||||||
*
|
|
||||||
* This is the external interface for the decimation module.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __LOD_DECIMATION_H__
|
|
||||||
#define __LOD_DECIMATION_H__
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* External decimation structure
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct LOD_Decimation_Info {
|
|
||||||
float * vertex_buffer;
|
|
||||||
float * vertex_normal_buffer;
|
|
||||||
int * triangle_index_buffer;
|
|
||||||
int vertex_num;
|
|
||||||
int face_num;
|
|
||||||
void * intern;
|
|
||||||
} LOD_Decimation_Info;
|
|
||||||
|
|
||||||
typedef LOD_Decimation_Info* LOD_Decimation_InfoPtr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create internal mesh representation from
|
|
||||||
* LOD_Decimation_Info structure.
|
|
||||||
* @return 1 on successful loading
|
|
||||||
* @return 0 on failure
|
|
||||||
* @warning This should be changed to return an enumeration
|
|
||||||
* detailing the error encountered
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern int LOD_LoadMesh(LOD_Decimation_InfoPtr info);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate and Compute internal data strucures required for
|
|
||||||
* decimation.
|
|
||||||
* @return 1 on successful computation of data
|
|
||||||
* @return 0 on failure
|
|
||||||
* @warning This should be changed to return an enumeration
|
|
||||||
* detailing the error encountered
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern int LOD_PreprocessMesh(LOD_Decimation_InfoPtr info);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Once both the stages above have been completed
|
|
||||||
* this function collapses a single edge in the mesh.
|
|
||||||
* The LOD_Decimation_Info structure is updated
|
|
||||||
* to represent the new mesh.
|
|
||||||
* @return 1 if an edge was collapsed.
|
|
||||||
* @return 0 if no suitable edge was found to be collapsable
|
|
||||||
* You should stop calling this method in this case
|
|
||||||
* @warning Do not expect that the order of polygons, vertices or
|
|
||||||
* vertex normals will be preserved by this operation. This function
|
|
||||||
* returns a packed array of polygons and vertices and so necessarily
|
|
||||||
* the order will be different. This means you should not expect to
|
|
||||||
* find the same polygon in the same place in the polygon array after
|
|
||||||
* this function has been called.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern int LOD_CollapseEdge(LOD_Decimation_InfoPtr info);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free any memory the decimation process used
|
|
||||||
* during the decimation process
|
|
||||||
* @return 1 if internal data successfully freed
|
|
||||||
* @return 0 if no data was freed
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern int LOD_FreeDecimationData(LOD_Decimation_InfoPtr);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __LOD_DECIMATION_H__
|
|
||||||
|
|
@@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_DecimationClass.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LOD_DECIMATIONCLASS_H__
|
|
||||||
#define __LOD_DECIMATIONCLASS_H__
|
|
||||||
|
|
||||||
#include "MEM_SmartPtr.h"
|
|
||||||
#include "MEM_NonCopyable.h"
|
|
||||||
|
|
||||||
#include "LOD_ManMesh2.h"
|
|
||||||
#include "LOD_QSDecimator.h"
|
|
||||||
#include "LOD_ExternNormalEditor.h"
|
|
||||||
#include "../extern/LOD_decimation.h"
|
|
||||||
#include "LOD_ExternBufferEditor.h"
|
|
||||||
|
|
||||||
|
|
||||||
class LOD_DecimationClass : public MEM_NonCopyable
|
|
||||||
{
|
|
||||||
public :
|
|
||||||
|
|
||||||
enum {
|
|
||||||
e_not_loaded,
|
|
||||||
e_loaded,
|
|
||||||
e_preprocessed
|
|
||||||
} m_e_decimation_state;
|
|
||||||
|
|
||||||
|
|
||||||
static
|
|
||||||
LOD_DecimationClass *
|
|
||||||
New(
|
|
||||||
LOD_Decimation_InfoPtr extern_info
|
|
||||||
) {
|
|
||||||
// create everything
|
|
||||||
|
|
||||||
MEM_SmartPtr<LOD_DecimationClass> output(new LOD_DecimationClass());
|
|
||||||
MEM_SmartPtr<LOD_ManMesh2> mesh(LOD_ManMesh2::New());
|
|
||||||
MEM_SmartPtr<LOD_ExternBufferEditor> extern_editor(LOD_ExternBufferEditor::New(extern_info));
|
|
||||||
|
|
||||||
if (mesh == NULL || extern_editor == NULL) return NULL;
|
|
||||||
MEM_SmartPtr<LOD_ExternNormalEditor> normals(LOD_ExternNormalEditor::New(extern_info,mesh.Ref()));
|
|
||||||
|
|
||||||
if (normals == NULL) return NULL;
|
|
||||||
MEM_SmartPtr<LOD_QSDecimator> decimator(LOD_QSDecimator::New(
|
|
||||||
mesh.Ref(),
|
|
||||||
normals.Ref(),
|
|
||||||
extern_editor.Ref()
|
|
||||||
));
|
|
||||||
if (decimator == NULL || output == NULL) return NULL;
|
|
||||||
|
|
||||||
output->m_mesh = mesh.Release();
|
|
||||||
output->m_decimator = decimator.Release();
|
|
||||||
output->m_normals = normals.Release();
|
|
||||||
output->m_extern_editor = extern_editor.Release();
|
|
||||||
|
|
||||||
return output.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
LOD_ManMesh2 &
|
|
||||||
Mesh(
|
|
||||||
){
|
|
||||||
return m_mesh.Ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
LOD_QSDecimator &
|
|
||||||
Decimator(
|
|
||||||
) {
|
|
||||||
return m_decimator.Ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
LOD_ExternNormalEditor &
|
|
||||||
FaceEditor(
|
|
||||||
){
|
|
||||||
return m_normals.Ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
LOD_DecimationClass(
|
|
||||||
) : m_e_decimation_state(e_not_loaded) {
|
|
||||||
};
|
|
||||||
|
|
||||||
MEM_SmartPtr<LOD_ManMesh2> m_mesh;
|
|
||||||
MEM_SmartPtr<LOD_QSDecimator> m_decimator;
|
|
||||||
MEM_SmartPtr<LOD_ExternNormalEditor> m_normals;
|
|
||||||
MEM_SmartPtr<LOD_ExternBufferEditor> m_extern_editor;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,410 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_EdgeCollapser.cpp
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "LOD_EdgeCollapser.h"
|
|
||||||
|
|
||||||
#include "LOD_ManMesh2.h"
|
|
||||||
#include "CTR_TaggedSetOps.h"
|
|
||||||
#include <algorithm>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
|
|
||||||
LOD_EdgeCollapser *
|
|
||||||
LOD_EdgeCollapser::
|
|
||||||
New(
|
|
||||||
){
|
|
||||||
return new LOD_EdgeCollapser();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_EdgeCollapser::
|
|
||||||
TJunctionTest(
|
|
||||||
LOD_ManMesh2 &mesh,
|
|
||||||
vector<LOD_EdgeInd> &e_v0v1,
|
|
||||||
LOD_EdgeInd collapse_edge
|
|
||||||
){
|
|
||||||
|
|
||||||
// we need to copy the edges in e_v0v1 from the mesh
|
|
||||||
// into a new buffer -> we are going to modify them
|
|
||||||
|
|
||||||
int original_size = e_v0v1.size();
|
|
||||||
if (original_size == 0) return true;
|
|
||||||
|
|
||||||
vector<LOD_Edge> &edge_set = mesh.EdgeSet();
|
|
||||||
|
|
||||||
LOD_VertexInd c_v0 = edge_set[collapse_edge].m_verts[0];
|
|
||||||
LOD_VertexInd c_v1 = edge_set[collapse_edge].m_verts[1];
|
|
||||||
|
|
||||||
vector<LOD_Edge> temp_edges;
|
|
||||||
temp_edges.reserve(e_v0v1.size());
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd>::iterator edge_it = e_v0v1.begin();
|
|
||||||
vector<LOD_EdgeInd>::const_iterator edge_end = e_v0v1.end();
|
|
||||||
|
|
||||||
for (;edge_it != edge_end; ++edge_it) {
|
|
||||||
temp_edges.push_back(edge_set[*edge_it]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// in the copied edges replace all instances of c_v0 with c_v1
|
|
||||||
|
|
||||||
vector<LOD_Edge>::iterator e_it = temp_edges.begin();
|
|
||||||
vector<LOD_Edge>::const_iterator e_it_end = temp_edges.end();
|
|
||||||
|
|
||||||
for (; e_it != e_it_end; ++e_it) {
|
|
||||||
|
|
||||||
if (e_it->m_verts[0] == c_v0) {
|
|
||||||
e_it->m_verts[0] = c_v1;
|
|
||||||
}
|
|
||||||
if (e_it->m_verts[1] == c_v0) {
|
|
||||||
e_it->m_verts[1] = c_v1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// normalize the edge
|
|
||||||
if (int(e_it->m_verts[0]) > int(e_it->m_verts[1])) {
|
|
||||||
LOD_EdgeInd temp = e_it->m_verts[0];
|
|
||||||
e_it->m_verts[0] = e_it->m_verts[1];
|
|
||||||
e_it->m_verts[1] = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort the edges using the edge less functional
|
|
||||||
|
|
||||||
sort(temp_edges.begin(),temp_edges.end(),LOD_EdgeCollapser::less());
|
|
||||||
// count the unique edges.
|
|
||||||
|
|
||||||
e_it = temp_edges.begin();
|
|
||||||
e_it_end = temp_edges.end();
|
|
||||||
|
|
||||||
int coincedent_edges = 0;
|
|
||||||
|
|
||||||
vector<LOD_Edge>::const_iterator last_edge = e_it;
|
|
||||||
++e_it;
|
|
||||||
|
|
||||||
for (; e_it != e_it_end; ++e_it) {
|
|
||||||
|
|
||||||
if ((e_it->m_verts[0] == last_edge->m_verts[0]) &&
|
|
||||||
(e_it->m_verts[1] == last_edge->m_verts[1])
|
|
||||||
) {
|
|
||||||
++coincedent_edges;
|
|
||||||
}
|
|
||||||
last_edge = e_it;
|
|
||||||
}
|
|
||||||
|
|
||||||
// now if the collapse edge is a boundary edges
|
|
||||||
// then we are alloved at most one coincedent edge
|
|
||||||
|
|
||||||
// otherwise at most 2 coincedent edges
|
|
||||||
|
|
||||||
if (edge_set[collapse_edge].BoundaryEdge()) {
|
|
||||||
return (coincedent_edges > 1);
|
|
||||||
} else {
|
|
||||||
return (coincedent_edges > 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_EdgeCollapser::
|
|
||||||
CollapseEdge(
|
|
||||||
LOD_EdgeInd ei,
|
|
||||||
LOD_ManMesh2 &mesh,
|
|
||||||
vector<LOD_EdgeInd> & degenerate_edges,
|
|
||||||
vector<LOD_FaceInd> & degenerate_faces,
|
|
||||||
vector<LOD_VertexInd> & degenerate_vertices,
|
|
||||||
vector<LOD_EdgeInd> & new_edges,
|
|
||||||
vector<LOD_FaceInd> & update_faces,
|
|
||||||
vector<LOD_VertexInd> & update_vertices
|
|
||||||
){
|
|
||||||
|
|
||||||
vector<LOD_Vertex> &verts = mesh.VertexSet();
|
|
||||||
vector<LOD_Edge> &edges = mesh.EdgeSet();
|
|
||||||
vector<LOD_TriFace> &faces = mesh.FaceSet();
|
|
||||||
|
|
||||||
// shouldn't do this (use mesh interface instead!)
|
|
||||||
LOD_VertexInd v0_ind = edges[ei].m_verts[0];
|
|
||||||
LOD_VertexInd v1_ind = edges[ei].m_verts[1];
|
|
||||||
#if 0
|
|
||||||
LOD_Vertex &v0 = verts[v0_ind];
|
|
||||||
LOD_Vertex &v1 = verts[v1_ind];
|
|
||||||
#endif
|
|
||||||
vector<vector<LOD_EdgeInd> > e_v01(2);
|
|
||||||
e_v01[0].reserve(32);
|
|
||||||
e_v01[1].reserve(32);
|
|
||||||
|
|
||||||
mesh.VertexEdges(v0_ind,e_v01[0]);
|
|
||||||
mesh.VertexEdges(v1_ind,e_v01[1]);
|
|
||||||
|
|
||||||
|
|
||||||
// compute the union of e_v0 and e_v1 -> this is the degenerate edges of the collapse
|
|
||||||
// we remove old edges and replace edges inside the collapse zone with new ones
|
|
||||||
|
|
||||||
CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Union(e_v01,edges,degenerate_edges);
|
|
||||||
|
|
||||||
vector< vector<LOD_FaceInd> > p_v01(2);
|
|
||||||
p_v01[0].reserve(32);
|
|
||||||
p_v01[1].reserve(32);
|
|
||||||
|
|
||||||
mesh.VertexFaces(v0_ind,p_v01[0]);
|
|
||||||
mesh.VertexFaces(v1_ind,p_v01[1]);
|
|
||||||
|
|
||||||
// compute the union of p_v0 anf p_v1
|
|
||||||
vector<LOD_FaceInd> p_v0v1;
|
|
||||||
p_v0v1.reserve(32);
|
|
||||||
|
|
||||||
CTR_TaggedSetOps<LOD_FaceInd,LOD_TriFace>::Union(p_v01,faces,p_v0v1);
|
|
||||||
|
|
||||||
// compute the union of all the edges in p_v0v1 this is the collapse zone
|
|
||||||
|
|
||||||
vector<vector<LOD_EdgeInd> > e_input_vectors(p_v0v1.size());
|
|
||||||
|
|
||||||
vector<LOD_FaceInd>::iterator p_v0v1_end = p_v0v1.end();
|
|
||||||
vector<LOD_FaceInd>::iterator p_v0v1_start = p_v0v1.begin();
|
|
||||||
|
|
||||||
vector<vector<LOD_FaceInd> >::iterator vector_insert_it = e_input_vectors.begin();
|
|
||||||
|
|
||||||
for (;p_v0v1_start != p_v0v1_end; ++p_v0v1_start , ++vector_insert_it) {
|
|
||||||
mesh.FaceEdges(*p_v0v1_start,*vector_insert_it);
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd> collapse_zone;
|
|
||||||
collapse_zone.reserve(32);
|
|
||||||
|
|
||||||
CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Union(e_input_vectors,edges,collapse_zone);
|
|
||||||
|
|
||||||
// compute the ring edges = collpase_zone - e_v0v1
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd> edge_ring;
|
|
||||||
edge_ring.reserve(32);
|
|
||||||
|
|
||||||
CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::Difference(collapse_zone,degenerate_edges,edges,edge_ring);
|
|
||||||
|
|
||||||
// T Junction test
|
|
||||||
//////////////////
|
|
||||||
// At this point we check to see if any of the polygons
|
|
||||||
// in p_v0v1 are coninceddent - this leads
|
|
||||||
// to errors later on if we try and insert a polygon
|
|
||||||
// into the mesh to an edge which already has 2 polygons.
|
|
||||||
|
|
||||||
// not that t junctions occur naturally from edge collapses
|
|
||||||
// and are not just the result of coincedent polygons
|
|
||||||
// for example consider collapsing an edge that forms part
|
|
||||||
// of a triangular bottle neck.
|
|
||||||
|
|
||||||
// Really we need to make sure that we don't create t-junctions.
|
|
||||||
|
|
||||||
// I think that a sufficient test is to check the number of
|
|
||||||
// coincedent edge pairs after a collapse. If it is more than 2
|
|
||||||
// then collapsing the edge may result in an undeleted edge
|
|
||||||
// sharing more than 2 polygons. This test probably is too
|
|
||||||
// restictive though.
|
|
||||||
|
|
||||||
// To perform this test we need to make a copy of the edges
|
|
||||||
// in e_v0v1. We then apply the contraction to these edge
|
|
||||||
// copies. Sort them using a function that places coincedent
|
|
||||||
// edges next to each other. And then count the number
|
|
||||||
// of coincedent pairs.
|
|
||||||
|
|
||||||
// Of course we have to do this test before we change any of the
|
|
||||||
// mesh -> so we can back out safely.
|
|
||||||
|
|
||||||
if (TJunctionTest(mesh,degenerate_edges,ei)) return false;
|
|
||||||
|
|
||||||
// Compute the set of possibly degenerate vertices
|
|
||||||
// this is the union of all the vertices of polygons
|
|
||||||
// of v0 and v1
|
|
||||||
|
|
||||||
vector<LOD_FaceInd>::iterator face_it = p_v0v1.begin();
|
|
||||||
vector<LOD_FaceInd>::const_iterator face_end = p_v0v1.end();
|
|
||||||
|
|
||||||
|
|
||||||
vector<vector<LOD_VertexInd> > p_v0v1_vertices(p_v0v1.size());
|
|
||||||
|
|
||||||
for (int i = 0; face_it != face_end; ++face_it, ++i) {
|
|
||||||
mesh.FaceVertices(*face_it,p_v0v1_vertices[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<LOD_VertexInd> vertex_ring;
|
|
||||||
vertex_ring.reserve(32);
|
|
||||||
|
|
||||||
CTR_TaggedSetOps<LOD_VertexInd,LOD_Vertex>::Union(p_v0v1_vertices,verts,vertex_ring);
|
|
||||||
|
|
||||||
// remove all the internal edges e_v0v1 from the mesh.
|
|
||||||
// for each edge remove the egde from it's vertices edge lists.
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd>::iterator edge_it = degenerate_edges.begin();
|
|
||||||
vector<LOD_EdgeInd>::const_iterator edge_end = degenerate_edges.end();
|
|
||||||
|
|
||||||
for (; !(edge_it == edge_end); ++edge_it) {
|
|
||||||
|
|
||||||
LOD_EdgeInd ed = (*edge_it);
|
|
||||||
LOD_Edge & edge = edges[ed];//*edge_it];
|
|
||||||
|
|
||||||
verts[edge.m_verts[0]].RemoveEdge(ed);
|
|
||||||
verts[edge.m_verts[1]].RemoveEdge(ed);
|
|
||||||
}
|
|
||||||
|
|
||||||
// we postpone deletion of the internal edges untill the end
|
|
||||||
// this is because deleting edges invalidates all of the
|
|
||||||
// EdgeInd vectors above.
|
|
||||||
|
|
||||||
|
|
||||||
// now untie all the polygons in p_v0v1 from the edge ring
|
|
||||||
|
|
||||||
// select all polygons in p_v0v1
|
|
||||||
|
|
||||||
face_it = p_v0v1.begin();
|
|
||||||
face_end = p_v0v1.end();
|
|
||||||
|
|
||||||
for (;face_it != face_end; ++face_it) {
|
|
||||||
faces[*face_it].SetSelectTag(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
edge_it = edge_ring.begin();
|
|
||||||
edge_end = edge_ring.end();
|
|
||||||
|
|
||||||
for (;edge_it != edge_end; ++edge_it) {
|
|
||||||
LOD_Edge & edge = edges[*edge_it];
|
|
||||||
|
|
||||||
// presumably all edges in edge_ring point to at least
|
|
||||||
// one polygon from p_v0v1
|
|
||||||
|
|
||||||
if (!edge.m_faces[0].IsEmpty() && faces[edge.m_faces[0]].SelectTag()) {
|
|
||||||
edge.m_faces[0].Invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!edge.m_faces[1].IsEmpty() && faces[edge.m_faces[1]].SelectTag()) {
|
|
||||||
edge.m_faces[1].Invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// deselect the faces
|
|
||||||
|
|
||||||
face_it = p_v0v1.begin();
|
|
||||||
face_end = p_v0v1.end();
|
|
||||||
|
|
||||||
for (;face_it != face_end; ++face_it) {
|
|
||||||
faces[*face_it].SetSelectTag(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// perform the edge collapse
|
|
||||||
////////////////////////////
|
|
||||||
|
|
||||||
// iterate through the polygons of p_v0 and replace the vertex
|
|
||||||
// index v0 with v1
|
|
||||||
|
|
||||||
face_it = p_v01[0].begin();
|
|
||||||
face_end = p_v01[0].end();
|
|
||||||
|
|
||||||
for (;face_it != face_end; ++face_it) {
|
|
||||||
faces[*face_it].SwapVertex(v0_ind,v1_ind);
|
|
||||||
}
|
|
||||||
|
|
||||||
face_it = p_v0v1.begin();
|
|
||||||
face_end = p_v0v1.end();
|
|
||||||
|
|
||||||
for (;face_it != face_end; ++face_it) {
|
|
||||||
if (faces[*face_it].Degenerate()) {
|
|
||||||
degenerate_faces.push_back(*face_it);
|
|
||||||
} else {
|
|
||||||
update_faces.push_back(*face_it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all the non-degenerate faces back into the
|
|
||||||
// mesh. Get a record of the new edges created in
|
|
||||||
// this process.
|
|
||||||
|
|
||||||
face_it = update_faces.begin();
|
|
||||||
face_end = update_faces.end();
|
|
||||||
|
|
||||||
for (;face_it != face_end; ++face_it) {
|
|
||||||
mesh.ConnectTriangle(*face_it,new_edges);
|
|
||||||
}
|
|
||||||
|
|
||||||
// degenerate ring primitives
|
|
||||||
/////////////////////////////
|
|
||||||
|
|
||||||
// we now need to examine each of the edges on the ring
|
|
||||||
// and work out if they are degenerate - if so we attempt
|
|
||||||
// to delete them -> add them to the other edges to delete
|
|
||||||
// in e_v0v1
|
|
||||||
|
|
||||||
edge_it = edge_ring.begin();
|
|
||||||
edge_end = edge_ring.end();
|
|
||||||
|
|
||||||
for (;edge_it != edge_end; ++edge_it) {
|
|
||||||
if (edges[*edge_it].Degenerate()) {
|
|
||||||
degenerate_edges.push_back(*edge_it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// do the same for the ring vertices.
|
|
||||||
|
|
||||||
vector<LOD_VertexInd>::iterator vertex_it = vertex_ring.begin();
|
|
||||||
vector<LOD_VertexInd>::const_iterator vertex_end = vertex_ring.end();
|
|
||||||
|
|
||||||
for (;vertex_it != vertex_end; ++vertex_it) {
|
|
||||||
if (verts[*vertex_it].Degenerate()) {
|
|
||||||
degenerate_vertices.push_back(*vertex_it);
|
|
||||||
} else {
|
|
||||||
update_vertices.push_back(*vertex_it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// we now know all the degenerate primitives
|
|
||||||
// and the new primitives we have inserted into the mesh
|
|
||||||
|
|
||||||
// We now delete the mesh primitives, mesh.DeleteXXXXXX() methods
|
|
||||||
// assume that the index vectors are sorted into descending order.
|
|
||||||
// we do that now.
|
|
||||||
|
|
||||||
sort(degenerate_edges.begin(),degenerate_edges.end(),LOD_EdgeInd::greater());
|
|
||||||
sort(degenerate_faces.begin(),degenerate_faces.end(),LOD_FaceInd::greater());
|
|
||||||
sort(degenerate_vertices.begin(),degenerate_vertices.end(),LOD_VertexInd::greater());
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
LOD_EdgeCollapser::
|
|
||||||
LOD_EdgeCollapser(
|
|
||||||
){
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
@@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_EdgeCollapser.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LOD_EDGECOLLAPSER_H__
|
|
||||||
#define __LOD_EDGECOLLAPSER_H__
|
|
||||||
|
|
||||||
// This is a helper class that collapses edges of a 2 - manifold mesh.
|
|
||||||
|
|
||||||
#include "LOD_MeshPrimitives.h"
|
|
||||||
#include "MEM_NonCopyable.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
class LOD_ManMesh2;
|
|
||||||
|
|
||||||
class LOD_EdgeCollapser
|
|
||||||
: public MEM_NonCopyable
|
|
||||||
{
|
|
||||||
|
|
||||||
public :
|
|
||||||
|
|
||||||
static
|
|
||||||
LOD_EdgeCollapser *
|
|
||||||
New(
|
|
||||||
);
|
|
||||||
|
|
||||||
// returns via arguments the set of modified
|
|
||||||
// verts,edges and faces.
|
|
||||||
|
|
||||||
bool
|
|
||||||
CollapseEdge(
|
|
||||||
LOD_EdgeInd ei,
|
|
||||||
LOD_ManMesh2 &mesh,
|
|
||||||
std::vector<LOD_EdgeInd> & degenerate_edges,
|
|
||||||
std::vector<LOD_FaceInd> & degenerate_faces,
|
|
||||||
std::vector<LOD_VertexInd> & degenerate_vertices,
|
|
||||||
std::vector<LOD_EdgeInd> & new_edges,
|
|
||||||
std::vector<LOD_FaceInd> & update_faces,
|
|
||||||
std::vector<LOD_VertexInd> & update_vertices
|
|
||||||
);
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
LOD_EdgeCollapser(
|
|
||||||
);
|
|
||||||
|
|
||||||
// Test to see if the result of collapsing the
|
|
||||||
// edge produces 2 junctions in the mesh i.e. where
|
|
||||||
// an edge is shared by more than 2 polygons
|
|
||||||
|
|
||||||
// We count the number of coincedent edge pairs that
|
|
||||||
// result from the collapse of collapse_edge.
|
|
||||||
|
|
||||||
// If collapse edge is a boundary edge then the number of
|
|
||||||
// coincedent pairs should be 1
|
|
||||||
// else it should be 2.
|
|
||||||
|
|
||||||
bool
|
|
||||||
TJunctionTest(
|
|
||||||
LOD_ManMesh2 &mesh,
|
|
||||||
std::vector<LOD_EdgeInd> &e_v0v1,
|
|
||||||
LOD_EdgeInd collapse_edge
|
|
||||||
);
|
|
||||||
|
|
||||||
// here's the definition of the sort function
|
|
||||||
// we use to determine coincedent edges
|
|
||||||
|
|
||||||
// assumes the edges are normalized i.e. m_verts[0] <= m_verts[1]
|
|
||||||
|
|
||||||
struct less : std::binary_function<LOD_Edge, LOD_Edge, bool> {
|
|
||||||
bool
|
|
||||||
operator()(
|
|
||||||
const LOD_Edge& a,
|
|
||||||
const LOD_Edge& b
|
|
||||||
) const {
|
|
||||||
|
|
||||||
if (int(a.m_verts[0]) == int(b.m_verts[0])) {
|
|
||||||
return (int(a.m_verts[1]) < int(b.m_verts[1]));
|
|
||||||
} else {
|
|
||||||
return (int(a.m_verts[0]) < int(b.m_verts[0]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,164 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_ExternBufferEditor.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
* Copyright (C) 2001 NaN Technologies B.V.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __LOD_EXTERNBUFFEREDITOR_H__
|
|
||||||
#define __LOD_EXTERNBUFFEREDITOR_H__
|
|
||||||
|
|
||||||
#include "LOD_MeshPrimitives.h"
|
|
||||||
#include <vector>
|
|
||||||
#include "LOD_ManMesh2.h"
|
|
||||||
#include "../extern/LOD_decimation.h"
|
|
||||||
|
|
||||||
|
|
||||||
// This class syncs external vertex/face buffers
|
|
||||||
// with the internal mesh representation during
|
|
||||||
// decimation.
|
|
||||||
|
|
||||||
class LOD_ExternBufferEditor
|
|
||||||
{
|
|
||||||
|
|
||||||
public :
|
|
||||||
|
|
||||||
static
|
|
||||||
LOD_ExternBufferEditor *
|
|
||||||
New(
|
|
||||||
LOD_Decimation_InfoPtr extern_info
|
|
||||||
){
|
|
||||||
if (extern_info == NULL) return NULL;
|
|
||||||
return new LOD_ExternBufferEditor(extern_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the external vertex buffer with vertices
|
|
||||||
// from the mesh
|
|
||||||
|
|
||||||
void
|
|
||||||
CopyModifiedVerts(
|
|
||||||
LOD_ManMesh2 & mesh,
|
|
||||||
const std::vector<LOD_VertexInd> & mod_vertices
|
|
||||||
){
|
|
||||||
|
|
||||||
std::vector<LOD_VertexInd>::const_iterator v_start = mod_vertices.begin();
|
|
||||||
std::vector<LOD_VertexInd>::const_iterator v_end = mod_vertices.end();
|
|
||||||
|
|
||||||
std::vector<LOD_Vertex> & mesh_verts = mesh.VertexSet();
|
|
||||||
|
|
||||||
float * const extern_vertex_ptr = m_extern_info->vertex_buffer;
|
|
||||||
|
|
||||||
for (; v_start != v_end; ++v_start) {
|
|
||||||
float * mod_vert = extern_vertex_ptr + int(*v_start)*3;
|
|
||||||
mesh_verts[*v_start].CopyPosition(mod_vert);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the external face buffer with faces from the mesh
|
|
||||||
|
|
||||||
void
|
|
||||||
CopyModifiedFaces(
|
|
||||||
LOD_ManMesh2 & mesh,
|
|
||||||
const std::vector<LOD_FaceInd> & mod_faces
|
|
||||||
){
|
|
||||||
|
|
||||||
std::vector<LOD_FaceInd>::const_iterator f_start = mod_faces.begin();
|
|
||||||
std::vector<LOD_FaceInd>::const_iterator f_end = mod_faces.end();
|
|
||||||
|
|
||||||
std::vector<LOD_TriFace> &mesh_faces = mesh.FaceSet();
|
|
||||||
|
|
||||||
int * const extern_face_ptr = m_extern_info->triangle_index_buffer;
|
|
||||||
|
|
||||||
for (; f_start != f_end; ++f_start) {
|
|
||||||
int *mod_face = extern_face_ptr + 3*int(*f_start);
|
|
||||||
mesh_faces[*f_start].CopyVerts(mod_face);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Copy the last vertex over the vertex specified by
|
|
||||||
// vi. Decrement the size of the vertex array
|
|
||||||
|
|
||||||
void
|
|
||||||
CopyBackVertex(
|
|
||||||
LOD_VertexInd vi
|
|
||||||
){
|
|
||||||
|
|
||||||
float * const extern_vertex_ptr = m_extern_info->vertex_buffer;
|
|
||||||
int * extern_vertex_num = &(m_extern_info->vertex_num);
|
|
||||||
|
|
||||||
float * last_external_vert = extern_vertex_ptr + 3*((*extern_vertex_num) - 1);
|
|
||||||
float * external_vert = extern_vertex_ptr + 3*int(vi);
|
|
||||||
|
|
||||||
external_vert[0] = last_external_vert[0];
|
|
||||||
external_vert[1] = last_external_vert[1];
|
|
||||||
external_vert[2] = last_external_vert[2];
|
|
||||||
|
|
||||||
*extern_vertex_num -=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the last face over the face specified by fi
|
|
||||||
// Decrement the size of the face array
|
|
||||||
|
|
||||||
void
|
|
||||||
CopyBackFace(
|
|
||||||
LOD_FaceInd fi
|
|
||||||
) {
|
|
||||||
int * const extern_face_ptr = m_extern_info->triangle_index_buffer;
|
|
||||||
int * extern_face_num = &(m_extern_info->face_num);
|
|
||||||
|
|
||||||
int * last_external_face = extern_face_ptr + 3*((*extern_face_num) -1);
|
|
||||||
int * external_face = extern_face_ptr + 3*int(fi);
|
|
||||||
external_face[0] = last_external_face[0];
|
|
||||||
external_face[1] = last_external_face[1];
|
|
||||||
external_face[2] = last_external_face[2];
|
|
||||||
|
|
||||||
*extern_face_num -=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
LOD_ExternBufferEditor(
|
|
||||||
LOD_Decimation_InfoPtr extern_info
|
|
||||||
) :
|
|
||||||
m_extern_info (extern_info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LOD_Decimation_InfoPtr const m_extern_info;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,264 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_ExternNormalEditor.cpp
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "LOD_ExternNormalEditor.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
|
|
||||||
LOD_ExternNormalEditor::
|
|
||||||
LOD_ExternNormalEditor(
|
|
||||||
LOD_Decimation_InfoPtr extern_info,
|
|
||||||
LOD_ManMesh2 &mesh
|
|
||||||
) :
|
|
||||||
m_mesh(mesh),
|
|
||||||
m_extern_info (extern_info)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LOD_ExternNormalEditor *
|
|
||||||
LOD_ExternNormalEditor::
|
|
||||||
New(
|
|
||||||
LOD_Decimation_InfoPtr extern_info,
|
|
||||||
LOD_ManMesh2 &mesh
|
|
||||||
){
|
|
||||||
if (extern_info == NULL) return NULL;
|
|
||||||
|
|
||||||
MEM_SmartPtr<LOD_ExternNormalEditor> output(new LOD_ExternNormalEditor(extern_info,mesh));
|
|
||||||
|
|
||||||
int face_num = mesh.FaceSet().size();
|
|
||||||
|
|
||||||
MEM_SmartPtr<vector<MT_Vector3> > normals(new vector<MT_Vector3>);
|
|
||||||
|
|
||||||
if (output == NULL ||
|
|
||||||
normals == NULL
|
|
||||||
) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
normals->reserve(face_num);
|
|
||||||
output->m_normals = normals.Release();
|
|
||||||
|
|
||||||
return output.Release();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ExternNormalEditor::
|
|
||||||
Remove(
|
|
||||||
std::vector<LOD_FaceInd> &sorted_faces
|
|
||||||
){
|
|
||||||
// assumes a collection of faces sorted in descending order .
|
|
||||||
|
|
||||||
vector<MT_Vector3> & normals = m_normals.Ref();
|
|
||||||
|
|
||||||
vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin();
|
|
||||||
vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end();
|
|
||||||
|
|
||||||
for (; it_start != it_end; ++it_start) {
|
|
||||||
|
|
||||||
if (normals.size() > 0) {
|
|
||||||
MT_Vector3 temp = normals[*it_start];
|
|
||||||
|
|
||||||
normals[*it_start] = normals.back();
|
|
||||||
normals.back() = temp;
|
|
||||||
|
|
||||||
normals.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME - throw exception
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ExternNormalEditor::
|
|
||||||
Add(
|
|
||||||
){
|
|
||||||
MT_Vector3 zero(0.0f,0.0f,0.0f);
|
|
||||||
m_normals->push_back(zero);
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ExternNormalEditor::
|
|
||||||
Update(
|
|
||||||
std::vector<LOD_FaceInd> &sorted_faces
|
|
||||||
){
|
|
||||||
vector<MT_Vector3> & normals = m_normals.Ref();
|
|
||||||
|
|
||||||
vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin();
|
|
||||||
vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end();
|
|
||||||
|
|
||||||
const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
|
|
||||||
|
|
||||||
for (; it_start != it_end; ++it_start) {
|
|
||||||
normals[*it_start] = ComputeNormal(faces[*it_start]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// vertex normals
|
|
||||||
/////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ExternNormalEditor::
|
|
||||||
RemoveVertexNormals(
|
|
||||||
std::vector<LOD_VertexInd> &sorted_verts
|
|
||||||
){
|
|
||||||
|
|
||||||
float * vertex_normals = m_extern_info->vertex_normal_buffer;
|
|
||||||
|
|
||||||
// assumption here that the vertexs normal number corresponds with
|
|
||||||
// the number of vertices !
|
|
||||||
|
|
||||||
int vertex_normal_num = m_extern_info->vertex_num;
|
|
||||||
|
|
||||||
vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin();
|
|
||||||
vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end();
|
|
||||||
|
|
||||||
for (; it_start != it_end; ++it_start) {
|
|
||||||
|
|
||||||
if (vertex_normal_num > 0) {
|
|
||||||
float * vertex_normal = vertex_normals + int(*it_start)*3;
|
|
||||||
float * last_vertex = vertex_normals + ((vertex_normal_num-1)*3);
|
|
||||||
|
|
||||||
MT_Vector3 last_v(last_vertex);
|
|
||||||
last_v.getValue(vertex_normal);
|
|
||||||
vertex_normal_num--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME - through exception
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ExternNormalEditor::
|
|
||||||
UpdateVertexNormals(
|
|
||||||
std::vector<LOD_VertexInd> &sorted_verts
|
|
||||||
){
|
|
||||||
float * vertex_normals = m_extern_info->vertex_normal_buffer;
|
|
||||||
|
|
||||||
vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin();
|
|
||||||
vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end();
|
|
||||||
|
|
||||||
for (; it_start != it_end; ++it_start) {
|
|
||||||
MT_Vector3 temp = ComputeVertexNormal(*it_start);
|
|
||||||
float * vertex_normal = vertex_normals + int(*it_start)*3;
|
|
||||||
temp.getValue(vertex_normal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Editor specific methods
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ExternNormalEditor::
|
|
||||||
BuildNormals(
|
|
||||||
) {
|
|
||||||
const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
|
|
||||||
vector<MT_Vector3> & normals = m_normals.Ref();
|
|
||||||
|
|
||||||
int face_num = faces.size();
|
|
||||||
int cur_face = 0;
|
|
||||||
|
|
||||||
for (; cur_face < face_num; ++cur_face) {
|
|
||||||
|
|
||||||
MT_Vector3 new_normal = ComputeNormal(faces[cur_face]);
|
|
||||||
normals.push_back(new_normal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const
|
|
||||||
MT_Vector3
|
|
||||||
LOD_ExternNormalEditor::
|
|
||||||
ComputeNormal(
|
|
||||||
const LOD_TriFace &face
|
|
||||||
) const {
|
|
||||||
|
|
||||||
const vector<LOD_Vertex> &verts = m_mesh.VertexSet();
|
|
||||||
|
|
||||||
MT_Vector3 vec1 =
|
|
||||||
verts[face.m_verts[1]].pos -
|
|
||||||
verts[face.m_verts[0]].pos;
|
|
||||||
|
|
||||||
MT_Vector3 vec2 =
|
|
||||||
verts[face.m_verts[2]].pos -
|
|
||||||
verts[face.m_verts[1]].pos;
|
|
||||||
|
|
||||||
vec1 = vec1.cross(vec2);
|
|
||||||
|
|
||||||
if (!vec1.fuzzyZero()) {
|
|
||||||
vec1.normalize();
|
|
||||||
return (vec1);
|
|
||||||
} else {
|
|
||||||
return (MT_Vector3(1.0,0,0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const
|
|
||||||
MT_Vector3
|
|
||||||
LOD_ExternNormalEditor::
|
|
||||||
ComputeVertexNormal(
|
|
||||||
const LOD_VertexInd v
|
|
||||||
) const {
|
|
||||||
|
|
||||||
// average the face normals surrounding this
|
|
||||||
// vertex and normalize
|
|
||||||
// vector<LOD_Vertex> &verts = m_mesh.VertexSet(); /*unused*/
|
|
||||||
const vector<MT_Vector3> & face_normals = m_normals.Ref();
|
|
||||||
|
|
||||||
vector<LOD_FaceInd> vertex_faces;
|
|
||||||
vertex_faces.reserve(32);
|
|
||||||
|
|
||||||
m_mesh.VertexFaces(v,vertex_faces);
|
|
||||||
|
|
||||||
MT_Vector3 normal(0,0,0);
|
|
||||||
|
|
||||||
vector<LOD_FaceInd>::const_iterator face_it = vertex_faces.begin();
|
|
||||||
vector<LOD_FaceInd>::const_iterator face_end = vertex_faces.end();
|
|
||||||
|
|
||||||
for (; face_it != face_end; ++face_it) {
|
|
||||||
normal += face_normals[*face_it];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!normal.fuzzyZero()) {
|
|
||||||
normal.normalize();
|
|
||||||
return (normal);
|
|
||||||
} else {
|
|
||||||
return (MT_Vector3(1.0,0,0));
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_ExternNormalEditor.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LOD_EXTERNNORMALEDITOR_H__
|
|
||||||
#define __LOD_EXTERNNORMALEDITOR_H__
|
|
||||||
|
|
||||||
#include "MEM_NonCopyable.h"
|
|
||||||
#include "LOD_ManMesh2.h"
|
|
||||||
#include "MT_Vector3.h"
|
|
||||||
#include "../extern/LOD_decimation.h"
|
|
||||||
|
|
||||||
class LOD_ExternNormalEditor : public MEM_NonCopyable
|
|
||||||
{
|
|
||||||
|
|
||||||
public :
|
|
||||||
|
|
||||||
// Creation
|
|
||||||
///////////
|
|
||||||
|
|
||||||
static
|
|
||||||
LOD_ExternNormalEditor *
|
|
||||||
New(
|
|
||||||
LOD_Decimation_InfoPtr,
|
|
||||||
LOD_ManMesh2 &mesh
|
|
||||||
);
|
|
||||||
|
|
||||||
// Property editor interface
|
|
||||||
////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
// Faces
|
|
||||||
////////
|
|
||||||
void
|
|
||||||
Remove(
|
|
||||||
std::vector<LOD_FaceInd> &sorted_faces
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
Add(
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
Update(
|
|
||||||
std::vector<LOD_FaceInd> &sorted_faces
|
|
||||||
);
|
|
||||||
|
|
||||||
const
|
|
||||||
std::vector<MT_Vector3> &
|
|
||||||
Normals(
|
|
||||||
) const {
|
|
||||||
return m_normals.Ref();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// vertex normals
|
|
||||||
/////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoveVertexNormals(
|
|
||||||
std::vector<LOD_VertexInd> &sorted_verts
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
UpdateVertexNormals(
|
|
||||||
std::vector<LOD_VertexInd> &sorted_verts
|
|
||||||
);
|
|
||||||
|
|
||||||
// Editor specific methods
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
BuildNormals(
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
MEM_SmartPtr<std::vector<MT_Vector3> > m_normals;
|
|
||||||
|
|
||||||
LOD_ManMesh2 &m_mesh;
|
|
||||||
LOD_Decimation_InfoPtr m_extern_info;
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
|
|
||||||
LOD_ExternNormalEditor(
|
|
||||||
LOD_Decimation_InfoPtr extern_info,
|
|
||||||
LOD_ManMesh2 &mesh
|
|
||||||
);
|
|
||||||
|
|
||||||
const
|
|
||||||
MT_Vector3
|
|
||||||
ComputeNormal(
|
|
||||||
const LOD_TriFace &face
|
|
||||||
) const;
|
|
||||||
|
|
||||||
const
|
|
||||||
MT_Vector3
|
|
||||||
ComputeVertexNormal (
|
|
||||||
const LOD_VertexInd vi
|
|
||||||
) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,291 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_FaceNormalEditor.cpp
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// implementation of LOD_FaceNormalEditor.h
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
#include "LOD_FaceNormalEditor.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
LOD_FaceNormalEditor::
|
|
||||||
LOD_FaceNormalEditor(
|
|
||||||
LOD_ManMesh2 & mesh
|
|
||||||
) : m_mesh(mesh) {
|
|
||||||
};
|
|
||||||
|
|
||||||
LOD_FaceNormalEditor *
|
|
||||||
LOD_FaceNormalEditor::
|
|
||||||
New(
|
|
||||||
LOD_ManMesh2 &mesh
|
|
||||||
){
|
|
||||||
// build a set of normals of the same size
|
|
||||||
// as the number of polys in the mesh
|
|
||||||
|
|
||||||
MEM_SmartPtr<LOD_FaceNormalEditor> output(new LOD_FaceNormalEditor(mesh));
|
|
||||||
|
|
||||||
int face_num = mesh.FaceSet().size();
|
|
||||||
|
|
||||||
MEM_SmartPtr<vector<MT_Vector3> > normals(new vector<MT_Vector3>);
|
|
||||||
MEM_SmartPtr<vector<MT_Vector3> > vertex_normals(new vector<MT_Vector3>);
|
|
||||||
|
|
||||||
if (output == NULL ||
|
|
||||||
normals == NULL
|
|
||||||
) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
normals->reserve(face_num);
|
|
||||||
vertex_normals->reserve(mesh.VertexSet().size());
|
|
||||||
output->m_normals = normals.Release();
|
|
||||||
output->m_vertex_normals = vertex_normals.Release();
|
|
||||||
|
|
||||||
return output.Release();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Property editor interface
|
|
||||||
////////////////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_FaceNormalEditor::
|
|
||||||
Remove(
|
|
||||||
std::vector<LOD_FaceInd> &sorted_faces
|
|
||||||
){
|
|
||||||
|
|
||||||
// assumes a collection of faces sorted in descending order .
|
|
||||||
|
|
||||||
vector<MT_Vector3> & normals = m_normals.Ref();
|
|
||||||
|
|
||||||
vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin();
|
|
||||||
vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end();
|
|
||||||
|
|
||||||
for (; it_start != it_end; ++it_start) {
|
|
||||||
|
|
||||||
if (normals.size() > 0) {
|
|
||||||
MT_Vector3 temp = normals[*it_start];
|
|
||||||
|
|
||||||
normals[*it_start] = normals.back();
|
|
||||||
normals.back() = temp;
|
|
||||||
|
|
||||||
normals.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME - through exception
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_FaceNormalEditor::
|
|
||||||
Add(
|
|
||||||
){
|
|
||||||
MT_Vector3 zero(0.0f,0.0f,0.0f);
|
|
||||||
m_normals->push_back(zero);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_FaceNormalEditor::
|
|
||||||
Update(
|
|
||||||
std::vector<LOD_FaceInd> &sorted_faces
|
|
||||||
){
|
|
||||||
|
|
||||||
vector<MT_Vector3> & normals = m_normals.Ref();
|
|
||||||
|
|
||||||
vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin();
|
|
||||||
vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end();
|
|
||||||
|
|
||||||
const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
|
|
||||||
|
|
||||||
for (; it_start != it_end; ++it_start) {
|
|
||||||
normals[*it_start] = ComputeNormal(faces[*it_start]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// vertex normals
|
|
||||||
/////////////////
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_FaceNormalEditor::
|
|
||||||
RemoveVertexNormals(
|
|
||||||
vector<LOD_VertexInd> &sorted_verts
|
|
||||||
){
|
|
||||||
vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref();
|
|
||||||
|
|
||||||
vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin();
|
|
||||||
vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end();
|
|
||||||
|
|
||||||
for (; it_start != it_end; ++it_start) {
|
|
||||||
|
|
||||||
if (vertex_normals.size() > 0) {
|
|
||||||
MT_Vector3 temp = vertex_normals[*it_start];
|
|
||||||
|
|
||||||
vertex_normals[*it_start] = vertex_normals.back();
|
|
||||||
vertex_normals.back() = temp;
|
|
||||||
|
|
||||||
vertex_normals.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME - through exception
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_FaceNormalEditor::
|
|
||||||
UpdateVertexNormals(
|
|
||||||
vector<LOD_VertexInd> &sorted_verts
|
|
||||||
){
|
|
||||||
vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref();
|
|
||||||
|
|
||||||
vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin();
|
|
||||||
vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end();
|
|
||||||
|
|
||||||
for (; it_start != it_end; ++it_start) {
|
|
||||||
vertex_normals[*it_start] = ComputeVertexNormal(*it_start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Editor specific methods
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_FaceNormalEditor::
|
|
||||||
BuildNormals(
|
|
||||||
){
|
|
||||||
|
|
||||||
const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
|
|
||||||
vector<MT_Vector3> & normals = m_normals.Ref();
|
|
||||||
|
|
||||||
int face_num = faces.size();
|
|
||||||
int cur_face = 0;
|
|
||||||
|
|
||||||
for (; cur_face < face_num; ++cur_face) {
|
|
||||||
|
|
||||||
MT_Vector3 new_normal = ComputeNormal(faces[cur_face]);
|
|
||||||
normals.push_back(new_normal);
|
|
||||||
}
|
|
||||||
// now build the vertex normals
|
|
||||||
|
|
||||||
vector<MT_Vector3> & vertex_normals = m_vertex_normals.Ref();
|
|
||||||
const vector<LOD_Vertex> &verts = m_mesh.VertexSet();
|
|
||||||
|
|
||||||
int vertex_num = verts.size();
|
|
||||||
int cur_vertex = 0;
|
|
||||||
|
|
||||||
for (; cur_vertex < vertex_num; ++cur_vertex) {
|
|
||||||
MT_Vector3 new_normal = ComputeVertexNormal(cur_vertex);
|
|
||||||
vertex_normals.push_back(new_normal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const
|
|
||||||
MT_Vector3
|
|
||||||
LOD_FaceNormalEditor::
|
|
||||||
ComputeNormal(
|
|
||||||
const LOD_TriFace &face
|
|
||||||
) const {
|
|
||||||
|
|
||||||
const vector<LOD_Vertex> &verts = m_mesh.VertexSet();
|
|
||||||
|
|
||||||
MT_Vector3 vec1 =
|
|
||||||
verts[face.m_verts[1]].pos -
|
|
||||||
verts[face.m_verts[0]].pos;
|
|
||||||
|
|
||||||
MT_Vector3 vec2 =
|
|
||||||
verts[face.m_verts[2]].pos -
|
|
||||||
verts[face.m_verts[1]].pos;
|
|
||||||
|
|
||||||
vec1 = vec1.cross(vec2);
|
|
||||||
|
|
||||||
if (!vec1.fuzzyZero()) {
|
|
||||||
vec1.normalize();
|
|
||||||
return (vec1);
|
|
||||||
} else {
|
|
||||||
return (MT_Vector3(1.0,0,0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const
|
|
||||||
MT_Vector3
|
|
||||||
LOD_FaceNormalEditor::
|
|
||||||
ComputeVertexNormal(
|
|
||||||
const LOD_VertexInd v
|
|
||||||
) const {
|
|
||||||
|
|
||||||
// average the face normals surrounding this
|
|
||||||
// vertex and normalize
|
|
||||||
const vector<MT_Vector3> & face_normals = m_normals.Ref();
|
|
||||||
|
|
||||||
vector<LOD_FaceInd> vertex_faces;
|
|
||||||
vertex_faces.reserve(32);
|
|
||||||
|
|
||||||
m_mesh.VertexFaces(v,vertex_faces);
|
|
||||||
|
|
||||||
MT_Vector3 normal(0,0,0);
|
|
||||||
|
|
||||||
vector<LOD_FaceInd>::const_iterator face_it = vertex_faces.begin();
|
|
||||||
vector<LOD_FaceInd>::const_iterator face_end = vertex_faces.end();
|
|
||||||
|
|
||||||
for (; face_it != face_end; ++face_it) {
|
|
||||||
normal += face_normals[*face_it];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!normal.fuzzyZero()) {
|
|
||||||
normal.normalize();
|
|
||||||
return (normal);
|
|
||||||
} else {
|
|
||||||
return (MT_Vector3(1.0,0,0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_FaceNormalEditor.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LOD_FACENORMALEDITOR_H__
|
|
||||||
#define __LOD_FACENORMALEDITOR_H__
|
|
||||||
|
|
||||||
#include "MEM_NonCopyable.h"
|
|
||||||
#include "LOD_ManMesh2.h"
|
|
||||||
#include "MT_Vector3.h"
|
|
||||||
|
|
||||||
|
|
||||||
class LOD_FaceNormalEditor : public MEM_NonCopyable
|
|
||||||
{
|
|
||||||
|
|
||||||
public :
|
|
||||||
|
|
||||||
// Creation
|
|
||||||
///////////
|
|
||||||
|
|
||||||
static
|
|
||||||
LOD_FaceNormalEditor *
|
|
||||||
New(
|
|
||||||
LOD_ManMesh2 &mesh
|
|
||||||
);
|
|
||||||
|
|
||||||
// Property editor interface
|
|
||||||
////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
// Faces
|
|
||||||
////////
|
|
||||||
void
|
|
||||||
Remove(
|
|
||||||
std::vector<LOD_FaceInd> &sorted_faces
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
Add(
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
Update(
|
|
||||||
std::vector<LOD_FaceInd> &sorted_faces
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// vertex normals
|
|
||||||
/////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
RemoveVertexNormals(
|
|
||||||
std::vector<LOD_VertexInd> &sorted_verts
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
UpdateVertexNormals(
|
|
||||||
std::vector<LOD_VertexInd> &sorted_verts
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const
|
|
||||||
std::vector<MT_Vector3> &
|
|
||||||
Normals(
|
|
||||||
) const {
|
|
||||||
return m_normals.Ref();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const
|
|
||||||
std::vector<MT_Vector3> &
|
|
||||||
VertexNormals(
|
|
||||||
) const {
|
|
||||||
return m_vertex_normals.Ref();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Editor specific methods
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
BuildNormals(
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
MEM_SmartPtr<std::vector<MT_Vector3> > m_normals;
|
|
||||||
MEM_SmartPtr<std::vector<MT_Vector3> > m_vertex_normals;
|
|
||||||
|
|
||||||
LOD_ManMesh2 &m_mesh;
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
|
|
||||||
LOD_FaceNormalEditor(LOD_ManMesh2 &mesh);
|
|
||||||
|
|
||||||
const
|
|
||||||
MT_Vector3
|
|
||||||
ComputeNormal(
|
|
||||||
const LOD_TriFace &face
|
|
||||||
) const;
|
|
||||||
|
|
||||||
const
|
|
||||||
MT_Vector3
|
|
||||||
ComputeVertexNormal (
|
|
||||||
const LOD_VertexInd vi
|
|
||||||
) const;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,618 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_ManMesh2.cpp
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "LOD_ManMesh2.h"
|
|
||||||
|
|
||||||
#include "MT_assert.h"
|
|
||||||
#include <algorithm>
|
|
||||||
#include "LOD_MeshException.h"
|
|
||||||
#include "CTR_TaggedSetOps.h"
|
|
||||||
#include "CTR_UHeap.h"
|
|
||||||
#include "LOD_ExternBufferEditor.h"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
LOD_ManMesh2::
|
|
||||||
LOD_ManMesh2(
|
|
||||||
) :
|
|
||||||
m_bbox_min(0,0,0),
|
|
||||||
m_bbox_max(0,0,0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LOD_ManMesh2 *
|
|
||||||
LOD_ManMesh2::
|
|
||||||
New(
|
|
||||||
){
|
|
||||||
MEM_SmartPtr<LOD_ManMesh2> output(new LOD_ManMesh2());
|
|
||||||
if (output == NULL) return NULL;
|
|
||||||
|
|
||||||
// build the vertex, edge and face sets.
|
|
||||||
|
|
||||||
MEM_SmartPtr<vector<LOD_Vertex> > verts(new vector<LOD_Vertex>);
|
|
||||||
MEM_SmartPtr<vector<LOD_TriFace> > faces(new vector<LOD_TriFace>);
|
|
||||||
MEM_SmartPtr<vector<LOD_Edge> > edges(new vector<LOD_Edge>);
|
|
||||||
|
|
||||||
if ((faces == NULL) || (edges == NULL) || (verts == NULL)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
output->m_verts = verts.Release();
|
|
||||||
output->m_faces = faces.Release();
|
|
||||||
output->m_edges = edges.Release();
|
|
||||||
|
|
||||||
return output.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
// take ownership of the vertices.
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_ManMesh2::
|
|
||||||
SetVertices(
|
|
||||||
MEM_SmartPtr<vector<LOD_Vertex> > verts
|
|
||||||
){
|
|
||||||
|
|
||||||
|
|
||||||
// take ownership of vertices
|
|
||||||
m_verts = verts;
|
|
||||||
|
|
||||||
// create a polygon and edge buffer of half the size
|
|
||||||
// and just use the automatic resizing feature of vector<>
|
|
||||||
// to worry about the dynamic array resizing
|
|
||||||
|
|
||||||
m_faces->clear();
|
|
||||||
m_edges->clear();
|
|
||||||
|
|
||||||
m_faces->reserve(m_verts->size()/2);
|
|
||||||
m_edges->reserve(m_verts->size()/2);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// add a triangle to the mesh
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
AddTriangle(
|
|
||||||
int verts[3]
|
|
||||||
) {
|
|
||||||
|
|
||||||
MT_assert(verts[0] < int(m_verts->size()));
|
|
||||||
MT_assert(verts[1] < int(m_verts->size()));
|
|
||||||
MT_assert(verts[2] < int(m_verts->size()));
|
|
||||||
|
|
||||||
LOD_TriFace face;
|
|
||||||
face.m_verts[0] = verts[0];
|
|
||||||
face.m_verts[1] = verts[1];
|
|
||||||
face.m_verts[2] = verts[2];
|
|
||||||
|
|
||||||
LOD_FaceInd face_index = m_faces->size();
|
|
||||||
|
|
||||||
m_faces->push_back(face);
|
|
||||||
|
|
||||||
// now work out if any of the directed edges or their
|
|
||||||
// companion edges exist already.
|
|
||||||
// We go through the edges associated with each of the given vertices
|
|
||||||
|
|
||||||
// the safest thing to do is iterate through each of the edge sets
|
|
||||||
// check against each of the 2 other triangle edges to see if they are there
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd> new_edges;
|
|
||||||
new_edges.reserve(3);
|
|
||||||
|
|
||||||
InsertEdge(verts[0],verts[1],face_index,new_edges);
|
|
||||||
InsertEdge(verts[1],verts[2],face_index,new_edges);
|
|
||||||
InsertEdge(verts[2],verts[0],face_index,new_edges);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds the index of any created edges to new_edges
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_ManMesh2::
|
|
||||||
InsertEdge(
|
|
||||||
const LOD_VertexInd v1,
|
|
||||||
const LOD_VertexInd v2,
|
|
||||||
const LOD_FaceInd f,
|
|
||||||
vector<LOD_EdgeInd> &new_edges
|
|
||||||
){
|
|
||||||
|
|
||||||
MT_assert(!v1.IsEmpty());
|
|
||||||
MT_assert(!v2.IsEmpty());
|
|
||||||
MT_assert(!f.IsEmpty());
|
|
||||||
|
|
||||||
vector<LOD_Vertex> &verts = VertexSet();
|
|
||||||
vector<LOD_Edge> &edges = EdgeSet();
|
|
||||||
|
|
||||||
LOD_EdgeInd e;
|
|
||||||
|
|
||||||
e = FindEdge(v1,v2);
|
|
||||||
|
|
||||||
if (e.IsEmpty()) {
|
|
||||||
// This edge does not exist -- make a new one
|
|
||||||
|
|
||||||
LOD_Edge temp_e;
|
|
||||||
temp_e.m_verts[0] = v1;
|
|
||||||
temp_e.m_verts[1] = v2;
|
|
||||||
|
|
||||||
e = m_edges->size();
|
|
||||||
|
|
||||||
// set the face ptr for this half-edge
|
|
||||||
temp_e.m_faces[0] = f;
|
|
||||||
|
|
||||||
m_edges->push_back(temp_e);
|
|
||||||
|
|
||||||
// add the edge index to it's vertices
|
|
||||||
|
|
||||||
verts[v1].AddEdge(e);
|
|
||||||
verts[v2].AddEdge(e);
|
|
||||||
|
|
||||||
new_edges.push_back(e);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// edge already exists
|
|
||||||
// insure that there is no polygon already
|
|
||||||
// attached to the other side of this edge
|
|
||||||
|
|
||||||
// swap the empty face pointer in edge with f
|
|
||||||
|
|
||||||
LOD_Edge &edge = edges[e];
|
|
||||||
|
|
||||||
edge.SwapFace(LOD_FaceInd::Empty(),f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
ConnectTriangle(
|
|
||||||
LOD_FaceInd fi,
|
|
||||||
std::vector<LOD_EdgeInd> & new_edges
|
|
||||||
){
|
|
||||||
|
|
||||||
vector<LOD_TriFace> &faces = FaceSet();
|
|
||||||
|
|
||||||
MT_assert(!faces[fi].Degenerate());
|
|
||||||
|
|
||||||
LOD_TriFace & face = faces[fi];
|
|
||||||
|
|
||||||
InsertEdge(face.m_verts[0],face.m_verts[1],fi,new_edges);
|
|
||||||
InsertEdge(face.m_verts[1],face.m_verts[2],fi,new_edges);
|
|
||||||
InsertEdge(face.m_verts[2],face.m_verts[0],fi,new_edges);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// geometry access
|
|
||||||
//////////////////
|
|
||||||
|
|
||||||
vector<LOD_Vertex> &
|
|
||||||
LOD_ManMesh2::
|
|
||||||
VertexSet(
|
|
||||||
) const {
|
|
||||||
return m_verts.Ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<LOD_TriFace> &
|
|
||||||
LOD_ManMesh2::
|
|
||||||
FaceSet(
|
|
||||||
) const {
|
|
||||||
return m_faces.Ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<LOD_Edge> &
|
|
||||||
LOD_ManMesh2::
|
|
||||||
EdgeSet(
|
|
||||||
) const {
|
|
||||||
return m_edges.Ref();
|
|
||||||
};
|
|
||||||
|
|
||||||
LOD_ManMesh2::
|
|
||||||
~LOD_ManMesh2(
|
|
||||||
){
|
|
||||||
//auto ptr takes care of vertex arrays etc.
|
|
||||||
}
|
|
||||||
|
|
||||||
LOD_EdgeInd
|
|
||||||
LOD_ManMesh2::
|
|
||||||
FindEdge(
|
|
||||||
const LOD_VertexInd v1,
|
|
||||||
const LOD_VertexInd v2
|
|
||||||
) {
|
|
||||||
|
|
||||||
vector<LOD_Vertex> &verts = VertexSet();
|
|
||||||
vector<LOD_Edge> &edges = EdgeSet();
|
|
||||||
|
|
||||||
LOD_Edge e;
|
|
||||||
e.m_verts[0] = v1;
|
|
||||||
e.m_verts[1] = v2;
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd> &v1_edges = verts[v1].m_edges;
|
|
||||||
vector<LOD_EdgeInd>::const_iterator v1_end = v1_edges.end();
|
|
||||||
vector<LOD_EdgeInd>::iterator v1_begin = v1_edges.begin();
|
|
||||||
|
|
||||||
for (; v1_begin != v1_end; ++v1_begin) {
|
|
||||||
if (edges[*v1_begin] == e) return *v1_begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
return LOD_EdgeInd::Empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// face queries
|
|
||||||
///////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
FaceVertices(
|
|
||||||
LOD_FaceInd fi,
|
|
||||||
vector<LOD_VertexInd> &output
|
|
||||||
){
|
|
||||||
const vector<LOD_TriFace> &faces = FaceSet();
|
|
||||||
const LOD_TriFace & f = faces[fi];
|
|
||||||
|
|
||||||
output.push_back(f.m_verts[0]);
|
|
||||||
output.push_back(f.m_verts[1]);
|
|
||||||
output.push_back(f.m_verts[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
FaceEdges(
|
|
||||||
LOD_FaceInd fi,
|
|
||||||
vector<LOD_EdgeInd> &output
|
|
||||||
){
|
|
||||||
const vector<LOD_TriFace> &faces = FaceSet();
|
|
||||||
vector<LOD_Edge> &edges = EdgeSet();
|
|
||||||
vector<LOD_Vertex> &verts = VertexSet();
|
|
||||||
|
|
||||||
const LOD_TriFace & f = faces[fi];
|
|
||||||
// intersect vertex edges
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd> & v0_edges = verts[f.m_verts[0]].m_edges;
|
|
||||||
vector<LOD_EdgeInd> & v1_edges = verts[f.m_verts[1]].m_edges;
|
|
||||||
vector<LOD_EdgeInd> & v2_edges = verts[f.m_verts[2]].m_edges;
|
|
||||||
|
|
||||||
CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v0_edges,v1_edges,edges,output);
|
|
||||||
CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v1_edges,v2_edges,edges,output);
|
|
||||||
CTR_TaggedSetOps<LOD_EdgeInd,LOD_Edge>::IntersectPair(v2_edges,v0_edges,edges,output);
|
|
||||||
|
|
||||||
MT_assert(output.size() == 3);
|
|
||||||
if (output.size() != 3) {
|
|
||||||
LOD_MeshException e(LOD_MeshException::e_non_manifold);
|
|
||||||
throw(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// edge queries
|
|
||||||
///////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
EdgeVertices(
|
|
||||||
LOD_EdgeInd ei,
|
|
||||||
vector<LOD_VertexInd> &output
|
|
||||||
){
|
|
||||||
const vector<LOD_Edge> &edges = EdgeSet();
|
|
||||||
const LOD_Edge & e = edges[ei];
|
|
||||||
|
|
||||||
output.push_back(e.m_verts[0]);
|
|
||||||
output.push_back(e.m_verts[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
EdgeFaces(
|
|
||||||
LOD_EdgeInd ei,
|
|
||||||
vector<LOD_FaceInd> &output
|
|
||||||
){
|
|
||||||
const vector<LOD_Edge> &edges = EdgeSet();
|
|
||||||
const LOD_Edge & e = edges[ei];
|
|
||||||
|
|
||||||
if (!e.m_faces[0].IsEmpty()) {
|
|
||||||
output.push_back(e.m_faces[0]);
|
|
||||||
}
|
|
||||||
if (!e.m_faces[1].IsEmpty()) {
|
|
||||||
output.push_back(e.m_faces[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// vertex queries
|
|
||||||
/////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
VertexEdges(
|
|
||||||
LOD_VertexInd vi,
|
|
||||||
vector<LOD_EdgeInd> &output
|
|
||||||
){
|
|
||||||
// iterate through the edges of v and push them onto the
|
|
||||||
// output
|
|
||||||
|
|
||||||
vector<LOD_Vertex> &verts = VertexSet();
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd> & v_edges = verts[vi].m_edges;
|
|
||||||
vector<LOD_EdgeInd>::iterator v_it = v_edges.begin();
|
|
||||||
|
|
||||||
for (; v_it != v_edges.end(); ++v_it) {
|
|
||||||
output.push_back(*v_it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
VertexFaces(
|
|
||||||
LOD_VertexInd vi,
|
|
||||||
vector<LOD_FaceInd> &output
|
|
||||||
){
|
|
||||||
const vector<LOD_Vertex> &verts = VertexSet();
|
|
||||||
vector<LOD_Edge> &edges = EdgeSet();
|
|
||||||
vector<LOD_TriFace> &faces = FaceSet();
|
|
||||||
|
|
||||||
const vector<LOD_EdgeInd> &v_edges = verts[vi].m_edges;
|
|
||||||
vector<LOD_EdgeInd>::const_iterator e_it = v_edges.begin();
|
|
||||||
|
|
||||||
for (; e_it != v_edges.end(); ++e_it) {
|
|
||||||
|
|
||||||
LOD_Edge &e = edges[*e_it];
|
|
||||||
|
|
||||||
if ((!e.m_faces[0].IsEmpty()) && (!faces[e.m_faces[0]].SelectTag())) {
|
|
||||||
output.push_back(e.m_faces[0]);
|
|
||||||
faces[e.m_faces[0]].SetSelectTag(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!e.m_faces[1].IsEmpty()) && (!faces[e.m_faces[1]].SelectTag())) {
|
|
||||||
output.push_back(e.m_faces[1]);
|
|
||||||
faces[e.m_faces[1]].SetSelectTag(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<LOD_FaceInd>::iterator f_it = output.begin();
|
|
||||||
|
|
||||||
for (; f_it != output.end(); ++f_it) {
|
|
||||||
faces[*f_it].SetSelectTag(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
SetBBox(
|
|
||||||
MT_Vector3 bbox_min,
|
|
||||||
MT_Vector3 bbox_max
|
|
||||||
){
|
|
||||||
m_bbox_min = bbox_min;
|
|
||||||
m_bbox_max = bbox_max;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
SC_TriFace(
|
|
||||||
LOD_FaceInd f
|
|
||||||
){
|
|
||||||
LOD_TriFace face = (*m_faces)[f];
|
|
||||||
|
|
||||||
// check for unique vertices
|
|
||||||
|
|
||||||
if (
|
|
||||||
(face.m_verts[0] == face.m_verts[1]) ||
|
|
||||||
(face.m_verts[1] == face.m_verts[2]) ||
|
|
||||||
(face.m_verts[2] == face.m_verts[0])
|
|
||||||
) {
|
|
||||||
MT_assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
SC_EdgeList(
|
|
||||||
LOD_VertexInd v
|
|
||||||
){
|
|
||||||
vector<LOD_Edge> &edges = EdgeSet();
|
|
||||||
vector<LOD_Vertex> &verts = VertexSet();
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd>::iterator e_it = verts[v].m_edges.begin();
|
|
||||||
|
|
||||||
for (;e_it != verts[v].m_edges.end(); ++e_it) {
|
|
||||||
MT_assert( (edges[*e_it].m_verts[0] == v) || (edges[*e_it].m_verts[1] == v));
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
DeleteVertex(
|
|
||||||
LOD_ExternBufferEditor & extern_editor,
|
|
||||||
LOD_VertexInd v
|
|
||||||
){
|
|
||||||
|
|
||||||
vector<LOD_Edge> &edges = EdgeSet();
|
|
||||||
vector<LOD_Vertex> &verts = VertexSet();
|
|
||||||
vector<LOD_TriFace> &faces = FaceSet();
|
|
||||||
|
|
||||||
// need to update all the edge and polygons pointing to
|
|
||||||
// the last vertex in m_verts
|
|
||||||
|
|
||||||
if (verts.size() == 1) {
|
|
||||||
verts.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOD_VertexInd last = LOD_VertexInd(size_t(verts.end() - verts.begin() - 1));
|
|
||||||
|
|
||||||
if (!(last == v)) {
|
|
||||||
|
|
||||||
// we asume that v is already disconnected
|
|
||||||
|
|
||||||
vector<LOD_FaceInd> v_faces;
|
|
||||||
vector<LOD_EdgeInd> v_edges;
|
|
||||||
|
|
||||||
v_faces.reserve(64);
|
|
||||||
v_edges.reserve(64);
|
|
||||||
|
|
||||||
VertexFaces(last,v_faces);
|
|
||||||
VertexEdges(last,v_edges);
|
|
||||||
|
|
||||||
// map the faces and edges to look at v
|
|
||||||
|
|
||||||
vector<LOD_FaceInd>::iterator face_it = v_faces.begin();
|
|
||||||
|
|
||||||
for(; face_it != v_faces.end(); ++face_it) {
|
|
||||||
faces[*face_it].SwapVertex(last,v);
|
|
||||||
}
|
|
||||||
vector<LOD_EdgeInd>::iterator edge_it = v_edges.begin();
|
|
||||||
|
|
||||||
for (; edge_it != v_edges.end(); ++edge_it) {
|
|
||||||
edges[*edge_it].SwapVertex(last,v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy the last vertex onto v and pop off the back.
|
|
||||||
|
|
||||||
verts[v] = verts[last];
|
|
||||||
|
|
||||||
// tidy external buffer
|
|
||||||
extern_editor.CopyModifiedFaces(*this,v_faces);
|
|
||||||
}
|
|
||||||
|
|
||||||
verts.pop_back();
|
|
||||||
extern_editor.CopyBackVertex(v);
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
DeleteEdge(
|
|
||||||
LOD_EdgeInd e,
|
|
||||||
CTR_UHeap<LOD_Edge> * heap
|
|
||||||
){
|
|
||||||
vector<LOD_Edge> &edges = EdgeSet();
|
|
||||||
vector<LOD_Vertex> &verts = VertexSet();
|
|
||||||
|
|
||||||
if (edges.size() == 1) {
|
|
||||||
edges.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOD_EdgeInd last = LOD_EdgeInd(size_t(edges.end() - edges.begin() - 1));
|
|
||||||
|
|
||||||
if (!(last == e)) {
|
|
||||||
vector<LOD_EdgeInd> e_verts;
|
|
||||||
e_verts.reserve(2);
|
|
||||||
EdgeVertices(last,e_verts);
|
|
||||||
// something is wrong if there arent two!
|
|
||||||
|
|
||||||
verts[e_verts[0]].SwapEdge(last,e);
|
|
||||||
verts[e_verts[1]].SwapEdge(last,e);
|
|
||||||
|
|
||||||
// edges[e] should already have been removed from the heap
|
|
||||||
|
|
||||||
MT_assert(edges[e].HeapPos() == -1);
|
|
||||||
|
|
||||||
edges[e] = edges[last];
|
|
||||||
// also have to swap there heap positions.!!!!!
|
|
||||||
|
|
||||||
heap->HeapVector()[edges[e].HeapPos()] = e;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
edges.pop_back();
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_ManMesh2::
|
|
||||||
DeleteFace(
|
|
||||||
LOD_ExternBufferEditor & extern_editor,
|
|
||||||
LOD_FaceInd f
|
|
||||||
){
|
|
||||||
|
|
||||||
vector<LOD_Edge> &edges = EdgeSet();
|
|
||||||
vector<LOD_TriFace> &faces = FaceSet();
|
|
||||||
|
|
||||||
if (faces.size() == 1) {
|
|
||||||
faces.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOD_FaceInd last = LOD_FaceInd(size_t (faces.end() - faces.begin() - 1));
|
|
||||||
|
|
||||||
if (!(last == f)) {
|
|
||||||
|
|
||||||
// we have to update the edges which point to the last
|
|
||||||
// face
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd> f_edges;
|
|
||||||
f_edges.reserve(3);
|
|
||||||
|
|
||||||
FaceEdges(last,f_edges);
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd>::iterator edge_it = f_edges.begin();
|
|
||||||
vector<LOD_EdgeInd>::const_iterator edge_end = f_edges.end();
|
|
||||||
|
|
||||||
for (; edge_it != edge_end; ++edge_it) {
|
|
||||||
edges[*edge_it].SwapFace(last,f);
|
|
||||||
}
|
|
||||||
|
|
||||||
faces[f] = faces[last];
|
|
||||||
|
|
||||||
}
|
|
||||||
faces.pop_back();
|
|
||||||
|
|
||||||
// tidy external buffers
|
|
||||||
extern_editor.CopyBackFace(f);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@@ -1,265 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_ManMesh2.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LOD_MANMESH2_H__
|
|
||||||
#define __LOD_MANMESH2_H__
|
|
||||||
|
|
||||||
#include "LOD_MeshPrimitives.h"
|
|
||||||
#include "MEM_SmartPtr.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
template <class HeapType> class CTR_UHeap;
|
|
||||||
|
|
||||||
class LOD_ExternBufferEditor;
|
|
||||||
|
|
||||||
class LOD_ManMesh2 // Manifold 2 dimensional mesh
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
static
|
|
||||||
LOD_ManMesh2 *
|
|
||||||
New(
|
|
||||||
);
|
|
||||||
|
|
||||||
// take ownership of the vertices.
|
|
||||||
|
|
||||||
bool
|
|
||||||
SetVertices(
|
|
||||||
MEM_SmartPtr<std::vector<LOD_Vertex> > verts
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add a triangle to the mesh
|
|
||||||
|
|
||||||
void
|
|
||||||
AddTriangle(
|
|
||||||
int verts[3]
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
ConnectTriangle(
|
|
||||||
LOD_FaceInd fi,
|
|
||||||
std::vector<LOD_EdgeInd> & new_edges
|
|
||||||
);
|
|
||||||
|
|
||||||
// geometry access
|
|
||||||
//////////////////
|
|
||||||
|
|
||||||
std::vector<LOD_Vertex> &
|
|
||||||
VertexSet(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
std::vector<LOD_TriFace> &
|
|
||||||
FaceSet(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
std::vector<LOD_Edge> &
|
|
||||||
EdgeSet(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
~LOD_ManMesh2(
|
|
||||||
);
|
|
||||||
|
|
||||||
// local geometry queries
|
|
||||||
/////////////////////////
|
|
||||||
|
|
||||||
// face queries
|
|
||||||
///////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
FaceVertices(
|
|
||||||
LOD_FaceInd f,
|
|
||||||
std::vector<LOD_VertexInd> &output
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
FaceEdges(
|
|
||||||
LOD_FaceInd f,
|
|
||||||
std::vector<LOD_EdgeInd> &output
|
|
||||||
);
|
|
||||||
|
|
||||||
// edge queries
|
|
||||||
///////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
EdgeVertices(
|
|
||||||
LOD_EdgeInd e,
|
|
||||||
std::vector<LOD_VertexInd> &output
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
EdgeFaces(
|
|
||||||
LOD_EdgeInd e,
|
|
||||||
std::vector<LOD_FaceInd> &output
|
|
||||||
);
|
|
||||||
|
|
||||||
// vertex queries
|
|
||||||
/////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
VertexEdges(
|
|
||||||
LOD_VertexInd v,
|
|
||||||
std::vector<LOD_EdgeInd> &output
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
VertexFaces(
|
|
||||||
LOD_VertexInd v,
|
|
||||||
std::vector<LOD_FaceInd> &output
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
SetBBox(
|
|
||||||
MT_Vector3 bbox_min,
|
|
||||||
MT_Vector3 bbox_max
|
|
||||||
);
|
|
||||||
|
|
||||||
MT_Vector3
|
|
||||||
BBoxMin(
|
|
||||||
) const {
|
|
||||||
return m_bbox_min;
|
|
||||||
};
|
|
||||||
|
|
||||||
MT_Vector3
|
|
||||||
BBoxMax(
|
|
||||||
) const {
|
|
||||||
return m_bbox_max;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Remove a primitive from the mesh
|
|
||||||
///////////////////////////////////
|
|
||||||
|
|
||||||
// These methods assume you have correctly
|
|
||||||
// tidied up the index pointers in other primitives,
|
|
||||||
// so that nothing refers to this object any more
|
|
||||||
|
|
||||||
// These methods exchange the primitive with the
|
|
||||||
// last primitive in the vector. It modifies everything
|
|
||||||
// pointing to the last primitive correctly.
|
|
||||||
|
|
||||||
// FIXME refactor extern editor out of primitive deletion
|
|
||||||
// insead return a vector of primitives that need to be
|
|
||||||
// modified and do this externally
|
|
||||||
|
|
||||||
void
|
|
||||||
DeleteVertex(
|
|
||||||
LOD_ExternBufferEditor & extern_editor,
|
|
||||||
LOD_VertexInd v
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
DeleteEdge(
|
|
||||||
LOD_EdgeInd e,
|
|
||||||
CTR_UHeap<LOD_Edge> *heap
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
DeleteFace(
|
|
||||||
LOD_ExternBufferEditor & extern_editor,
|
|
||||||
LOD_FaceInd f
|
|
||||||
);
|
|
||||||
|
|
||||||
// Sanity Check routines
|
|
||||||
////////////////////////
|
|
||||||
|
|
||||||
// Make sure the edge sets and the vertex sets are
|
|
||||||
// consistent
|
|
||||||
|
|
||||||
void
|
|
||||||
SC_TriFace(
|
|
||||||
LOD_FaceInd f
|
|
||||||
);
|
|
||||||
|
|
||||||
// basic sanity checking of an edge list bails out if there are more than 1024
|
|
||||||
// edges
|
|
||||||
|
|
||||||
void
|
|
||||||
SC_EdgeList(
|
|
||||||
LOD_EdgeInd e
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// Check to see that the edges of v1 and v2 are unique.
|
|
||||||
|
|
||||||
bool
|
|
||||||
SC_UniqueEdge(
|
|
||||||
LOD_EdgeInd e
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
|
|
||||||
// Returns the edge index of the edge from v1 to v2.
|
|
||||||
// Does this by searching the edge sets of v1 - but not v2.
|
|
||||||
// If you are paranoid you should check both and make sure the
|
|
||||||
// indices are the same. If the edge doe not exist edgeInd is empty.
|
|
||||||
|
|
||||||
LOD_EdgeInd
|
|
||||||
FindEdge(
|
|
||||||
const LOD_VertexInd v1,
|
|
||||||
const LOD_VertexInd v2
|
|
||||||
);
|
|
||||||
|
|
||||||
// Insert an edge into the mesh
|
|
||||||
// Tie up the ptrs and create space for the edge
|
|
||||||
// returns manifold errors - need to sort out memory edges
|
|
||||||
|
|
||||||
bool
|
|
||||||
InsertEdge(
|
|
||||||
const LOD_VertexInd v1,
|
|
||||||
const LOD_VertexInd v2,
|
|
||||||
const LOD_FaceInd f,
|
|
||||||
std::vector<LOD_EdgeInd> &new_edges
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
LOD_ManMesh2(
|
|
||||||
);
|
|
||||||
|
|
||||||
MEM_SmartPtr< std::vector<LOD_Vertex> > m_verts;
|
|
||||||
MEM_SmartPtr< std::vector<LOD_TriFace> > m_faces;
|
|
||||||
MEM_SmartPtr< std::vector<LOD_Edge> > m_edges;
|
|
||||||
|
|
||||||
// not sure of these descrtiptions of the mesh should
|
|
||||||
// reside in this class coz may lead to very bloated interface.
|
|
||||||
|
|
||||||
MT_Vector3 m_bbox_min;
|
|
||||||
MT_Vector3 m_bbox_max;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_MeshBounds.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LOD_MESHBOUNDS_H__
|
|
||||||
#define __LOD_MESHBOUNDS_H__
|
|
||||||
|
|
||||||
#include "MEM_SmartPtr.h"
|
|
||||||
#include "LOD_MeshPrimitives.h"
|
|
||||||
#include "LOD_ManMesh2.h"
|
|
||||||
#include "MT_assert.h"
|
|
||||||
|
|
||||||
// simple class to compute the mesh bounds of a manifold mesh,
|
|
||||||
|
|
||||||
class LOD_MeshBounds {
|
|
||||||
|
|
||||||
public :
|
|
||||||
static
|
|
||||||
LOD_MeshBounds *
|
|
||||||
New(
|
|
||||||
){
|
|
||||||
|
|
||||||
MEM_SmartPtr<LOD_MeshBounds> output(new LOD_MeshBounds());
|
|
||||||
return output.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ComputeBounds(
|
|
||||||
const LOD_ManMesh2 * mesh
|
|
||||||
){
|
|
||||||
MT_assert(mesh!=NULL);
|
|
||||||
MT_assert(mesh->VertexSet().size() > 0);
|
|
||||||
|
|
||||||
const std::vector<LOD_Vertex> &verts = mesh->VertexSet();
|
|
||||||
|
|
||||||
m_min = verts[0].pos;
|
|
||||||
m_max = verts[0].pos;
|
|
||||||
|
|
||||||
// iterate through the verts
|
|
||||||
|
|
||||||
int t;
|
|
||||||
const int size = verts.size();
|
|
||||||
|
|
||||||
for (t=1; t< size ; ++t) {
|
|
||||||
|
|
||||||
UpdateBounds(verts[t].pos,m_min,m_max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MT_Vector3
|
|
||||||
Min(
|
|
||||||
) const {
|
|
||||||
return m_min;
|
|
||||||
}
|
|
||||||
|
|
||||||
MT_Vector3
|
|
||||||
Max(
|
|
||||||
) const {
|
|
||||||
return m_max;
|
|
||||||
}
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
void
|
|
||||||
UpdateBounds(
|
|
||||||
MT_Vector3 vertex,
|
|
||||||
MT_Vector3& min,
|
|
||||||
MT_Vector3& max
|
|
||||||
) {
|
|
||||||
if (vertex.x() < min.x()) {
|
|
||||||
min.x() = vertex.x();
|
|
||||||
} else
|
|
||||||
if (vertex.x() > max.x()) {
|
|
||||||
max.x()= vertex.x();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vertex.y() < min.y()) {
|
|
||||||
min.y() = vertex.y();
|
|
||||||
} else
|
|
||||||
if (vertex.y() > max.y()) {
|
|
||||||
max.y()= vertex.y();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vertex.z() < min.z()) {
|
|
||||||
min.z() = vertex.z();
|
|
||||||
} else
|
|
||||||
if (vertex.z() > max.z()) {
|
|
||||||
max.z()= vertex.z();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOD_MeshBounds(
|
|
||||||
) :
|
|
||||||
m_min(0,0,0),
|
|
||||||
m_max(0,0,0)
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
MT_Vector3 m_min;
|
|
||||||
MT_Vector3 m_max;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_MeshException.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LOD_MESHEXCEPTION_H__
|
|
||||||
#define __LOD_MESHEXCEPTION_H__
|
|
||||||
|
|
||||||
class LOD_MeshException {
|
|
||||||
|
|
||||||
public :
|
|
||||||
|
|
||||||
// stick in more error types as you think of them
|
|
||||||
|
|
||||||
enum ExceptionType{
|
|
||||||
e_non_manifold,
|
|
||||||
e_search_error
|
|
||||||
} m_e_type;
|
|
||||||
|
|
||||||
LOD_MeshException (
|
|
||||||
ExceptionType type
|
|
||||||
) : m_e_type (type)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,404 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_MeshPrimitives.cpp
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "LOD_MeshPrimitives.h"
|
|
||||||
|
|
||||||
#include "MT_assert.h"
|
|
||||||
#include "LOD_MeshException.h"
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
// Vertex Methods
|
|
||||||
/////////////////
|
|
||||||
|
|
||||||
LOD_Vertex::
|
|
||||||
LOD_Vertex(
|
|
||||||
) :
|
|
||||||
pos (MT_Vector3()),
|
|
||||||
m_select_tag(false)
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_Vertex::
|
|
||||||
RemoveEdge(
|
|
||||||
LOD_EdgeInd e
|
|
||||||
){
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd>::iterator result = find(m_edges.begin(),m_edges.end(),e);
|
|
||||||
if (result == m_edges.end()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::swap(*result, m_edges.back());
|
|
||||||
m_edges.pop_back();
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_Vertex::
|
|
||||||
AddEdge(
|
|
||||||
LOD_EdgeInd e
|
|
||||||
){
|
|
||||||
m_edges.push_back(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_Vertex::
|
|
||||||
SwapEdge(
|
|
||||||
LOD_EdgeInd e_old,
|
|
||||||
LOD_EdgeInd e_new
|
|
||||||
){
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd>::iterator result =
|
|
||||||
find(m_edges.begin(),m_edges.end(),e_old);
|
|
||||||
if (result == m_edges.end()) {
|
|
||||||
MT_assert(false);
|
|
||||||
LOD_MeshException e(LOD_MeshException::e_search_error);
|
|
||||||
throw(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
*result = e_new;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_Vertex::
|
|
||||||
SelectTag(
|
|
||||||
) const {
|
|
||||||
return m_select_tag;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_Vertex::
|
|
||||||
SetSelectTag(
|
|
||||||
bool tag
|
|
||||||
){
|
|
||||||
m_select_tag = tag;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_Vertex::
|
|
||||||
Degenerate(
|
|
||||||
){
|
|
||||||
return m_edges.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_Vertex::
|
|
||||||
CopyPosition(
|
|
||||||
float *float_ptr
|
|
||||||
){
|
|
||||||
pos.getValue(float_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Edge Methods
|
|
||||||
///////////////
|
|
||||||
|
|
||||||
LOD_Edge::
|
|
||||||
LOD_Edge (
|
|
||||||
) {
|
|
||||||
m_verts[0] = m_verts[1] = LOD_VertexInd::Empty();
|
|
||||||
m_faces[0] = m_faces[1] = LOD_FaceInd::Empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_Edge::
|
|
||||||
operator == (
|
|
||||||
LOD_Edge & rhs
|
|
||||||
) {
|
|
||||||
// edges are the same if their vertex indices are the
|
|
||||||
// same!!! Other properties are not checked
|
|
||||||
|
|
||||||
int matches = 0;
|
|
||||||
|
|
||||||
if (this->m_verts[0] == rhs.m_verts[0]) {
|
|
||||||
++matches;
|
|
||||||
}
|
|
||||||
if (this->m_verts[1] == rhs.m_verts[0]) {
|
|
||||||
++matches;
|
|
||||||
}
|
|
||||||
if (this->m_verts[0] == rhs.m_verts[1]) {
|
|
||||||
++matches;
|
|
||||||
}
|
|
||||||
if (this->m_verts[1] == rhs.m_verts[1]) {
|
|
||||||
++matches;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matches >= 2) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Elementary helper methods
|
|
||||||
////////////////////////////
|
|
||||||
|
|
||||||
LOD_FaceInd
|
|
||||||
LOD_Edge::
|
|
||||||
OpFace(
|
|
||||||
LOD_FaceInd f
|
|
||||||
) const {
|
|
||||||
if (f == m_faces[0]) {
|
|
||||||
return m_faces[1];
|
|
||||||
} else
|
|
||||||
if (f == m_faces[1]) {
|
|
||||||
return m_faces[0];
|
|
||||||
} else {
|
|
||||||
MT_assert(false);
|
|
||||||
LOD_MeshException e(LOD_MeshException::e_search_error);
|
|
||||||
throw(e);
|
|
||||||
|
|
||||||
return LOD_FaceInd::Empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_Edge::
|
|
||||||
SwapFace(
|
|
||||||
LOD_FaceInd old_f,
|
|
||||||
LOD_FaceInd new_f
|
|
||||||
) {
|
|
||||||
if (old_f == m_faces[0]) {
|
|
||||||
m_faces[0] = new_f;
|
|
||||||
} else
|
|
||||||
if (old_f == m_faces[1]) {
|
|
||||||
m_faces[1] = new_f;
|
|
||||||
} else {
|
|
||||||
LOD_MeshException e(LOD_MeshException::e_search_error);
|
|
||||||
throw(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// return the half edge face - the half edge is defined
|
|
||||||
// by the {vertex,edge} tuple.
|
|
||||||
|
|
||||||
LOD_FaceInd
|
|
||||||
LOD_Edge::
|
|
||||||
HalfEdgeFace(
|
|
||||||
LOD_VertexInd vi
|
|
||||||
){
|
|
||||||
if (vi == m_verts[0]) return m_faces[0];
|
|
||||||
if (vi == m_verts[1]) return m_faces[1];
|
|
||||||
MT_assert(false);
|
|
||||||
|
|
||||||
LOD_MeshException e(LOD_MeshException::e_search_error);
|
|
||||||
throw(e);
|
|
||||||
|
|
||||||
return LOD_FaceInd::Empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LOD_VertexInd
|
|
||||||
LOD_Edge::
|
|
||||||
OpVertex(
|
|
||||||
LOD_VertexInd vi
|
|
||||||
) {
|
|
||||||
if (vi == m_verts[0]) return m_verts[1];
|
|
||||||
if (vi == m_verts[1]) return m_verts[0];
|
|
||||||
MT_assert(false);
|
|
||||||
|
|
||||||
LOD_MeshException e(LOD_MeshException::e_search_error);
|
|
||||||
throw(e);
|
|
||||||
|
|
||||||
return LOD_VertexInd::Empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace the vertex v_old with vertex v_new
|
|
||||||
// error if v_old is not one of the original vertices
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_Edge::
|
|
||||||
SwapVertex(
|
|
||||||
LOD_VertexInd v_old,
|
|
||||||
LOD_VertexInd v_new
|
|
||||||
) {
|
|
||||||
if (v_old == m_verts[0]) {
|
|
||||||
m_verts[0] = v_new;
|
|
||||||
} else
|
|
||||||
if (v_old == m_verts[1]) {
|
|
||||||
m_verts[1] = v_new;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
MT_assert(false);
|
|
||||||
|
|
||||||
LOD_MeshException e(LOD_MeshException::e_search_error);
|
|
||||||
throw(e);
|
|
||||||
}
|
|
||||||
if(m_verts[0] == m_verts[1]) {
|
|
||||||
MT_assert(false);
|
|
||||||
|
|
||||||
LOD_MeshException e(LOD_MeshException::e_non_manifold);
|
|
||||||
throw(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_Edge::
|
|
||||||
SelectTag(
|
|
||||||
) const {
|
|
||||||
return bool(m_verts[1].Tag() & 0x1);
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_Edge::
|
|
||||||
SetSelectTag(
|
|
||||||
bool tag
|
|
||||||
) {
|
|
||||||
m_verts[1].SetTag(int(tag));
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
LOD_Edge::
|
|
||||||
OpenTag(
|
|
||||||
) const {
|
|
||||||
return m_faces[0].Tag();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_Edge::
|
|
||||||
SetOpenTag(
|
|
||||||
int tag
|
|
||||||
) {
|
|
||||||
m_faces[0].SetTag(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_Edge::
|
|
||||||
Degenerate(
|
|
||||||
) const {
|
|
||||||
return (
|
|
||||||
(m_faces[0].IsEmpty() && m_faces[1].IsEmpty()) ||
|
|
||||||
(m_verts[0] == m_verts[1])
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// TriFace Methods
|
|
||||||
//////////////////
|
|
||||||
|
|
||||||
LOD_TriFace::
|
|
||||||
LOD_TriFace(
|
|
||||||
) {
|
|
||||||
m_verts[0] = m_verts[1] = m_verts[2] = LOD_VertexInd::Empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Elementary helper methods
|
|
||||||
////////////////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_TriFace::
|
|
||||||
SwapVertex(
|
|
||||||
LOD_VertexInd old_v,
|
|
||||||
LOD_VertexInd new_v
|
|
||||||
) {
|
|
||||||
// could save branching here...
|
|
||||||
|
|
||||||
if (m_verts[0] == old_v) {
|
|
||||||
m_verts[0] = new_v;
|
|
||||||
} else
|
|
||||||
if (m_verts[1] == old_v) {
|
|
||||||
m_verts[1] = new_v;
|
|
||||||
} else
|
|
||||||
if (m_verts[2] == old_v) {
|
|
||||||
m_verts[2] = new_v;
|
|
||||||
} else {
|
|
||||||
MT_assert(false);
|
|
||||||
|
|
||||||
LOD_MeshException excep(LOD_MeshException::e_search_error);
|
|
||||||
throw(excep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_TriFace::
|
|
||||||
SelectTag(
|
|
||||||
) const {
|
|
||||||
return bool(m_verts[1].Tag() & 0x1);
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_TriFace::
|
|
||||||
SetSelectTag(
|
|
||||||
bool tag
|
|
||||||
) {
|
|
||||||
m_verts[1].SetTag(int(tag));
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
LOD_TriFace::
|
|
||||||
OpenTag(
|
|
||||||
) {
|
|
||||||
return m_verts[2].Tag();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_TriFace::
|
|
||||||
SetOpenTag(
|
|
||||||
int tag
|
|
||||||
) {
|
|
||||||
m_verts[2].SetTag(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_TriFace::
|
|
||||||
Degenerate(
|
|
||||||
) {
|
|
||||||
|
|
||||||
return (
|
|
||||||
(m_verts[0] == m_verts[1]) ||
|
|
||||||
(m_verts[1] == m_verts[2]) ||
|
|
||||||
(m_verts[2] == m_verts[0])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_TriFace::
|
|
||||||
CopyVerts(
|
|
||||||
int * index_ptr
|
|
||||||
){
|
|
||||||
index_ptr[0] = m_verts[0];
|
|
||||||
index_ptr[1] = m_verts[1];
|
|
||||||
index_ptr[2] = m_verts[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@@ -1,221 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_MeshPrimitives.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LOD_MESHPRIMITIVES_H__
|
|
||||||
#define __LOD_MESHPRIMITIVES_H__
|
|
||||||
|
|
||||||
#include "MT_Vector3.h"
|
|
||||||
#include "CTR_TaggedIndex.h"
|
|
||||||
#include "CTR_UHeap.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
typedef CTR_TaggedIndex<24,0x00ffffff> LOD_VertexInd;
|
|
||||||
typedef CTR_TaggedIndex<24,0x00ffffff> LOD_EdgeInd;
|
|
||||||
typedef CTR_TaggedIndex<24,0x00ffffff> LOD_FaceInd;
|
|
||||||
typedef CTR_TaggedIndex<24,0x00ffffff> LOD_HeapInd;
|
|
||||||
|
|
||||||
class LOD_Vertex {
|
|
||||||
public :
|
|
||||||
MT_Vector3 pos;
|
|
||||||
std::vector<LOD_EdgeInd> m_edges;
|
|
||||||
bool m_select_tag;
|
|
||||||
|
|
||||||
LOD_Vertex(
|
|
||||||
);
|
|
||||||
|
|
||||||
bool
|
|
||||||
RemoveEdge(
|
|
||||||
LOD_EdgeInd e
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
AddEdge(
|
|
||||||
LOD_EdgeInd e
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
SwapEdge(
|
|
||||||
LOD_EdgeInd e_old,
|
|
||||||
LOD_EdgeInd e_new
|
|
||||||
);
|
|
||||||
|
|
||||||
bool
|
|
||||||
SelectTag(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void
|
|
||||||
SetSelectTag(
|
|
||||||
bool tag
|
|
||||||
);
|
|
||||||
|
|
||||||
bool
|
|
||||||
Degenerate(
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
CopyPosition(
|
|
||||||
float *float_ptr
|
|
||||||
);
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class LOD_Edge : public CTR_UHeapable {
|
|
||||||
public :
|
|
||||||
LOD_VertexInd m_verts[2];
|
|
||||||
LOD_FaceInd m_faces[2];
|
|
||||||
|
|
||||||
LOD_Edge (
|
|
||||||
);
|
|
||||||
|
|
||||||
bool operator == (
|
|
||||||
LOD_Edge & rhs
|
|
||||||
);
|
|
||||||
|
|
||||||
// Elementary helper methods
|
|
||||||
////////////////////////////
|
|
||||||
|
|
||||||
LOD_FaceInd
|
|
||||||
OpFace(
|
|
||||||
LOD_FaceInd f
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void
|
|
||||||
SwapFace(
|
|
||||||
LOD_FaceInd old_f,
|
|
||||||
LOD_FaceInd new_f
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// return the half edge face - the half edge is defined
|
|
||||||
// by the {vertex,edge} tuple.
|
|
||||||
|
|
||||||
LOD_FaceInd
|
|
||||||
HalfEdgeFace(
|
|
||||||
LOD_VertexInd vi
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
LOD_VertexInd
|
|
||||||
OpVertex(
|
|
||||||
LOD_VertexInd vi
|
|
||||||
);
|
|
||||||
|
|
||||||
// replace the vertex v_old with vertex v_new
|
|
||||||
// error if v_old is not one of the original vertices
|
|
||||||
|
|
||||||
void
|
|
||||||
SwapVertex(
|
|
||||||
LOD_VertexInd v_old,
|
|
||||||
LOD_VertexInd v_new
|
|
||||||
);
|
|
||||||
|
|
||||||
bool
|
|
||||||
SelectTag(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void
|
|
||||||
SetSelectTag(
|
|
||||||
bool tag
|
|
||||||
);
|
|
||||||
|
|
||||||
int
|
|
||||||
OpenTag(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void
|
|
||||||
SetOpenTag(
|
|
||||||
int tag
|
|
||||||
);
|
|
||||||
|
|
||||||
bool
|
|
||||||
Degenerate(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
bool
|
|
||||||
BoundaryEdge(
|
|
||||||
) const {
|
|
||||||
return (m_faces[0].IsEmpty() || m_faces[1].IsEmpty());
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class LOD_TriFace {
|
|
||||||
public:
|
|
||||||
|
|
||||||
LOD_VertexInd m_verts[3];
|
|
||||||
|
|
||||||
LOD_TriFace(
|
|
||||||
);
|
|
||||||
|
|
||||||
// Elementary helper methods
|
|
||||||
////////////////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
SwapVertex(
|
|
||||||
LOD_VertexInd old_v,
|
|
||||||
LOD_VertexInd new_v
|
|
||||||
);
|
|
||||||
|
|
||||||
bool
|
|
||||||
SelectTag(
|
|
||||||
) const;
|
|
||||||
|
|
||||||
void
|
|
||||||
SetSelectTag(
|
|
||||||
bool tag
|
|
||||||
);
|
|
||||||
|
|
||||||
int
|
|
||||||
OpenTag(
|
|
||||||
);
|
|
||||||
void
|
|
||||||
SetOpenTag(
|
|
||||||
int tag
|
|
||||||
);
|
|
||||||
|
|
||||||
bool
|
|
||||||
Degenerate(
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
CopyVerts(
|
|
||||||
int * index_ptr
|
|
||||||
);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,327 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_QSDecimator.cpp
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "LOD_QSDecimator.h"
|
|
||||||
|
|
||||||
#include "LOD_ExternBufferEditor.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
LOD_QSDecimator *
|
|
||||||
LOD_QSDecimator::
|
|
||||||
New(
|
|
||||||
LOD_ManMesh2 &mesh,
|
|
||||||
LOD_ExternNormalEditor &face_editor,
|
|
||||||
LOD_ExternBufferEditor &extern_editor
|
|
||||||
){
|
|
||||||
|
|
||||||
MEM_SmartPtr<LOD_QSDecimator> output
|
|
||||||
= new LOD_QSDecimator(mesh,face_editor,extern_editor);
|
|
||||||
|
|
||||||
MEM_SmartPtr<LOD_EdgeCollapser > collapser(LOD_EdgeCollapser::New());
|
|
||||||
MEM_SmartPtr<LOD_QuadricEditor> q_editor(LOD_QuadricEditor::New(mesh));
|
|
||||||
|
|
||||||
if (
|
|
||||||
output == NULL ||
|
|
||||||
collapser == NULL ||
|
|
||||||
q_editor == NULL
|
|
||||||
) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
output->m_collapser = collapser.Release();
|
|
||||||
output->m_quadric_editor = q_editor.Release();
|
|
||||||
return output.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_QSDecimator::
|
|
||||||
Arm(
|
|
||||||
){
|
|
||||||
MT_assert(!m_is_armed);
|
|
||||||
bool heap_result = BuildHeap();
|
|
||||||
if (!heap_result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_is_armed = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_QSDecimator::
|
|
||||||
Step(
|
|
||||||
){
|
|
||||||
return CollapseEdge();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LOD_QSDecimator::
|
|
||||||
LOD_QSDecimator(
|
|
||||||
LOD_ManMesh2 &mesh,
|
|
||||||
LOD_ExternNormalEditor &face_editor,
|
|
||||||
LOD_ExternBufferEditor &extern_editor
|
|
||||||
) :
|
|
||||||
m_is_armed (false),
|
|
||||||
m_mesh(mesh),
|
|
||||||
m_face_editor(face_editor),
|
|
||||||
m_extern_editor(extern_editor)
|
|
||||||
{
|
|
||||||
m_deg_edges.reserve(32);
|
|
||||||
m_deg_faces.reserve(32);
|
|
||||||
m_deg_vertices.reserve(32);
|
|
||||||
m_update_faces.reserve(32);
|
|
||||||
m_new_edges.reserve(32);
|
|
||||||
m_update_vertices.reserve(32);
|
|
||||||
};
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_QSDecimator::
|
|
||||||
CollapseEdge(
|
|
||||||
){
|
|
||||||
|
|
||||||
// find an edge to collapse
|
|
||||||
|
|
||||||
// FIXME force an edge collapse
|
|
||||||
// or return false
|
|
||||||
|
|
||||||
std::vector<LOD_Edge> & edges = m_mesh.EdgeSet();
|
|
||||||
std::vector<LOD_Vertex> & verts = m_mesh.VertexSet();
|
|
||||||
std::vector<LOD_Quadric> & quadrics = m_quadric_editor->Quadrics();
|
|
||||||
int size = edges.size();
|
|
||||||
|
|
||||||
if (size == 0) return false;
|
|
||||||
|
|
||||||
const int heap_top = m_heap->Top();
|
|
||||||
|
|
||||||
if (heap_top == -1 || edges[heap_top].HeapKey() <= -MT_INFINITY) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute the target position
|
|
||||||
MT_Vector3 new_vertex = m_quadric_editor->TargetVertex(edges[heap_top]);
|
|
||||||
LOD_Quadric & q0 = quadrics[edges[heap_top].m_verts[0]];
|
|
||||||
LOD_Quadric & q1 = quadrics[edges[heap_top].m_verts[1]];
|
|
||||||
|
|
||||||
LOD_Vertex &v0 = verts[edges[heap_top].m_verts[0]];
|
|
||||||
LOD_Vertex &v1 = verts[edges[heap_top].m_verts[1]];
|
|
||||||
|
|
||||||
LOD_Quadric sum = q0;
|
|
||||||
sum += q1;
|
|
||||||
|
|
||||||
|
|
||||||
if (m_collapser->CollapseEdge(
|
|
||||||
heap_top,
|
|
||||||
m_mesh,
|
|
||||||
m_deg_edges,
|
|
||||||
m_deg_faces,
|
|
||||||
m_deg_vertices,
|
|
||||||
m_new_edges,
|
|
||||||
m_update_faces,
|
|
||||||
m_update_vertices
|
|
||||||
)) {
|
|
||||||
|
|
||||||
// assign new vertex position
|
|
||||||
|
|
||||||
v0.pos = new_vertex;
|
|
||||||
v1.pos = new_vertex;
|
|
||||||
|
|
||||||
// sum the quadrics of v0 and v1
|
|
||||||
q0 = sum;
|
|
||||||
q1 = sum;
|
|
||||||
|
|
||||||
// ok update the primitive properties
|
|
||||||
|
|
||||||
m_face_editor.Update(m_update_faces);
|
|
||||||
m_face_editor.UpdateVertexNormals(m_update_vertices);
|
|
||||||
|
|
||||||
// update the external vertex buffer
|
|
||||||
m_extern_editor.CopyModifiedVerts(m_mesh,m_update_vertices);
|
|
||||||
|
|
||||||
// update the external face buffer
|
|
||||||
m_extern_editor.CopyModifiedFaces(m_mesh,m_update_faces);
|
|
||||||
|
|
||||||
// update the edge heap
|
|
||||||
UpdateHeap(m_deg_edges,m_new_edges);
|
|
||||||
|
|
||||||
m_quadric_editor->Remove(m_deg_vertices);
|
|
||||||
m_face_editor.Remove(m_deg_faces);
|
|
||||||
m_face_editor.RemoveVertexNormals(m_deg_vertices);
|
|
||||||
|
|
||||||
// delete the primitives
|
|
||||||
|
|
||||||
DeletePrimitives(m_deg_edges,m_deg_faces,m_deg_vertices);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// the edge could not be collapsed at the moment - so
|
|
||||||
// we adjust it's priority and add it back to the heap.
|
|
||||||
m_heap->Remove(&edges[0],0);
|
|
||||||
edges[heap_top].HeapKey() = - MT_INFINITY;
|
|
||||||
m_heap->Insert(&edges[0],heap_top);
|
|
||||||
}
|
|
||||||
|
|
||||||
//clear all the temporary buffers
|
|
||||||
|
|
||||||
m_deg_faces.clear();
|
|
||||||
m_deg_edges.clear();
|
|
||||||
m_deg_vertices.clear();
|
|
||||||
|
|
||||||
m_update_faces.clear();
|
|
||||||
m_update_vertices.clear();
|
|
||||||
m_new_edges.clear();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_QSDecimator::
|
|
||||||
DeletePrimitives(
|
|
||||||
const vector<LOD_EdgeInd> & degenerate_edges,
|
|
||||||
const vector<LOD_FaceInd> & degenerate_faces,
|
|
||||||
const vector<LOD_VertexInd> & degenerate_vertices
|
|
||||||
) {
|
|
||||||
|
|
||||||
// assumes that the 3 vectors are sorted in descending order.
|
|
||||||
|
|
||||||
// Delete Degnerate primitives
|
|
||||||
//////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
// delete the old edges - we have to be very careful here
|
|
||||||
// mesh.delete() swaps edges to be deleted with the last edge in
|
|
||||||
// the edge buffer. However the next edge to be deleted may have
|
|
||||||
// been the last edge in the buffer!
|
|
||||||
|
|
||||||
// One way to solve this is to sort degenerate_edges in descending order.
|
|
||||||
// And then delete them in that order.
|
|
||||||
|
|
||||||
// it is also vital that degenerate_edges contains no duplicates
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd>::const_iterator edge_it = degenerate_edges.begin();
|
|
||||||
vector<LOD_EdgeInd>::const_iterator edge_end = degenerate_edges.end();
|
|
||||||
|
|
||||||
for (; edge_it != edge_end; ++edge_it) {
|
|
||||||
m_mesh.DeleteEdge(*edge_it,m_heap);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vector<LOD_FaceInd>::const_iterator face_it = degenerate_faces.begin();
|
|
||||||
vector<LOD_FaceInd>::const_iterator face_end = degenerate_faces.end();
|
|
||||||
|
|
||||||
for (;face_it != face_end; ++face_it) {
|
|
||||||
m_mesh.DeleteFace(m_extern_editor,*face_it);
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<LOD_VertexInd>::const_iterator vertex_it = degenerate_vertices.begin();
|
|
||||||
vector<LOD_VertexInd>::const_iterator vertex_end = degenerate_vertices.end();
|
|
||||||
|
|
||||||
for (;vertex_it != vertex_end; ++vertex_it) {
|
|
||||||
m_mesh.DeleteVertex(m_extern_editor,*vertex_it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_QSDecimator::
|
|
||||||
BuildHeap(
|
|
||||||
){
|
|
||||||
// build the quadrics
|
|
||||||
|
|
||||||
if (m_quadric_editor->BuildQuadrics(m_face_editor,true) == false) return false;
|
|
||||||
|
|
||||||
|
|
||||||
m_heap = CTR_UHeap<LOD_Edge>::New();
|
|
||||||
// load in edge pointers to the heap
|
|
||||||
|
|
||||||
std::vector<LOD_Edge> & edge_set= m_mesh.EdgeSet();
|
|
||||||
|
|
||||||
// UNUSED
|
|
||||||
// std::vector<LOD_Edge>::const_iterator edge_end = edge_set.end();
|
|
||||||
// std::vector<LOD_Edge>::iterator edge_start = edge_set.begin();
|
|
||||||
|
|
||||||
std::vector<int> & heap_vector = m_heap->HeapVector();
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < edge_set.size(); ++i) {
|
|
||||||
edge_set[i].HeapPos() = i;
|
|
||||||
heap_vector.push_back(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_heap->MakeHeap(&edge_set[0]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_QSDecimator::
|
|
||||||
UpdateHeap(
|
|
||||||
std::vector<LOD_EdgeInd> °_edges,
|
|
||||||
std::vector<LOD_EdgeInd> &new_edges
|
|
||||||
){
|
|
||||||
// first of all compute values for the new edges
|
|
||||||
// and bung them on the heap.
|
|
||||||
|
|
||||||
std::vector<LOD_Edge> & edge_set= m_mesh.EdgeSet();
|
|
||||||
|
|
||||||
std::vector<LOD_EdgeInd>::const_iterator edge_it = new_edges.begin();
|
|
||||||
std::vector<LOD_EdgeInd>::const_iterator end_it = new_edges.end();
|
|
||||||
|
|
||||||
|
|
||||||
// insert all the new edges
|
|
||||||
///////////////////////////
|
|
||||||
|
|
||||||
// compute edge costs ffor the new edges
|
|
||||||
|
|
||||||
m_quadric_editor->ComputeEdgeCosts(new_edges);
|
|
||||||
|
|
||||||
// inser the new elements into the heap
|
|
||||||
|
|
||||||
for (; edge_it != end_it; ++edge_it) {
|
|
||||||
m_heap->Insert(&edge_set[0],*edge_it);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// remove all the old values from the heap
|
|
||||||
|
|
||||||
edge_it = deg_edges.begin();
|
|
||||||
end_it = deg_edges.end();
|
|
||||||
|
|
||||||
for (; edge_it != end_it; ++edge_it) {
|
|
||||||
LOD_Edge &e = edge_set[*edge_it];
|
|
||||||
m_heap->Remove(&edge_set[0],e.HeapPos());
|
|
||||||
|
|
||||||
e.HeapPos() = -1;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@@ -1,129 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_QSDecimator.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LOD_QSDECIMATOR_H__
|
|
||||||
#define __LOD_QSDECIMATOR_H__
|
|
||||||
|
|
||||||
#include "MEM_NonCopyable.h"
|
|
||||||
#include "LOD_ManMesh2.h"
|
|
||||||
#include "LOD_ExternNormalEditor.h"
|
|
||||||
#include "LOD_EdgeCollapser.h"
|
|
||||||
#include "LOD_QuadricEditor.h"
|
|
||||||
|
|
||||||
class LOD_ExternBufferEditor;
|
|
||||||
|
|
||||||
class LOD_QSDecimator : public MEM_NonCopyable {
|
|
||||||
|
|
||||||
public :
|
|
||||||
|
|
||||||
static
|
|
||||||
LOD_QSDecimator *
|
|
||||||
New(
|
|
||||||
LOD_ManMesh2 &mesh,
|
|
||||||
LOD_ExternNormalEditor &face_editor,
|
|
||||||
LOD_ExternBufferEditor &extern_editor
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Arm(
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Step(
|
|
||||||
);
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
LOD_QSDecimator(
|
|
||||||
LOD_ManMesh2 &mesh,
|
|
||||||
LOD_ExternNormalEditor &face_editor,
|
|
||||||
LOD_ExternBufferEditor &extern_editor
|
|
||||||
);
|
|
||||||
|
|
||||||
bool
|
|
||||||
CollapseEdge(
|
|
||||||
);
|
|
||||||
|
|
||||||
bool
|
|
||||||
BuildHeap(
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
UpdateHeap(
|
|
||||||
std::vector<LOD_EdgeInd> °_edges,
|
|
||||||
std::vector<LOD_EdgeInd> &new_edges
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
DeletePrimitives(
|
|
||||||
const std::vector<LOD_EdgeInd> & degenerate_edges,
|
|
||||||
const std::vector<LOD_FaceInd> & degenerate_faces,
|
|
||||||
const std::vector<LOD_VertexInd> & degenerate_vertices
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
// owned by this class
|
|
||||||
//////////////////////
|
|
||||||
|
|
||||||
MEM_SmartPtr<LOD_EdgeCollapser> m_collapser;
|
|
||||||
MEM_SmartPtr<CTR_UHeap<LOD_Edge> > m_heap;
|
|
||||||
MEM_SmartPtr<LOD_QuadricEditor> m_quadric_editor;
|
|
||||||
|
|
||||||
bool m_is_armed;
|
|
||||||
|
|
||||||
// arguments to New(...)
|
|
||||||
////////////////////////
|
|
||||||
|
|
||||||
LOD_ManMesh2 & m_mesh;
|
|
||||||
LOD_ExternNormalEditor &m_face_editor;
|
|
||||||
LOD_ExternBufferEditor & m_extern_editor;
|
|
||||||
|
|
||||||
// temporary buffers
|
|
||||||
////////////////////
|
|
||||||
|
|
||||||
std::vector<LOD_FaceInd> m_deg_faces;
|
|
||||||
std::vector<LOD_EdgeInd> m_deg_edges;
|
|
||||||
std::vector<LOD_VertexInd> m_deg_vertices;
|
|
||||||
|
|
||||||
std::vector<LOD_FaceInd> m_update_faces;
|
|
||||||
std::vector<LOD_EdgeInd> m_new_edges;
|
|
||||||
std::vector<LOD_VertexInd> m_update_vertices;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,167 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_Quadric.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LOD_QUADRIC_H__
|
|
||||||
#define __LOD_QUADRIC_H__
|
|
||||||
|
|
||||||
#include "MT_Vector3.h"
|
|
||||||
#include "MT_Matrix3x3.h"
|
|
||||||
|
|
||||||
|
|
||||||
class LOD_Quadric {
|
|
||||||
|
|
||||||
private:
|
|
||||||
MT_Scalar a2, ab, ac, ad;
|
|
||||||
MT_Scalar b2, bc, bd;
|
|
||||||
MT_Scalar c2, cd;
|
|
||||||
MT_Scalar d2;
|
|
||||||
|
|
||||||
//void init(MT_Scalar a, MT_Scalar b, MT_Scalar c, MT_Scalar d);
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
LOD_Quadric(
|
|
||||||
) {
|
|
||||||
Clear();
|
|
||||||
};
|
|
||||||
|
|
||||||
LOD_Quadric(
|
|
||||||
const MT_Vector3 & vec,
|
|
||||||
const MT_Scalar & offset
|
|
||||||
) {
|
|
||||||
a2 = vec[0] *vec[0];
|
|
||||||
b2 = vec[1] *vec[1];
|
|
||||||
c2 = vec[2] *vec[2];
|
|
||||||
|
|
||||||
ab = vec[0]*vec[1];
|
|
||||||
ac = vec[0]*vec[2];
|
|
||||||
bc = vec[1]*vec[2];
|
|
||||||
|
|
||||||
MT_Vector3 temp = vec*offset;
|
|
||||||
ad = temp[0];
|
|
||||||
bd = temp[1];
|
|
||||||
cd = temp[2];
|
|
||||||
|
|
||||||
d2 = offset*offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
MT_Matrix3x3
|
|
||||||
Tensor(
|
|
||||||
) const {
|
|
||||||
// return a symmetric matrix
|
|
||||||
|
|
||||||
return MT_Matrix3x3(
|
|
||||||
a2,ab,ac,
|
|
||||||
ab,b2,bc,
|
|
||||||
ac,bc,c2
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
MT_Vector3
|
|
||||||
Vector(
|
|
||||||
) const {
|
|
||||||
return MT_Vector3(ad, bd, cd);
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
Clear(
|
|
||||||
MT_Scalar val=0.0
|
|
||||||
) {
|
|
||||||
a2=ab=ac=ad=b2=bc=bd=c2=cd=d2=val;
|
|
||||||
};
|
|
||||||
|
|
||||||
LOD_Quadric &
|
|
||||||
operator=(
|
|
||||||
const LOD_Quadric& Q
|
|
||||||
) {
|
|
||||||
|
|
||||||
a2 = Q.a2; ab = Q.ab; ac = Q.ac; ad = Q.ad;
|
|
||||||
b2 = Q.b2; bc = Q.bc; bd = Q.bd;
|
|
||||||
c2 = Q.c2; cd = Q.cd;
|
|
||||||
d2 = Q.d2;
|
|
||||||
return *this;
|
|
||||||
};
|
|
||||||
|
|
||||||
LOD_Quadric&
|
|
||||||
operator+=(
|
|
||||||
const LOD_Quadric& Q
|
|
||||||
) {
|
|
||||||
a2 += Q.a2; ab += Q.ab; ac += Q.ac; ad += Q.ad;
|
|
||||||
b2 += Q.b2; bc += Q.bc; bd += Q.bd;
|
|
||||||
c2 += Q.c2; cd += Q.cd;
|
|
||||||
d2 += Q.d2;
|
|
||||||
return *this;
|
|
||||||
};
|
|
||||||
|
|
||||||
LOD_Quadric&
|
|
||||||
operator*=(
|
|
||||||
const MT_Scalar & s
|
|
||||||
) {
|
|
||||||
a2 *= s; ab *= s; ac *= s; ad *= s;
|
|
||||||
b2 *= s; bc *= s; bd *= s;
|
|
||||||
c2 *= s; cd *= s;
|
|
||||||
d2 *= s;
|
|
||||||
return *this;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
MT_Scalar
|
|
||||||
Evaluate(
|
|
||||||
const MT_Vector3 &v
|
|
||||||
) const {
|
|
||||||
// compute the LOD_Quadric error
|
|
||||||
|
|
||||||
return v[0]*v[0]*a2 + 2*v[0]*v[1]*ab + 2*v[0]*v[2]*ac + 2*v[0]*ad
|
|
||||||
+v[1]*v[1]*b2 + 2*v[1]*v[2]*bc + 2*v[1]*bd
|
|
||||||
+v[2]*v[2]*c2 + 2*v[2]*cd
|
|
||||||
+ d2;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool
|
|
||||||
Optimize(
|
|
||||||
MT_Vector3& v
|
|
||||||
) const {
|
|
||||||
|
|
||||||
MT_Scalar det = Tensor().determinant();
|
|
||||||
if (MT_fuzzyZero(det)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
v = -((Tensor().inverse()) * Vector());
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,279 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_QuadricEditor.cpp
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "LOD_QuadricEditor.h"
|
|
||||||
#include "LOD_ExternNormalEditor.h"
|
|
||||||
|
|
||||||
// Creation
|
|
||||||
///////////
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
|
|
||||||
LOD_QuadricEditor::
|
|
||||||
LOD_QuadricEditor(
|
|
||||||
LOD_ManMesh2 &mesh
|
|
||||||
) :
|
|
||||||
m_quadrics(NULL),
|
|
||||||
m_mesh(mesh)
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
LOD_QuadricEditor *
|
|
||||||
LOD_QuadricEditor::
|
|
||||||
New(
|
|
||||||
LOD_ManMesh2 &mesh
|
|
||||||
){
|
|
||||||
//same number of quadrics as vertices in the mesh
|
|
||||||
|
|
||||||
MEM_SmartPtr<LOD_QuadricEditor> output(new LOD_QuadricEditor(mesh));
|
|
||||||
|
|
||||||
if (output == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return output.Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Property editor interface
|
|
||||||
////////////////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_QuadricEditor::
|
|
||||||
Remove(
|
|
||||||
std::vector<LOD_VertexInd> &sorted_vertices
|
|
||||||
){
|
|
||||||
vector<LOD_Quadric> & quadrics = *m_quadrics;
|
|
||||||
|
|
||||||
vector<LOD_VertexInd>::const_iterator it_start = sorted_vertices.begin();
|
|
||||||
vector<LOD_VertexInd>::const_iterator it_end = sorted_vertices.end();
|
|
||||||
|
|
||||||
for (; it_start != it_end; ++it_start) {
|
|
||||||
|
|
||||||
if (quadrics.size() > 0) {
|
|
||||||
LOD_Quadric temp = quadrics[*it_start];
|
|
||||||
|
|
||||||
quadrics[*it_start] = quadrics.back();
|
|
||||||
quadrics.back() = temp;
|
|
||||||
|
|
||||||
quadrics.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Editor specific methods
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
bool
|
|
||||||
LOD_QuadricEditor::
|
|
||||||
BuildQuadrics(
|
|
||||||
LOD_ExternNormalEditor& normal_editor,
|
|
||||||
bool preserve_boundaries
|
|
||||||
){
|
|
||||||
if (m_quadrics != NULL) delete(m_quadrics);
|
|
||||||
|
|
||||||
m_quadrics =new vector<LOD_Quadric> (m_mesh.VertexSet().size());
|
|
||||||
if (m_quadrics == NULL) return false;
|
|
||||||
|
|
||||||
// iterate through the face set of the mesh
|
|
||||||
// compute a quadric based upon that face and
|
|
||||||
// add it to each of it's vertices quadrics.
|
|
||||||
|
|
||||||
const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
|
|
||||||
const vector<LOD_Vertex> &verts = m_mesh.VertexSet();
|
|
||||||
vector<LOD_Edge> &edges = m_mesh.EdgeSet();
|
|
||||||
|
|
||||||
const vector<MT_Vector3> &normals = normal_editor.Normals();
|
|
||||||
vector<MT_Vector3>::const_iterator normal_it = normals.begin();
|
|
||||||
|
|
||||||
vector<LOD_TriFace>::const_iterator face_it = faces.begin();
|
|
||||||
vector<LOD_TriFace>::const_iterator face_end = faces.end();
|
|
||||||
|
|
||||||
vector<LOD_Quadric> & quadrics = *m_quadrics;
|
|
||||||
|
|
||||||
|
|
||||||
for (; face_it != face_end; ++face_it, ++normal_it) {
|
|
||||||
|
|
||||||
MT_Vector3 normal = *normal_it;
|
|
||||||
MT_Scalar offset = -normal.dot(verts[face_it->m_verts[0]].pos);
|
|
||||||
|
|
||||||
LOD_Quadric q(normal,offset);
|
|
||||||
|
|
||||||
quadrics[face_it->m_verts[0]] += q;
|
|
||||||
quadrics[face_it->m_verts[1]] += q;
|
|
||||||
quadrics[face_it->m_verts[2]] += q;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (preserve_boundaries) {
|
|
||||||
|
|
||||||
// iterate through the edge set and add a boundary quadric to
|
|
||||||
// each of the boundary edges vertices.
|
|
||||||
|
|
||||||
vector<LOD_Edge>::const_iterator edge_it = edges.begin();
|
|
||||||
vector<LOD_Edge>::const_iterator edge_end = edges.end();
|
|
||||||
|
|
||||||
for (; edge_it != edge_end; ++edge_it) {
|
|
||||||
if (edge_it->BoundaryEdge()) {
|
|
||||||
|
|
||||||
// compute a plane perpendicular to the edge and the normal
|
|
||||||
// of the edges single polygon.
|
|
||||||
const MT_Vector3 & v0 = verts[edge_it->m_verts[0]].pos;
|
|
||||||
const MT_Vector3 & v1 = verts[edge_it->m_verts[1]].pos;
|
|
||||||
|
|
||||||
MT_Vector3 edge_vector = v1 - v0;
|
|
||||||
|
|
||||||
LOD_FaceInd edge_face = edge_it->OpFace(LOD_EdgeInd::Empty());
|
|
||||||
edge_vector = edge_vector.cross(normals[edge_face]);
|
|
||||||
|
|
||||||
if (!edge_vector.fuzzyZero()) {
|
|
||||||
edge_vector.normalize();
|
|
||||||
|
|
||||||
LOD_Quadric boundary_q(edge_vector, - edge_vector.dot(v0));
|
|
||||||
boundary_q *= 100;
|
|
||||||
|
|
||||||
quadrics[edge_it->m_verts[0]] += boundary_q;
|
|
||||||
quadrics[edge_it->m_verts[1]] += boundary_q;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// initiate the heap keys of the edges by computing the edge costs.
|
|
||||||
|
|
||||||
vector<LOD_Edge>::iterator edge_it = edges.begin();
|
|
||||||
vector<LOD_Edge>::const_iterator edge_end = edges.end();
|
|
||||||
|
|
||||||
for (; edge_it != edge_end; ++edge_it) {
|
|
||||||
|
|
||||||
MT_Vector3 target = TargetVertex(*edge_it);
|
|
||||||
|
|
||||||
LOD_Edge &e = *edge_it;
|
|
||||||
const LOD_Quadric &q0 = quadrics[e.m_verts[0]];
|
|
||||||
const LOD_Quadric &q1 = quadrics[e.m_verts[1]];
|
|
||||||
|
|
||||||
e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
MT_Vector3
|
|
||||||
LOD_QuadricEditor::
|
|
||||||
TargetVertex(
|
|
||||||
LOD_Edge & e
|
|
||||||
){
|
|
||||||
|
|
||||||
// compute an edge contration target for edge ei
|
|
||||||
// this is computed by summing it's vertices quadrics and
|
|
||||||
// optimizing the result.
|
|
||||||
vector<LOD_Vertex> &verts = m_mesh.VertexSet();
|
|
||||||
|
|
||||||
vector<LOD_Quadric> &quadrics = *m_quadrics;
|
|
||||||
|
|
||||||
LOD_VertexInd v0 = e.m_verts[0];
|
|
||||||
LOD_VertexInd v1 = e.m_verts[1];
|
|
||||||
|
|
||||||
LOD_Quadric q0 = quadrics[v0];
|
|
||||||
q0 += quadrics[v1];
|
|
||||||
|
|
||||||
MT_Vector3 result;
|
|
||||||
|
|
||||||
if (q0.Optimize(result)) {
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
// the quadric was degenerate -> just take the average of
|
|
||||||
// v0 and v1
|
|
||||||
|
|
||||||
return ((verts[v0].pos + verts[v1].pos) * 0.5);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
LOD_QuadricEditor::
|
|
||||||
ComputeEdgeCosts(
|
|
||||||
vector<LOD_EdgeInd> &edges
|
|
||||||
){
|
|
||||||
|
|
||||||
// for each we compute the target vertex and then compute
|
|
||||||
// the quadric error e = Q1(v') + Q2(v')
|
|
||||||
vector<LOD_Edge> &edge_set = m_mesh.EdgeSet();
|
|
||||||
|
|
||||||
vector<LOD_Quadric> &quadrics = *m_quadrics;
|
|
||||||
|
|
||||||
vector<LOD_EdgeInd>::const_iterator edge_it = edges.begin();
|
|
||||||
vector<LOD_EdgeInd>::const_iterator edge_end = edges.end();
|
|
||||||
|
|
||||||
for (; edge_it != edge_end; ++edge_it) {
|
|
||||||
|
|
||||||
MT_Vector3 target = TargetVertex(edge_set[*edge_it]);
|
|
||||||
|
|
||||||
LOD_Edge &e = edge_set[*edge_it];
|
|
||||||
LOD_Quadric q0 = quadrics[e.m_verts[0]];
|
|
||||||
const LOD_Quadric &q1 = quadrics[e.m_verts[1]];
|
|
||||||
|
|
||||||
e.HeapKey() = -float(q0.Evaluate(target) + q1.Evaluate(target));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_QuadricEditor.h
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __LOD_QUADRICEDITOR_H__
|
|
||||||
#define __LOD_QUADRICEDITOR_H__
|
|
||||||
|
|
||||||
#include "MEM_NonCopyable.h"
|
|
||||||
#include "LOD_ManMesh2.h"
|
|
||||||
#include "MT_Vector3.h"
|
|
||||||
#include "LOD_Quadric.h"
|
|
||||||
|
|
||||||
class LOD_ExternNormalEditor;
|
|
||||||
|
|
||||||
|
|
||||||
class LOD_QuadricEditor : public MEM_NonCopyable
|
|
||||||
{
|
|
||||||
|
|
||||||
public :
|
|
||||||
|
|
||||||
// Creation
|
|
||||||
///////////
|
|
||||||
|
|
||||||
static
|
|
||||||
LOD_QuadricEditor *
|
|
||||||
New(
|
|
||||||
LOD_ManMesh2 &mesh
|
|
||||||
);
|
|
||||||
|
|
||||||
// Property editor interface
|
|
||||||
////////////////////////////
|
|
||||||
|
|
||||||
void
|
|
||||||
Remove(
|
|
||||||
std::vector<LOD_VertexInd> &sorted_vertices
|
|
||||||
);
|
|
||||||
|
|
||||||
void
|
|
||||||
Update(
|
|
||||||
std::vector<LOD_FaceInd> &sorted_vertices
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
std::vector<LOD_Quadric> &
|
|
||||||
Quadrics(
|
|
||||||
) const {
|
|
||||||
return *m_quadrics;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Editor specific methods
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
bool
|
|
||||||
BuildQuadrics(
|
|
||||||
LOD_ExternNormalEditor& normal_editor,
|
|
||||||
bool preserve_boundaries
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ComputeEdgeCosts(
|
|
||||||
std::vector<LOD_EdgeInd> &edges
|
|
||||||
);
|
|
||||||
|
|
||||||
MT_Vector3
|
|
||||||
TargetVertex(
|
|
||||||
LOD_Edge &e
|
|
||||||
);
|
|
||||||
|
|
||||||
~LOD_QuadricEditor(
|
|
||||||
){
|
|
||||||
delete(m_quadrics);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
std::vector<LOD_Quadric> * m_quadrics;
|
|
||||||
|
|
||||||
LOD_ManMesh2 &m_mesh;
|
|
||||||
|
|
||||||
private :
|
|
||||||
|
|
||||||
LOD_QuadricEditor(LOD_ManMesh2 &mesh);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2
|
|
||||||
* of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*
|
|
||||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* The Original Code is: all of this file.
|
|
||||||
*
|
|
||||||
* Contributor(s): none yet.
|
|
||||||
*
|
|
||||||
* ***** END GPL LICENSE BLOCK *****
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** \file decimation/intern/LOD_decimation.cpp
|
|
||||||
* \ingroup decimation
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// implementation of external c api
|
|
||||||
#include "../extern/LOD_decimation.h"
|
|
||||||
#include "LOD_DecimationClass.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
int
|
|
||||||
LOD_LoadMesh(
|
|
||||||
LOD_Decimation_InfoPtr info
|
|
||||||
) {
|
|
||||||
if (info == NULL) return 0;
|
|
||||||
if (
|
|
||||||
info->vertex_buffer == NULL ||
|
|
||||||
info->vertex_normal_buffer == NULL ||
|
|
||||||
info->triangle_index_buffer == NULL
|
|
||||||
) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// create the intern object to hold all
|
|
||||||
// the decimation classes
|
|
||||||
|
|
||||||
MEM_SmartPtr<LOD_DecimationClass> intern(LOD_DecimationClass::New(info));
|
|
||||||
|
|
||||||
if (intern == NULL) return 0;
|
|
||||||
|
|
||||||
MEM_SmartPtr<vector<LOD_Vertex> > intern_vertex_buffer(new vector<LOD_Vertex>(info->vertex_num));
|
|
||||||
if (intern_vertex_buffer == NULL) return 0;
|
|
||||||
|
|
||||||
vector<LOD_Vertex>::iterator intern_vertex_it(intern_vertex_buffer->begin());
|
|
||||||
|
|
||||||
// now load in the vertices to the mesh
|
|
||||||
|
|
||||||
const int vertex_stride = 3;
|
|
||||||
|
|
||||||
float * vertex_ptr = info->vertex_buffer;
|
|
||||||
const float * vertex_end = vertex_ptr + info->vertex_num*vertex_stride;
|
|
||||||
|
|
||||||
LOD_ManMesh2 &mesh = intern->Mesh();
|
|
||||||
|
|
||||||
for (;vertex_ptr < vertex_end; vertex_ptr += vertex_stride,++intern_vertex_it) {
|
|
||||||
intern_vertex_it->pos = MT_Vector3(vertex_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh.SetVertices(intern_vertex_buffer);
|
|
||||||
|
|
||||||
// load in the triangles
|
|
||||||
|
|
||||||
const int triangle_stride = 3;
|
|
||||||
|
|
||||||
int * triangle_ptr = info->triangle_index_buffer;
|
|
||||||
const int * triangle_end = triangle_ptr + info->face_num*triangle_stride;
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
for (;triangle_ptr < triangle_end; triangle_ptr += triangle_stride) {
|
|
||||||
mesh.AddTriangle(triangle_ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (...) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ok we have built the mesh
|
|
||||||
|
|
||||||
intern->m_e_decimation_state = LOD_DecimationClass::e_loaded;
|
|
||||||
|
|
||||||
info->intern = (void *) (intern.Release());
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
LOD_PreprocessMesh(
|
|
||||||
LOD_Decimation_InfoPtr info
|
|
||||||
) {
|
|
||||||
if (info == NULL) return 0;
|
|
||||||
if (info->intern == NULL) return 0;
|
|
||||||
|
|
||||||
LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern;
|
|
||||||
if (intern->m_e_decimation_state != LOD_DecimationClass::e_loaded) return 0;
|
|
||||||
|
|
||||||
// arm the various internal classes so that we are ready to step
|
|
||||||
// through decimation
|
|
||||||
|
|
||||||
intern->FaceEditor().BuildNormals();
|
|
||||||
if (intern->Decimator().Arm() == false) return 0;
|
|
||||||
|
|
||||||
// ok preprocessing done
|
|
||||||
intern->m_e_decimation_state = LOD_DecimationClass::e_preprocessed;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
LOD_CollapseEdge(
|
|
||||||
LOD_Decimation_InfoPtr info
|
|
||||||
){
|
|
||||||
if (info == NULL) return 0;
|
|
||||||
if (info->intern == NULL) return 0;
|
|
||||||
LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern;
|
|
||||||
if (intern->m_e_decimation_state != LOD_DecimationClass::e_preprocessed) return 0;
|
|
||||||
|
|
||||||
bool step_result = intern->Decimator().Step();
|
|
||||||
|
|
||||||
return step_result == true ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
LOD_FreeDecimationData(
|
|
||||||
LOD_Decimation_InfoPtr info
|
|
||||||
){
|
|
||||||
if (info == NULL) return 0;
|
|
||||||
if (info->intern == NULL) return 0;
|
|
||||||
LOD_DecimationClass *intern = (LOD_DecimationClass *) info->intern;
|
|
||||||
delete(intern);
|
|
||||||
info->intern = NULL;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
@@ -356,12 +356,6 @@ if(WITH_MOD_OCEANSIM)
|
|||||||
add_definitions(-DWITH_OCEANSIM)
|
add_definitions(-DWITH_OCEANSIM)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_MOD_DECIMATE)
|
|
||||||
list(APPEND INC
|
|
||||||
../../../intern/decimation/extern
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_MOD_BOOLEAN)
|
if(WITH_MOD_BOOLEAN)
|
||||||
list(APPEND INC
|
list(APPEND INC
|
||||||
../../../intern/bsp/extern
|
../../../intern/bsp/extern
|
||||||
|
@@ -10,7 +10,7 @@ sources_mask = env.Glob('intern/mask*.c')
|
|||||||
|
|
||||||
incs = '. #/intern/guardedalloc #/intern/memutil'
|
incs = '. #/intern/guardedalloc #/intern/memutil'
|
||||||
incs += ' ../blenlib ../blenfont ../makesdna ../windowmanager'
|
incs += ' ../blenlib ../blenfont ../makesdna ../windowmanager'
|
||||||
incs += ' ../render/extern/include #/intern/decimation/extern ../makesrna'
|
incs += ' ../render/extern/include ../makesrna'
|
||||||
incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers'
|
incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers'
|
||||||
incs += ' #/intern/iksolver/extern ../blenloader'
|
incs += ' #/intern/iksolver/extern ../blenloader'
|
||||||
incs += ' #/extern/bullet2/src'
|
incs += ' #/extern/bullet2/src'
|
||||||
|
@@ -117,13 +117,6 @@ if(WITH_MOD_REMESH)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_MOD_DECIMATE)
|
|
||||||
add_definitions(-DWITH_MOD_DECIMATE)
|
|
||||||
list(APPEND INC
|
|
||||||
../../../intern/decimation/extern
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_MOD_FLUID)
|
if(WITH_MOD_FLUID)
|
||||||
add_definitions(-DWITH_MOD_FLUID)
|
add_definitions(-DWITH_MOD_FLUID)
|
||||||
endif()
|
endif()
|
||||||
|
@@ -4,7 +4,7 @@ Import ('env')
|
|||||||
sources = env.Glob('intern/*.c')
|
sources = env.Glob('intern/*.c')
|
||||||
|
|
||||||
incs = '. ./intern'
|
incs = '. ./intern'
|
||||||
incs += ' #/intern/guardedalloc #/intern/decimation/extern #/intern/bsp/extern #/intern/elbeem/extern #/extern/glew/include'
|
incs += ' #/intern/guardedalloc #/intern/bsp/extern #/intern/elbeem/extern #/extern/glew/include'
|
||||||
incs += ' ../render/extern/include ../blenloader ../bmesh'
|
incs += ' ../render/extern/include ../blenloader ../bmesh'
|
||||||
incs += ' ../include ../blenlib ../blenfont ../makesdna ../makesrna ../blenkernel ../blenkernel/intern'
|
incs += ' ../include ../blenlib ../blenfont ../makesdna ../makesrna ../blenkernel ../blenkernel/intern'
|
||||||
incs += ' ../gpu'
|
incs += ' ../gpu'
|
||||||
@@ -20,9 +20,6 @@ if env['WITH_BF_REMESH']:
|
|||||||
incs += ' #/intern/dualcon'
|
incs += ' #/intern/dualcon'
|
||||||
defs.append('WITH_MOD_REMESH')
|
defs.append('WITH_MOD_REMESH')
|
||||||
|
|
||||||
if env ['WITH_BF_DECIMATE']:
|
|
||||||
defs.append('WITH_MOD_DECIMATE')
|
|
||||||
|
|
||||||
if env['WITH_BF_FLUID']:
|
if env['WITH_BF_FLUID']:
|
||||||
defs.append('WITH_MOD_FLUID')
|
defs.append('WITH_MOD_FLUID')
|
||||||
|
|
||||||
|
@@ -32,7 +32,6 @@
|
|||||||
* \ingroup modifiers
|
* \ingroup modifiers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "DNA_meshdata_types.h"
|
#include "DNA_meshdata_types.h"
|
||||||
|
|
||||||
#include "BLI_math.h"
|
#include "BLI_math.h"
|
||||||
@@ -48,19 +47,12 @@
|
|||||||
#include "BKE_cdderivedmesh.h"
|
#include "BKE_cdderivedmesh.h"
|
||||||
|
|
||||||
#include "BKE_tessmesh.h"
|
#include "BKE_tessmesh.h"
|
||||||
|
#include "bmesh.h"
|
||||||
|
|
||||||
// #define USE_TIMEIT
|
|
||||||
|
|
||||||
/* testing only! - Campbell */
|
|
||||||
#define USE_DECIMATE_BMESH
|
|
||||||
#ifdef USE_TIMEIT
|
#ifdef USE_TIMEIT
|
||||||
# include "PIL_time.h"
|
# include "PIL_time.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_MOD_DECIMATE
|
|
||||||
#include "LOD_decimation.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "MOD_util.h"
|
#include "MOD_util.h"
|
||||||
|
|
||||||
static void initData(ModifierData *md)
|
static void initData(ModifierData *md)
|
||||||
@@ -78,11 +70,6 @@ static void copyData(ModifierData *md, ModifierData *target)
|
|||||||
tdmd->percent = dmd->percent;
|
tdmd->percent = dmd->percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_MOD_DECIMATE
|
|
||||||
#ifdef USE_DECIMATE_BMESH
|
|
||||||
|
|
||||||
#include "bmesh.h"
|
|
||||||
|
|
||||||
static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
|
static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
|
||||||
DerivedMesh *derivedData,
|
DerivedMesh *derivedData,
|
||||||
ModifierApplyFlag UNUSED(flag))
|
ModifierApplyFlag UNUSED(flag))
|
||||||
@@ -123,143 +110,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
|
|
||||||
DerivedMesh *derivedData,
|
|
||||||
ModifierApplyFlag UNUSED(flag))
|
|
||||||
{
|
|
||||||
DecimateModifierData *dmd = (DecimateModifierData *) md;
|
|
||||||
DerivedMesh *dm = derivedData, *result = NULL;
|
|
||||||
MVert *mvert;
|
|
||||||
MFace *mface;
|
|
||||||
LOD_Decimation_Info lod;
|
|
||||||
int totvert, totface;
|
|
||||||
int a, numTris;
|
|
||||||
|
|
||||||
// TIMEIT_START(decim);
|
|
||||||
|
|
||||||
DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
|
|
||||||
|
|
||||||
mvert = dm->getVertArray(dm);
|
|
||||||
mface = dm->getTessFaceArray(dm);
|
|
||||||
totvert = dm->getNumVerts(dm);
|
|
||||||
totface = dm->getNumTessFaces(dm);
|
|
||||||
|
|
||||||
numTris = 0;
|
|
||||||
for (a = 0; a < totface; a++) {
|
|
||||||
MFace *mf = &mface[a];
|
|
||||||
numTris++;
|
|
||||||
if (mf->v4) numTris++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numTris < 3) {
|
|
||||||
modifier_setError(md, "%s", TIP_("Modifier requires more than 3 input faces (triangles)"));
|
|
||||||
dm = CDDM_copy(dm);
|
|
||||||
return dm;
|
|
||||||
}
|
|
||||||
|
|
||||||
lod.vertex_buffer = MEM_mallocN(3 * sizeof(float) * totvert, "vertices");
|
|
||||||
lod.vertex_normal_buffer = MEM_mallocN(3 * sizeof(float) * totvert, "normals");
|
|
||||||
lod.triangle_index_buffer = MEM_mallocN(3 * sizeof(int) * numTris, "trias");
|
|
||||||
lod.vertex_num = totvert;
|
|
||||||
lod.face_num = numTris;
|
|
||||||
|
|
||||||
for (a = 0; a < totvert; a++) {
|
|
||||||
MVert *mv = &mvert[a];
|
|
||||||
float *vbCo = &lod.vertex_buffer[a * 3];
|
|
||||||
float *vbNo = &lod.vertex_normal_buffer[a * 3];
|
|
||||||
|
|
||||||
copy_v3_v3(vbCo, mv->co);
|
|
||||||
normal_short_to_float_v3(vbNo, mv->no);
|
|
||||||
}
|
|
||||||
|
|
||||||
numTris = 0;
|
|
||||||
for (a = 0; a < totface; a++) {
|
|
||||||
MFace *mf = &mface[a];
|
|
||||||
int *tri = &lod.triangle_index_buffer[3 * numTris++];
|
|
||||||
tri[0] = mf->v1;
|
|
||||||
tri[1] = mf->v2;
|
|
||||||
tri[2] = mf->v3;
|
|
||||||
|
|
||||||
if (mf->v4) {
|
|
||||||
tri = &lod.triangle_index_buffer[3 * numTris++];
|
|
||||||
tri[0] = mf->v1;
|
|
||||||
tri[1] = mf->v3;
|
|
||||||
tri[2] = mf->v4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dmd->faceCount = 0;
|
|
||||||
if (LOD_LoadMesh(&lod) ) {
|
|
||||||
if (LOD_PreprocessMesh(&lod) ) {
|
|
||||||
/* we assume the decim_faces tells how much to reduce */
|
|
||||||
|
|
||||||
while (lod.face_num > numTris * dmd->percent) {
|
|
||||||
if (LOD_CollapseEdge(&lod) == 0) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lod.vertex_num > 2) {
|
|
||||||
result = CDDM_new(lod.vertex_num, 0, lod.face_num, 0, 0);
|
|
||||||
dmd->faceCount = lod.face_num;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result = CDDM_new(lod.vertex_num, 0, 0, 0, 0);
|
|
||||||
|
|
||||||
mvert = CDDM_get_verts(result);
|
|
||||||
for (a = 0; a < lod.vertex_num; a++) {
|
|
||||||
MVert *mv = &mvert[a];
|
|
||||||
float *vbCo = &lod.vertex_buffer[a * 3];
|
|
||||||
|
|
||||||
copy_v3_v3(mv->co, vbCo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lod.vertex_num > 2) {
|
|
||||||
mface = CDDM_get_tessfaces(result);
|
|
||||||
for (a = 0; a < lod.face_num; a++) {
|
|
||||||
MFace *mf = &mface[a];
|
|
||||||
int *tri = &lod.triangle_index_buffer[a * 3];
|
|
||||||
mf->v1 = tri[0];
|
|
||||||
mf->v2 = tri[1];
|
|
||||||
mf->v3 = tri[2];
|
|
||||||
test_index_face(mf, NULL, 0, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CDDM_calc_edges_tessface(result);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
modifier_setError(md, "%s", TIP_("Out of memory"));
|
|
||||||
|
|
||||||
LOD_FreeDecimationData(&lod);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
modifier_setError(md, "%s", TIP_("Non-manifold mesh as input"));
|
|
||||||
|
|
||||||
MEM_freeN(lod.vertex_buffer);
|
|
||||||
MEM_freeN(lod.vertex_normal_buffer);
|
|
||||||
MEM_freeN(lod.triangle_index_buffer);
|
|
||||||
|
|
||||||
// TIMEIT_END(decim);
|
|
||||||
|
|
||||||
if (result) {
|
|
||||||
CDDM_tessfaces_to_faces(result); /*builds ngon faces from tess (mface) faces*/
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return dm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // USE_DECIMATE_BMESH
|
|
||||||
#else // WITH_MOD_DECIMATE
|
|
||||||
static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
|
|
||||||
DerivedMesh *derivedData,
|
|
||||||
ModifierApplyFlag UNUSED(flag))
|
|
||||||
{
|
|
||||||
return derivedData;
|
|
||||||
}
|
|
||||||
#endif // WITH_MOD_DECIMATE
|
|
||||||
|
|
||||||
ModifierTypeInfo modifierType_Decimate = {
|
ModifierTypeInfo modifierType_Decimate = {
|
||||||
/* name */ "Decimate",
|
/* name */ "Decimate",
|
||||||
/* structName */ "DecimateModifierData",
|
/* structName */ "DecimateModifierData",
|
||||||
|
@@ -169,10 +169,6 @@ endif()
|
|||||||
|
|
||||||
list(APPEND BLENDER_SORTED_LIBS extern_colamd)
|
list(APPEND BLENDER_SORTED_LIBS extern_colamd)
|
||||||
|
|
||||||
if(WITH_MOD_DECIMATE)
|
|
||||||
list(APPEND BLENDER_SORTED_LIBS bf_intern_decimate)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_MOD_BOOLEAN)
|
if(WITH_MOD_BOOLEAN)
|
||||||
list(APPEND BLENDER_SORTED_LIBS bf_intern_bsp)
|
list(APPEND BLENDER_SORTED_LIBS bf_intern_bsp)
|
||||||
list(APPEND BLENDER_SORTED_LIBS bf_intern_moto)
|
list(APPEND BLENDER_SORTED_LIBS bf_intern_moto)
|
||||||
|
@@ -60,7 +60,6 @@ struct Image;
|
|||||||
struct ImageUser;
|
struct ImageUser;
|
||||||
struct KeyingSet;
|
struct KeyingSet;
|
||||||
struct KeyingSetInfo;
|
struct KeyingSetInfo;
|
||||||
struct LOD_Decimation_Info;
|
|
||||||
struct MCol;
|
struct MCol;
|
||||||
struct MTex;
|
struct MTex;
|
||||||
struct Main;
|
struct Main;
|
||||||
|
@@ -898,7 +898,6 @@ endif()
|
|||||||
bf_imbuf_dds
|
bf_imbuf_dds
|
||||||
bf_collada
|
bf_collada
|
||||||
bf_intern_bsp
|
bf_intern_bsp
|
||||||
bf_intern_decimate
|
|
||||||
bf_intern_elbeem
|
bf_intern_elbeem
|
||||||
bf_intern_memutil
|
bf_intern_memutil
|
||||||
bf_intern_guardedalloc
|
bf_intern_guardedalloc
|
||||||
|
@@ -34,7 +34,6 @@
|
|||||||
# pragma warning (disable:4786)
|
# pragma warning (disable:4786)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "CTR_Map.h"
|
|
||||||
#include "RAS_MaterialBucket.h"
|
#include "RAS_MaterialBucket.h"
|
||||||
#include "STR_HashedString.h"
|
#include "STR_HashedString.h"
|
||||||
#include "RAS_MeshObject.h"
|
#include "RAS_MeshObject.h"
|
||||||
|
@@ -34,7 +34,6 @@
|
|||||||
|
|
||||||
#include "MT_Transform.h"
|
#include "MT_Transform.h"
|
||||||
#include "RAS_MaterialBucket.h"
|
#include "RAS_MaterialBucket.h"
|
||||||
#include "CTR_Map.h"
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user