403 lines
8.9 KiB
Text
403 lines
8.9 KiB
Text
|
/**
|
||
|
* PANDA 3D SOFTWARE
|
||
|
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||
|
*
|
||
|
* All use of this software is subject to the terms of the revised BSD
|
||
|
* license. You should have received a copy of this license along
|
||
|
* with this source code in a file named "LICENSE."
|
||
|
*
|
||
|
* @file eggPrimitive.I
|
||
|
* @author drose
|
||
|
* @date 1999-01-16
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE EggPrimitive::
|
||
|
EggPrimitive(const std::string &name): EggNode(name) {
|
||
|
_bface = false;
|
||
|
_connected_shading = S_unknown;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE EggPrimitive::
|
||
|
EggPrimitive(const EggPrimitive ©) :
|
||
|
EggNode(copy),
|
||
|
EggAttributes(copy),
|
||
|
EggRenderMode(copy),
|
||
|
_textures(copy._textures),
|
||
|
_material(copy._material),
|
||
|
_bface(copy._bface)
|
||
|
{
|
||
|
copy_vertices(copy);
|
||
|
_connected_shading = S_unknown;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE EggPrimitive &EggPrimitive::
|
||
|
operator = (const EggPrimitive ©) {
|
||
|
EggNode::operator = (copy);
|
||
|
EggAttributes::operator = (copy);
|
||
|
EggRenderMode::operator = (copy);
|
||
|
copy_vertices(copy);
|
||
|
_textures = copy._textures;
|
||
|
_material = copy._material;
|
||
|
_bface = copy._bface;
|
||
|
_connected_shading = S_unknown;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE EggPrimitive::
|
||
|
~EggPrimitive() {
|
||
|
clear();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the name of the primitive for the purposes of sorting primitives
|
||
|
* into different groups, if there is one.
|
||
|
*
|
||
|
* Presently, this is defined as the primitive name itself, unless it begins
|
||
|
* with a digit.
|
||
|
*/
|
||
|
INLINE std::string EggPrimitive::
|
||
|
get_sort_name() const {
|
||
|
const std::string &name = get_name();
|
||
|
if (!name.empty() && !isdigit(name[0])) {
|
||
|
return name;
|
||
|
}
|
||
|
return std::string();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Resets the connected_shading member in this primitive, so that
|
||
|
* get_connected_shading() will recompute a new value.
|
||
|
*/
|
||
|
INLINE void EggPrimitive::
|
||
|
clear_connected_shading() {
|
||
|
_connected_shading = S_unknown;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Determines what sort of shading properties this primitive's connected
|
||
|
* neighbors have.
|
||
|
*
|
||
|
* To get the most accurate results, you should first call
|
||
|
* clear_connected_shading() on all connected primitives (or on all primitives
|
||
|
* in the egg file). It might also be a good idea to call
|
||
|
* remove_unused_vertices() to ensure proper connectivity.
|
||
|
*
|
||
|
* You may find it easiest to call these other methods on the EggData root
|
||
|
* node (they are defined on EggGroupNode).
|
||
|
*/
|
||
|
INLINE EggPrimitive::Shading EggPrimitive::
|
||
|
get_connected_shading() const {
|
||
|
if (_connected_shading == S_unknown) {
|
||
|
((EggPrimitive *)this)->set_connected_shading(S_unknown, this);
|
||
|
}
|
||
|
|
||
|
return _connected_shading;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Replaces the current list of textures with the indicated texture.
|
||
|
*
|
||
|
* This method is deprecated and is used in support of single-texturing only.
|
||
|
* Please use the multitexture variant add_texture instead.
|
||
|
*/
|
||
|
INLINE void EggPrimitive::
|
||
|
set_texture(EggTexture *texture) {
|
||
|
clear_texture();
|
||
|
add_texture(texture);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if the primitive has any textures specified, false otherwise.
|
||
|
*
|
||
|
* This method is deprecated and is used in support of single-texturing only.
|
||
|
* New code should be written to use the multitexture variants instead.
|
||
|
*/
|
||
|
INLINE bool EggPrimitive::
|
||
|
has_texture() const {
|
||
|
return get_num_textures() > 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns true if the primitive has the particular indicated texture, false
|
||
|
* otherwise.
|
||
|
*/
|
||
|
INLINE bool EggPrimitive::
|
||
|
has_texture(EggTexture *texture) const {
|
||
|
PT_EggTexture t = texture;
|
||
|
return (std::find(_textures.begin(), _textures.end(), t) != _textures.end());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the first texture on the primitive, if any, or NULL if there are no
|
||
|
* textures on the primitive.
|
||
|
*
|
||
|
* This method is deprecated and is used in support of single-texturing only.
|
||
|
* New code should be written to use the multitexture variants instead.
|
||
|
*/
|
||
|
INLINE EggTexture *EggPrimitive::
|
||
|
get_texture() const {
|
||
|
return has_texture() ? get_texture(0) : nullptr;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Applies the indicated texture to the primitive.
|
||
|
*
|
||
|
* Note that, in the case of multiple textures being applied to a single
|
||
|
* primitive, the order in which the textures are applied does not affect the
|
||
|
* rendering order; use EggTexture::set_sort() to specify that.
|
||
|
*/
|
||
|
INLINE void EggPrimitive::
|
||
|
add_texture(EggTexture *texture) {
|
||
|
_textures.push_back(texture);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Removes any texturing from the primitive.
|
||
|
*/
|
||
|
INLINE void EggPrimitive::
|
||
|
clear_texture() {
|
||
|
_textures.clear();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the number of textures applied to the primitive.
|
||
|
*/
|
||
|
INLINE int EggPrimitive::
|
||
|
get_num_textures() const {
|
||
|
return _textures.size();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the nth texture that has been applied to the primitive.
|
||
|
*/
|
||
|
INLINE EggTexture *EggPrimitive::
|
||
|
get_texture(int n) const {
|
||
|
nassertr(n >= 0 && n < (int)_textures.size(), nullptr);
|
||
|
return _textures[n];
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Applies the indicated material to the primitive.
|
||
|
*/
|
||
|
INLINE void EggPrimitive::
|
||
|
set_material(EggMaterial *material) {
|
||
|
_material = material;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Removes any material from the primitive.
|
||
|
*/
|
||
|
INLINE void EggPrimitive::
|
||
|
clear_material() {
|
||
|
_material = nullptr;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a pointer to the applied material, or NULL if there is no material
|
||
|
* applied.
|
||
|
*/
|
||
|
INLINE EggMaterial *EggPrimitive::
|
||
|
get_material() const {
|
||
|
return _material;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Returns true if the primitive is materiald (and get_material() will return
|
||
|
* a real pointer), false otherwise (and get_material() will return NULL).
|
||
|
*/
|
||
|
INLINE bool EggPrimitive::
|
||
|
has_material() const {
|
||
|
return _material != nullptr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Sets the backfacing flag of the polygon. If this is true, the polygon will
|
||
|
* be rendered so that both faces are visible; if it is false, only the front
|
||
|
* face of the polygon will be visible.
|
||
|
*/
|
||
|
INLINE void EggPrimitive::
|
||
|
set_bface_flag(bool flag) {
|
||
|
_bface = flag;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Retrieves the backfacing flag of the polygon. See set_bface_flag().
|
||
|
*/
|
||
|
INLINE bool EggPrimitive::
|
||
|
get_bface_flag() const {
|
||
|
return _bface;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE EggPrimitive::iterator EggPrimitive::
|
||
|
begin() const {
|
||
|
return _vertices.begin();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE EggPrimitive::iterator EggPrimitive::
|
||
|
end() const {
|
||
|
return _vertices.end();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE EggPrimitive::reverse_iterator EggPrimitive::
|
||
|
rbegin() const {
|
||
|
return _vertices.rbegin();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE EggPrimitive::reverse_iterator EggPrimitive::
|
||
|
rend() const {
|
||
|
return _vertices.rend();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE bool EggPrimitive::
|
||
|
empty() const {
|
||
|
return _vertices.empty();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE EggPrimitive::size_type EggPrimitive::
|
||
|
size() const {
|
||
|
return _vertices.size();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This is read-only: you can't assign directly to an indexed vertex. See
|
||
|
* set_vertex() instead.
|
||
|
*/
|
||
|
INLINE EggVertex *EggPrimitive::
|
||
|
operator [] (int index) const {
|
||
|
nassertr(index >= 0 && index < (int)size(), nullptr);
|
||
|
return *(begin() + index);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE EggPrimitive::iterator EggPrimitive::
|
||
|
insert(iterator position, EggVertex *x) {
|
||
|
prepare_add_vertex(x, position - _vertices.begin(), _vertices.size() + 1);
|
||
|
iterator i = _vertices.insert((Vertices::iterator &)position, x);
|
||
|
x->test_pref_integrity();
|
||
|
test_vref_integrity();
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE EggPrimitive::iterator EggPrimitive::
|
||
|
erase(iterator position) {
|
||
|
prepare_remove_vertex(*position, position - _vertices.begin(), _vertices.size());
|
||
|
iterator i = _vertices.erase((Vertices::iterator &)position);
|
||
|
test_vref_integrity();
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Replaces the vertex at the indicated position with the indicated vertex.
|
||
|
* It is an error to call this with an invalid position iterator (e.g.
|
||
|
* end()).
|
||
|
*/
|
||
|
INLINE void EggPrimitive::
|
||
|
replace(iterator position, EggVertex *x) {
|
||
|
nassertv(position != end());
|
||
|
|
||
|
// We pass -1 for i and n so that EggCompositePrimitive won't try to adjust
|
||
|
// its _components list.
|
||
|
prepare_remove_vertex(*position, -1, -1);
|
||
|
prepare_add_vertex(x, -1, -1);
|
||
|
*(Vertices::iterator &)position = x;
|
||
|
|
||
|
x->test_pref_integrity();
|
||
|
test_vref_integrity();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Removes all of the vertices from the primitive.
|
||
|
*/
|
||
|
INLINE void EggPrimitive::
|
||
|
clear() {
|
||
|
erase(begin(), end());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
INLINE size_t EggPrimitive::
|
||
|
get_num_vertices() const {
|
||
|
return size();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Replaces a particular vertex based on its index number in the list of
|
||
|
* vertices. This is just a convenience function for people who don't want to
|
||
|
* mess with the iterators.
|
||
|
*/
|
||
|
INLINE void EggPrimitive::
|
||
|
set_vertex(size_t index, EggVertex *vertex) {
|
||
|
nassertv(index < size());
|
||
|
replace(begin() + index, vertex);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Inserts a vertex at the given position.
|
||
|
*/
|
||
|
INLINE void EggPrimitive::
|
||
|
insert_vertex(size_t index, EggVertex *vertex) {
|
||
|
if (index > _vertices.size()) {
|
||
|
index = _vertices.size();
|
||
|
}
|
||
|
_vertices.insert(_vertices.begin() + index, vertex);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a particular index based on its index number.
|
||
|
*/
|
||
|
INLINE EggVertex *EggPrimitive::
|
||
|
get_vertex(size_t index) const {
|
||
|
nassertr(index < size(), nullptr);
|
||
|
return *(begin() + index);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the vertex pool associated with the vertices of the primitive, or
|
||
|
* NULL if the primitive has no vertices.
|
||
|
*/
|
||
|
INLINE EggVertexPool *EggPrimitive::
|
||
|
get_pool() const {
|
||
|
return empty() ? nullptr : _vertices.front()->get_pool();
|
||
|
}
|