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:
parent
91ceb8f552
commit
226a5ee834
|
@ -188,7 +188,6 @@ unset(PLATFORM_DEFAULT)
|
|||
# Modifiers
|
||||
option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid 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_REMESH "Enable Remesh Modifier" ON)
|
||||
option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF)
|
||||
|
@ -2126,7 +2125,6 @@ if(FIRST_RUN)
|
|||
info_cfg_text("Modifiers:")
|
||||
info_cfg_option(WITH_MOD_BOOLEAN)
|
||||
info_cfg_option(WITH_MOD_REMESH)
|
||||
info_cfg_option(WITH_MOD_DECIMATE)
|
||||
info_cfg_option(WITH_MOD_FLUID)
|
||||
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_OCEANSIM'] = 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_REMESH'] = False
|
||||
target_env_defs['WITH_BF_PYTHON'] = False
|
||||
|
|
|
@ -2,11 +2,9 @@ import os
|
|||
|
||||
IGNORE = (
|
||||
"/test/",
|
||||
"/decimate_glut_test/",
|
||||
"/BSP_GhostTest/",
|
||||
"/release/",
|
||||
"/xembed/",
|
||||
"/decimation/intern/future/",
|
||||
"/TerraplayNetwork/",
|
||||
"/ik_glut_test/",
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ set(WITH_JACK OFF CACHE FORCE BOOL)
|
|||
set(WITH_LZMA OFF CACHE FORCE BOOL)
|
||||
set(WITH_LZO 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_REMESH OFF CACHE FORCE BOOL)
|
||||
set(WITH_MOD_SMOKE OFF CACHE FORCE BOOL)
|
||||
|
|
|
@ -152,7 +152,6 @@ def validate_arguments(args, bc):
|
|||
'WITH_BF_RAYOPTIMIZATION',
|
||||
'BF_RAYOPTIMIZATION_SSE_FLAGS',
|
||||
'WITH_BF_FLUID',
|
||||
'WITH_BF_DECIMATE',
|
||||
'WITH_BF_BOOLEAN',
|
||||
'WITH_BF_REMESH',
|
||||
'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)', ''),
|
||||
|
||||
(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_REMESH', 'Build with remesh modifier', True)),
|
||||
(BoolVariable('WITH_BF_OCEANSIM', 'Build with ocean simulation', False)),
|
||||
|
|
|
@ -49,11 +49,6 @@ if(WITH_MOD_SMOKE)
|
|||
add_subdirectory(smoke)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_DECIMATE)
|
||||
add_subdirectory(container)
|
||||
add_subdirectory(decimation)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_BOOLEAN)
|
||||
add_subdirectory(bsp)
|
||||
endif()
|
||||
|
|
|
@ -6,9 +6,7 @@ SConscript(['audaspace/SConscript',
|
|||
'ghost/SConscript',
|
||||
'guardedalloc/SConscript',
|
||||
'moto/SConscript',
|
||||
'container/SConscript',
|
||||
'memutil/SConscript/',
|
||||
'decimation/SConscript',
|
||||
'iksolver/SConscript',
|
||||
'itasc/SConscript',
|
||||
'opencolorio/SConscript',
|
||||
|
@ -17,6 +15,9 @@ SConscript(['audaspace/SConscript',
|
|||
'smoke/SConscript',
|
||||
'raskter/SConscript'])
|
||||
|
||||
# currently only contains headers
|
||||
# SConscript('container/SConscript')
|
||||
|
||||
if env ['WITH_BF_REMESH']:
|
||||
SConscript(['dualcon/SConscript'])
|
||||
|
||||
|
|
|
@ -33,14 +33,9 @@ set(INC_SYS
|
|||
)
|
||||
|
||||
set(SRC
|
||||
intern/CTR_List.cpp
|
||||
|
||||
CTR_HashedPtr.h
|
||||
CTR_List.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}")
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
* \ingroup ctr
|
||||
*/
|
||||
|
||||
#ifndef CTR_HASHEDPTR_H
|
||||
#define CTR_HASHEDPTR_H
|
||||
#ifndef __CTR_HASHEDPTR_H__
|
||||
#define __CTR_HASHEDPTR_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -51,5 +51,5 @@ public:
|
|||
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
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CTR_MAP_H
|
||||
#define CTR_MAP_H
|
||||
#ifndef __CTR_MAP_H__
|
||||
#define __CTR_MAP_H__
|
||||
|
||||
template <class Key, class Value>
|
||||
class CTR_Map {
|
||||
|
@ -177,5 +176,4 @@ private:
|
|||
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] )
|
|
@ -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)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_DECIMATE)
|
||||
list(APPEND INC
|
||||
../../../intern/decimation/extern
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_BOOLEAN)
|
||||
list(APPEND INC
|
||||
../../../intern/bsp/extern
|
||||
|
|
|
@ -10,7 +10,7 @@ sources_mask = env.Glob('intern/mask*.c')
|
|||
|
||||
incs = '. #/intern/guardedalloc #/intern/memutil'
|
||||
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 += ' #/intern/iksolver/extern ../blenloader'
|
||||
incs += ' #/extern/bullet2/src'
|
||||
|
|
|
@ -117,13 +117,6 @@ if(WITH_MOD_REMESH)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_DECIMATE)
|
||||
add_definitions(-DWITH_MOD_DECIMATE)
|
||||
list(APPEND INC
|
||||
../../../intern/decimation/extern
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_FLUID)
|
||||
add_definitions(-DWITH_MOD_FLUID)
|
||||
endif()
|
||||
|
|
|
@ -4,7 +4,7 @@ Import ('env')
|
|||
sources = env.Glob('intern/*.c')
|
||||
|
||||
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 += ' ../include ../blenlib ../blenfont ../makesdna ../makesrna ../blenkernel ../blenkernel/intern'
|
||||
incs += ' ../gpu'
|
||||
|
@ -20,9 +20,6 @@ if env['WITH_BF_REMESH']:
|
|||
incs += ' #/intern/dualcon'
|
||||
defs.append('WITH_MOD_REMESH')
|
||||
|
||||
if env ['WITH_BF_DECIMATE']:
|
||||
defs.append('WITH_MOD_DECIMATE')
|
||||
|
||||
if env['WITH_BF_FLUID']:
|
||||
defs.append('WITH_MOD_FLUID')
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
* \ingroup modifiers
|
||||
*/
|
||||
|
||||
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
@ -48,19 +47,12 @@
|
|||
#include "BKE_cdderivedmesh.h"
|
||||
|
||||
#include "BKE_tessmesh.h"
|
||||
#include "bmesh.h"
|
||||
|
||||
// #define USE_TIMEIT
|
||||
|
||||
/* testing only! - Campbell */
|
||||
#define USE_DECIMATE_BMESH
|
||||
#ifdef USE_TIMEIT
|
||||
# include "PIL_time.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MOD_DECIMATE
|
||||
#include "LOD_decimation.h"
|
||||
#endif
|
||||
|
||||
#include "MOD_util.h"
|
||||
|
||||
static void initData(ModifierData *md)
|
||||
|
@ -78,11 +70,6 @@ static void copyData(ModifierData *md, ModifierData *target)
|
|||
tdmd->percent = dmd->percent;
|
||||
}
|
||||
|
||||
#ifdef WITH_MOD_DECIMATE
|
||||
#ifdef USE_DECIMATE_BMESH
|
||||
|
||||
#include "bmesh.h"
|
||||
|
||||
static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
|
||||
DerivedMesh *derivedData,
|
||||
ModifierApplyFlag UNUSED(flag))
|
||||
|
@ -123,143 +110,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob),
|
|||
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 = {
|
||||
/* name */ "Decimate",
|
||||
/* structName */ "DecimateModifierData",
|
||||
|
|
|
@ -169,10 +169,6 @@ endif()
|
|||
|
||||
list(APPEND BLENDER_SORTED_LIBS extern_colamd)
|
||||
|
||||
if(WITH_MOD_DECIMATE)
|
||||
list(APPEND BLENDER_SORTED_LIBS bf_intern_decimate)
|
||||
endif()
|
||||
|
||||
if(WITH_MOD_BOOLEAN)
|
||||
list(APPEND BLENDER_SORTED_LIBS bf_intern_bsp)
|
||||
list(APPEND BLENDER_SORTED_LIBS bf_intern_moto)
|
||||
|
|
|
@ -60,7 +60,6 @@ struct Image;
|
|||
struct ImageUser;
|
||||
struct KeyingSet;
|
||||
struct KeyingSetInfo;
|
||||
struct LOD_Decimation_Info;
|
||||
struct MCol;
|
||||
struct MTex;
|
||||
struct Main;
|
||||
|
|
|
@ -898,7 +898,6 @@ endif()
|
|||
bf_imbuf_dds
|
||||
bf_collada
|
||||
bf_intern_bsp
|
||||
bf_intern_decimate
|
||||
bf_intern_elbeem
|
||||
bf_intern_memutil
|
||||
bf_intern_guardedalloc
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
# pragma warning (disable:4786)
|
||||
#endif
|
||||
|
||||
#include "CTR_Map.h"
|
||||
#include "RAS_MaterialBucket.h"
|
||||
#include "STR_HashedString.h"
|
||||
#include "RAS_MeshObject.h"
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
|
||||
#include "MT_Transform.h"
|
||||
#include "RAS_MaterialBucket.h"
|
||||
#include "CTR_Map.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
Loading…
Reference in New Issue