808 lines
28 KiB
C++
808 lines
28 KiB
C++
/**
|
|
* 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 pgFrameStyle.cxx
|
|
* @author drose
|
|
* @date 2001-07-03
|
|
*/
|
|
|
|
#include "pgFrameStyle.h"
|
|
#include "geomNode.h"
|
|
#include "pandaNode.h"
|
|
#include "transparencyAttrib.h"
|
|
#include "pointerTo.h"
|
|
#include "nodePath.h"
|
|
#include "textureAttrib.h"
|
|
#include "renderState.h"
|
|
#include "shadeModelAttrib.h"
|
|
#include "colorAttrib.h"
|
|
#include "geom.h"
|
|
#include "geomTristrips.h"
|
|
#include "geomVertexWriter.h"
|
|
|
|
using std::max;
|
|
using std::min;
|
|
|
|
// Specifies the UV range of textures applied to the frame. Maybe we'll have
|
|
// a reason to make this a parameter of the frame style one day, but for now
|
|
// it's hardcoded to fit the entire texture over the rectangular frame.
|
|
static const LVecBase4 uv_range = LVecBase4(0.0f, 1.0f, 0.0f, 1.0f);
|
|
|
|
std::ostream &
|
|
operator << (std::ostream &out, PGFrameStyle::Type type) {
|
|
switch (type) {
|
|
case PGFrameStyle::T_none:
|
|
return out << "none";
|
|
|
|
case PGFrameStyle::T_flat:
|
|
return out << "flat";
|
|
|
|
case PGFrameStyle::T_bevel_out:
|
|
return out << "bevel_out";
|
|
|
|
case PGFrameStyle::T_bevel_in:
|
|
return out << "bevel_in";
|
|
|
|
case PGFrameStyle::T_groove:
|
|
return out << "groove";
|
|
|
|
case PGFrameStyle::T_ridge:
|
|
return out << "ridge";
|
|
|
|
case PGFrameStyle::T_texture_border:
|
|
return out << "texture_border";
|
|
}
|
|
|
|
return out << "**unknown(" << (int)type << ")**";
|
|
}
|
|
|
|
/**
|
|
* Computes the size of the internal frame, given the indicated external
|
|
* frame, appropriate for this kind of frame style. This simply subtracts the
|
|
* border width for those frame styles that include a border.
|
|
*/
|
|
LVecBase4 PGFrameStyle::
|
|
get_internal_frame(const LVecBase4 &frame) const {
|
|
LPoint2 center((frame[0] + frame[1]) / 2.0f,
|
|
(frame[2] + frame[3]) / 2.0f);
|
|
LVecBase4 scaled_frame
|
|
((frame[0] - center[0]) * _visible_scale[0] + center[0],
|
|
(frame[1] - center[0]) * _visible_scale[0] + center[0],
|
|
(frame[2] - center[1]) * _visible_scale[1] + center[1],
|
|
(frame[3] - center[1]) * _visible_scale[1] + center[1]);
|
|
|
|
switch (_type) {
|
|
case T_none:
|
|
case T_flat:
|
|
return scaled_frame;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return LVecBase4(scaled_frame[0] + _width[0],
|
|
scaled_frame[1] - _width[0],
|
|
scaled_frame[2] + _width[1],
|
|
scaled_frame[3] - _width[1]);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
void PGFrameStyle::
|
|
output(std::ostream &out) const {
|
|
out << _type << " color = " << _color << " width = " << _width;
|
|
if (_visible_scale != LVecBase2(1.0f, 1.0f)) {
|
|
out << "visible_scale = " << get_visible_scale();
|
|
}
|
|
if (has_texture()) {
|
|
out << " texture = " << *get_texture();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Applies the indicated transform to the FrameStyle. The return value is
|
|
* true if the frame style is transformed, or false if it was not affected by
|
|
* the transform.
|
|
*/
|
|
bool PGFrameStyle::
|
|
xform(const LMatrix4 &mat) {
|
|
// All we can do is scale the X and Y bevel sizes.
|
|
|
|
// Extract the X and Z axes from the matrix.
|
|
LVector3 x, z;
|
|
mat.get_row3(x, 0);
|
|
PN_stdfloat x_scale = x.length();
|
|
|
|
mat.get_row3(z, 2);
|
|
PN_stdfloat z_scale = z.length();
|
|
|
|
_width[0] *= x_scale;
|
|
_width[1] *= z_scale;
|
|
|
|
switch (_type) {
|
|
case T_none:
|
|
case T_flat:
|
|
return false;
|
|
|
|
case T_bevel_out:
|
|
case T_bevel_in:
|
|
case T_groove:
|
|
case T_ridge:
|
|
case T_texture_border:
|
|
return true;
|
|
}
|
|
|
|
// Shouldn't get here, but this makes the compiler happy.
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Generates geometry representing a frame of the indicated size, and parents
|
|
* it to the indicated node, with the indicated scene graph sort order.
|
|
*
|
|
* The return value is the generated NodePath, if any, or an empty NodePath if
|
|
* nothing is generated.
|
|
*/
|
|
NodePath PGFrameStyle::
|
|
generate_into(const NodePath &parent, const LVecBase4 &frame,
|
|
int sort) {
|
|
PT(PandaNode) new_node;
|
|
|
|
LPoint2 center((frame[0] + frame[1]) / 2.0f,
|
|
(frame[2] + frame[3]) / 2.0f);
|
|
LVecBase4 scaled_frame
|
|
((frame[0] - center[0]) * _visible_scale[0] + center[0],
|
|
(frame[1] - center[0]) * _visible_scale[0] + center[0],
|
|
(frame[2] - center[1]) * _visible_scale[1] + center[1],
|
|
(frame[3] - center[1]) * _visible_scale[1] + center[1]);
|
|
|
|
switch (_type) {
|
|
case T_none:
|
|
return NodePath();
|
|
|
|
case T_flat:
|
|
new_node = generate_flat_geom(scaled_frame);
|
|
break;
|
|
|
|
case T_bevel_out:
|
|
new_node = generate_bevel_geom(scaled_frame, false);
|
|
break;
|
|
|
|
case T_bevel_in:
|
|
new_node = generate_bevel_geom(scaled_frame, true);
|
|
break;
|
|
|
|
case T_groove:
|
|
new_node = generate_groove_geom(scaled_frame, true);
|
|
break;
|
|
|
|
case T_ridge:
|
|
new_node = generate_groove_geom(scaled_frame, false);
|
|
break;
|
|
|
|
case T_texture_border:
|
|
new_node = generate_texture_border_geom(scaled_frame);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (new_node != nullptr && _color[3] != 1.0f) {
|
|
// We've got some alpha on the color; we need transparency.
|
|
new_node->set_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha));
|
|
}
|
|
|
|
// Adding the node to the parent keeps the reference count.
|
|
return parent.attach_new_node(new_node, sort);
|
|
}
|
|
|
|
/**
|
|
* Generates the GeomNode appropriate to a T_flat frame.
|
|
*/
|
|
PT(PandaNode) PGFrameStyle::
|
|
generate_flat_geom(const LVecBase4 &frame) {
|
|
PT(GeomNode) gnode = new GeomNode("flat");
|
|
|
|
PN_stdfloat left = frame[0];
|
|
PN_stdfloat right = frame[1];
|
|
PN_stdfloat bottom = frame[2];
|
|
PN_stdfloat top = frame[3];
|
|
|
|
CPT(GeomVertexFormat) format;
|
|
if (has_texture()) {
|
|
format = GeomVertexFormat::get_v3t2();
|
|
} else {
|
|
format = GeomVertexFormat::get_v3();
|
|
}
|
|
|
|
PT(GeomVertexData) vdata = new GeomVertexData
|
|
("PGFrame", format, Geom::UH_static);
|
|
|
|
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
|
vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
|
|
|
|
if (has_texture()) {
|
|
// Generate UV's.
|
|
left = uv_range[0];
|
|
right = uv_range[1];
|
|
bottom = uv_range[2];
|
|
top = uv_range[3];
|
|
|
|
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
|
|
texcoord.add_data2(left, top);
|
|
texcoord.add_data2(left, bottom);
|
|
texcoord.add_data2(right, top);
|
|
texcoord.add_data2(right, bottom);
|
|
}
|
|
|
|
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
|
|
strip->add_next_vertices(4);
|
|
strip->close_primitive();
|
|
|
|
CPT(RenderState) state = RenderState::make(ColorAttrib::make_flat(_color), -1);
|
|
if (has_texture()) {
|
|
state = state->set_attrib(TextureAttrib::make(get_texture()));
|
|
}
|
|
PT(Geom) geom = new Geom(vdata);
|
|
geom->add_primitive(strip);
|
|
gnode->add_geom(geom, state);
|
|
|
|
return gnode;
|
|
}
|
|
|
|
/**
|
|
* Generates the GeomNode appropriate to a T_bevel_in or T_bevel_out frame.
|
|
*/
|
|
PT(PandaNode) PGFrameStyle::
|
|
generate_bevel_geom(const LVecBase4 &frame, bool in) {
|
|
/*
|
|
* Colors: * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* * * * * ctop * * * *
|
|
* * * * * * * * * * * * * * * * * * * * * *
|
|
* * * * * * * * cleft *
|
|
* _color * cright* * * * * *
|
|
* * * * * * * * * * * * * * * * * * * *
|
|
* * * * * * * * cbottom
|
|
* * * * * * * * * * * * * * * * * * *
|
|
* * * * * * * * * * * * Vertices: tristrip 1: 4 * * * * * * * * * * * * * * *
|
|
* * * * * * * 6 * * * * *
|
|
* * * * * * 5 * * * * * * * * * * * *
|
|
* * 7 * * * * * * * * * * * 3 * * * * * *
|
|
* * * * * * * * 1 * * * * *
|
|
* * * * * 2 * * * * * * * * * * * * * *
|
|
* * * * * * * * 0 tristrip 2: 1 * * * * * * 5 * * * * * * * * * * * * *
|
|
* 3 * * * * *
|
|
* * * * * * *
|
|
* * * * * * 4 * * * * * * * * * * * * *
|
|
* 2 * * * * * * * 0
|
|
*/
|
|
|
|
PT(GeomNode) gnode = new GeomNode("bevel");
|
|
|
|
PN_stdfloat left = frame[0];
|
|
PN_stdfloat right = frame[1];
|
|
PN_stdfloat bottom = frame[2];
|
|
PN_stdfloat top = frame[3];
|
|
|
|
PN_stdfloat cx = (left + right) * 0.5;
|
|
PN_stdfloat cy = (top + bottom) * 0.5;
|
|
|
|
PN_stdfloat inner_left = min(left + _width[0], cx);
|
|
PN_stdfloat inner_right = max(right - _width[0], cx);
|
|
PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
|
|
PN_stdfloat inner_top = max(top - _width[1], cy);
|
|
|
|
PN_stdfloat left_color_scale = 1.2;
|
|
PN_stdfloat right_color_scale = 0.8;
|
|
PN_stdfloat bottom_color_scale = 0.7;
|
|
PN_stdfloat top_color_scale = 1.3;
|
|
|
|
if (in) {
|
|
right_color_scale = 1.2;
|
|
left_color_scale = 0.8;
|
|
top_color_scale = 0.7;
|
|
bottom_color_scale = 1.3;
|
|
}
|
|
|
|
// Clamp all colors at white, and don't scale the alpha.
|
|
LColor cleft(min(_color[0] * left_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[1] * left_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[2] * left_color_scale, (PN_stdfloat)1.0),
|
|
_color[3]);
|
|
|
|
LColor cright(min(_color[0] * right_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[1] * right_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[2] * right_color_scale, (PN_stdfloat)1.0),
|
|
_color[3]);
|
|
|
|
LColor cbottom(min(_color[0] * bottom_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[1] * bottom_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[2] * bottom_color_scale, (PN_stdfloat)1.0),
|
|
_color[3]);
|
|
|
|
LColor ctop(min(_color[0] * top_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[1] * top_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[2] * top_color_scale, (PN_stdfloat)1.0),
|
|
_color[3]);
|
|
|
|
CPT(GeomVertexFormat) format;
|
|
if (has_texture()) {
|
|
format = GeomVertexFormat::get_v3cpt2();
|
|
} else {
|
|
format = GeomVertexFormat::get_v3cp();
|
|
}
|
|
|
|
PT(GeomVertexData) vdata = new GeomVertexData
|
|
("PGFrame", format, Geom::UH_static);
|
|
|
|
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
|
GeomVertexWriter color(vdata, InternalName::get_color());
|
|
|
|
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
|
|
// Tristrip 1.
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
|
|
color.add_data4(cbottom);
|
|
color.add_data4(cbottom);
|
|
color.add_data4(cbottom);
|
|
color.add_data4(cbottom);
|
|
color.add_data4(cleft);
|
|
color.add_data4(cleft);
|
|
color.add_data4(ctop);
|
|
color.add_data4(ctop);
|
|
|
|
strip->add_next_vertices(8);
|
|
strip->close_primitive();
|
|
|
|
// Tristrip 2.
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
|
|
color.add_data4(cright);
|
|
color.add_data4(cright);
|
|
color.add_data4(cright);
|
|
color.add_data4(cright);
|
|
color.add_data4(_color);
|
|
color.add_data4(_color);
|
|
|
|
strip->add_next_vertices(6);
|
|
strip->close_primitive();
|
|
strip->set_shade_model(Geom::SM_flat_last_vertex);
|
|
|
|
if (has_texture()) {
|
|
// Generate UV's.
|
|
PN_stdfloat left = uv_range[0];
|
|
PN_stdfloat right = uv_range[1];
|
|
PN_stdfloat bottom = uv_range[2];
|
|
PN_stdfloat top = uv_range[3];
|
|
|
|
PN_stdfloat cx = (left + right) * 0.5;
|
|
PN_stdfloat cy = (top + bottom) * 0.5;
|
|
|
|
PN_stdfloat inner_left = min(left + _uv_width[0], cx);
|
|
PN_stdfloat inner_right = max(right - _uv_width[0], cx);
|
|
PN_stdfloat inner_bottom = min(bottom + _uv_width[1], cy);
|
|
PN_stdfloat inner_top = max(top - _uv_width[1], cy);
|
|
|
|
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
|
|
texcoord.add_data2(right, bottom);
|
|
texcoord.add_data2(inner_right, inner_bottom);
|
|
texcoord.add_data2(left, bottom);
|
|
texcoord.add_data2(inner_left, inner_bottom);
|
|
texcoord.add_data2(left, top);
|
|
texcoord.add_data2(inner_left, inner_top);
|
|
texcoord.add_data2(right, top);
|
|
texcoord.add_data2(inner_right, inner_top);
|
|
|
|
texcoord.add_data2(right, bottom);
|
|
texcoord.add_data2(right, top);
|
|
texcoord.add_data2(inner_right, inner_bottom);
|
|
texcoord.add_data2(inner_right, inner_top);
|
|
texcoord.add_data2(inner_left, inner_bottom);
|
|
texcoord.add_data2(inner_left, inner_top);
|
|
}
|
|
PT(Geom) geom = new Geom(vdata);
|
|
geom->add_primitive(strip);
|
|
|
|
CPT(RenderState) state;
|
|
state = RenderState::make(ShadeModelAttrib::make(ShadeModelAttrib::M_flat),
|
|
ColorAttrib::make_vertex());
|
|
if (has_texture()) {
|
|
state = state->set_attrib(TextureAttrib::make(get_texture()));
|
|
}
|
|
gnode->add_geom(geom, state);
|
|
|
|
return gnode;
|
|
}
|
|
|
|
/**
|
|
* Generates the GeomNode appropriate to a T_groove or T_ridge frame.
|
|
*/
|
|
PT(PandaNode) PGFrameStyle::
|
|
generate_groove_geom(const LVecBase4 &frame, bool in) {
|
|
/*
|
|
* Colors: * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* * * * * ctop * * * *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* * * * * * * cbottom * * * * *
|
|
* * * * * * * * * * * * * * * * *
|
|
* * * * * * * * * * *
|
|
* * * * * * * cleft * cright* _color
|
|
* * cleft * cright* * * * * * * *
|
|
* * * * * * * * * * * * * * *
|
|
* * * * * * * * * * * *
|
|
* * * * * ctop * * * * * *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* * * * * cbottom * * * *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Vertices:
|
|
* tristrip 1: 4 * * * * * * * * * * * * * * * * * * * * * * * * * 6 * *
|
|
* * * * * * *
|
|
* * * 5 * * * * * * * * * * * * * * * * * 7 * * * * *
|
|
* * * * * * * * * * * * * * * * *
|
|
* * * * * * * 3 * * * * * * * * * * * * * * * * * 1 * *
|
|
* * * * * * *
|
|
* * 2 * * * * * * * * * * * * * * * * * * * * * * * * * 0 tristrip 2: 4 * * *
|
|
* * * * * * * * * * * * * * * 6 * * * * *
|
|
* * * * * * 5 * * * * * * * * * 7 * * *
|
|
* * * * * * * * * 3 * * * * * * * * * 1 * *
|
|
* * * * * * * * 2 *
|
|
* * * * * * * * * * * * * * * * * 0 tristrip 3: 1 * * * * * * 3 *
|
|
* * * * * * * * * * 7 * * * * * * * * * 5 *
|
|
* * * * * * * * *
|
|
* * * * * * * * *
|
|
* * * * * * 6 * * * * * * * * * 4 *
|
|
* * * * * * * * * * * 2 * * * * * * * 0
|
|
*/
|
|
|
|
PT(GeomNode) gnode = new GeomNode("groove");
|
|
|
|
PN_stdfloat left = frame[0];
|
|
PN_stdfloat right = frame[1];
|
|
PN_stdfloat bottom = frame[2];
|
|
PN_stdfloat top = frame[3];
|
|
|
|
PN_stdfloat cx = (left + right) * 0.5;
|
|
PN_stdfloat cy = (top + bottom) * 0.5;
|
|
|
|
PN_stdfloat mid_left = min(left + 0.5f * _width[0], cx);
|
|
PN_stdfloat mid_right = max(right - 0.5f * _width[0], cx);
|
|
PN_stdfloat mid_bottom = min(bottom + 0.5f * _width[1], cy);
|
|
PN_stdfloat mid_top = max(top - 0.5f * _width[1], cy);
|
|
|
|
PN_stdfloat inner_left = min(left + _width[0], cx);
|
|
PN_stdfloat inner_right = max(right - _width[0], cx);
|
|
PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
|
|
PN_stdfloat inner_top = max(top - _width[1], cy);
|
|
|
|
PN_stdfloat left_color_scale = 1.2;
|
|
PN_stdfloat right_color_scale = 0.8f;
|
|
PN_stdfloat bottom_color_scale = 0.7f;
|
|
PN_stdfloat top_color_scale = 1.3;
|
|
|
|
if (in) {
|
|
right_color_scale = 1.2;
|
|
left_color_scale = 0.8f;
|
|
top_color_scale = 0.7f;
|
|
bottom_color_scale = 1.3;
|
|
}
|
|
|
|
// Clamp all colors at white, and don't scale the alpha.
|
|
LColor cleft(min(_color[0] * left_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[1] * left_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[2] * left_color_scale, (PN_stdfloat)1.0),
|
|
_color[3]);
|
|
|
|
LColor cright(min(_color[0] * right_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[1] * right_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[2] * right_color_scale, (PN_stdfloat)1.0),
|
|
_color[3]);
|
|
|
|
LColor cbottom(min(_color[0] * bottom_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[1] * bottom_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[2] * bottom_color_scale, (PN_stdfloat)1.0),
|
|
_color[3]);
|
|
|
|
LColor ctop(min(_color[0] * top_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[1] * top_color_scale, (PN_stdfloat)1.0),
|
|
min(_color[2] * top_color_scale, (PN_stdfloat)1.0),
|
|
_color[3]);
|
|
|
|
CPT(GeomVertexFormat) format;
|
|
if (has_texture()) {
|
|
format = GeomVertexFormat::get_v3cpt2();
|
|
} else {
|
|
format = GeomVertexFormat::get_v3cp();
|
|
}
|
|
PT(GeomVertexData) vdata = new GeomVertexData
|
|
("PGFrame", format, Geom::UH_static);
|
|
|
|
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
|
GeomVertexWriter color(vdata, InternalName::get_color());
|
|
|
|
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
|
|
// Tristrip 1.
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
|
|
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
|
|
vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
|
|
vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_bottom));
|
|
vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_top));
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
|
|
color.add_data4(cbottom);
|
|
color.add_data4(cbottom);
|
|
color.add_data4(cbottom);
|
|
color.add_data4(cbottom);
|
|
color.add_data4(cleft);
|
|
color.add_data4(cleft);
|
|
color.add_data4(ctop);
|
|
color.add_data4(ctop);
|
|
|
|
strip->add_next_vertices(8);
|
|
strip->close_primitive();
|
|
|
|
// Tristrip 2.
|
|
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_bottom));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(mid_left, 0.0f, mid_top));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
|
|
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
|
|
color.add_data4(ctop);
|
|
color.add_data4(ctop);
|
|
color.add_data4(ctop);
|
|
color.add_data4(ctop);
|
|
color.add_data4(cright);
|
|
color.add_data4(cright);
|
|
color.add_data4(cbottom);
|
|
color.add_data4(cbottom);
|
|
|
|
strip->add_next_vertices(8);
|
|
strip->close_primitive();
|
|
|
|
// Tristrip 3.
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_bottom));
|
|
vertex.add_data3(LPoint3::rfu(mid_right, 0.0f, mid_top));
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
|
|
color.add_data4(cright);
|
|
color.add_data4(cright);
|
|
color.add_data4(cright);
|
|
color.add_data4(cright);
|
|
color.add_data4(cleft);
|
|
color.add_data4(cleft);
|
|
color.add_data4(_color);
|
|
color.add_data4(_color);
|
|
|
|
strip->add_next_vertices(8);
|
|
strip->close_primitive();
|
|
|
|
strip->set_shade_model(Geom::SM_flat_last_vertex);
|
|
|
|
if (has_texture()) {
|
|
// Generate UV's.
|
|
PN_stdfloat left = uv_range[0];
|
|
PN_stdfloat right = uv_range[1];
|
|
PN_stdfloat bottom = uv_range[2];
|
|
PN_stdfloat top = uv_range[3];
|
|
|
|
PN_stdfloat cx = (left + right) * 0.5;
|
|
PN_stdfloat cy = (top + bottom) * 0.5;
|
|
|
|
PN_stdfloat mid_left = min(left + 0.5f * _width[0], cx);
|
|
PN_stdfloat mid_right = max(right - 0.5f * _width[0], cx);
|
|
PN_stdfloat mid_bottom = min(bottom + 0.5f * _width[1], cy);
|
|
PN_stdfloat mid_top = max(top - 0.5f * _width[1], cy);
|
|
|
|
PN_stdfloat inner_left = min(left + _width[0], cx);
|
|
PN_stdfloat inner_right = max(right - _width[0], cx);
|
|
PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
|
|
PN_stdfloat inner_top = max(top - _width[1], cy);
|
|
|
|
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
|
|
texcoord.add_data2(right, bottom);
|
|
texcoord.add_data2(mid_right, mid_bottom);
|
|
texcoord.add_data2(left, bottom);
|
|
texcoord.add_data2(mid_left, mid_bottom);
|
|
texcoord.add_data2(left, top);
|
|
texcoord.add_data2(mid_left, mid_top);
|
|
texcoord.add_data2(right, top);
|
|
texcoord.add_data2(mid_right, mid_top);
|
|
|
|
texcoord.add_data2(mid_right, mid_bottom);
|
|
texcoord.add_data2(inner_right, inner_bottom);
|
|
texcoord.add_data2(mid_left, mid_bottom);
|
|
texcoord.add_data2(inner_left, inner_bottom);
|
|
texcoord.add_data2(mid_left, mid_top);
|
|
texcoord.add_data2(inner_left, inner_top);
|
|
texcoord.add_data2(mid_right, mid_top);
|
|
texcoord.add_data2(inner_right, inner_top);
|
|
|
|
texcoord.add_data2(right, bottom);
|
|
texcoord.add_data2(right, top);
|
|
texcoord.add_data2(mid_right, mid_bottom);
|
|
texcoord.add_data2(mid_right, mid_top);
|
|
texcoord.add_data2(inner_right, inner_bottom);
|
|
texcoord.add_data2(inner_right, inner_top);
|
|
texcoord.add_data2(inner_left, inner_bottom);
|
|
texcoord.add_data2(inner_left, inner_top);
|
|
}
|
|
|
|
PT(Geom) geom = new Geom(vdata);
|
|
geom->add_primitive(strip);
|
|
|
|
CPT(RenderState) state = RenderState::make(ShadeModelAttrib::make(ShadeModelAttrib::M_flat),
|
|
ColorAttrib::make_vertex());
|
|
if (has_texture()) {
|
|
state = state->set_attrib(TextureAttrib::make(get_texture()));
|
|
}
|
|
gnode->add_geom(geom, state);
|
|
|
|
return gnode;
|
|
}
|
|
|
|
/**
|
|
* Generates the GeomNode appropriate to a T_texture_border frame.
|
|
*/
|
|
PT(PandaNode) PGFrameStyle::
|
|
generate_texture_border_geom(const LVecBase4 &frame) {
|
|
/*
|
|
* Vertices: tristrip 1: 0 * * * 2 * * * * * * * * * * * * * 4 * * * 6 * *
|
|
* * * * * * * * * * * * * * * * * *
|
|
* * * * * * * * * * * * * 1 * * * 3 * * * * * * *
|
|
* * * * * * * 5 * * * 7 tristrip 2: 1 * * * 3 * * * * * * * * * * * * * 5 * *
|
|
* * 7 * * * * * * * *
|
|
* * * * * * * * * * * * * * * * * *
|
|
* * * * * * * * * * * * * * * *
|
|
* * * * * * 8 * * *10 * * * * * * * * * * * * *12
|
|
* * * *14 tristrip 3: 8 * * *10 * * * * * * * * * * * * *12 * * *14 * * *
|
|
* * * * * * * * * * * * * * * * * * * * * * * *
|
|
* * * * * * 9 * * *11 * * * * * * * * * * * * *13 * *
|
|
* *15
|
|
*/
|
|
|
|
PT(GeomNode) gnode = new GeomNode("flat");
|
|
|
|
PN_stdfloat left = frame[0];
|
|
PN_stdfloat right = frame[1];
|
|
PN_stdfloat bottom = frame[2];
|
|
PN_stdfloat top = frame[3];
|
|
|
|
PN_stdfloat cx = (left + right) * 0.5;
|
|
PN_stdfloat cy = (top + bottom) * 0.5;
|
|
|
|
PN_stdfloat inner_left = min(left + _width[0], cx);
|
|
PN_stdfloat inner_right = max(right - _width[0], cx);
|
|
PN_stdfloat inner_bottom = min(bottom + _width[1], cy);
|
|
PN_stdfloat inner_top = max(top - _width[1], cy);
|
|
|
|
CPT(GeomVertexFormat) format;
|
|
if (has_texture()) {
|
|
format = GeomVertexFormat::get_v3t2();
|
|
} else {
|
|
format = GeomVertexFormat::get_v3();
|
|
}
|
|
|
|
PT(GeomVertexData) vdata = new GeomVertexData
|
|
("PGFrame", format, Geom::UH_static);
|
|
|
|
GeomVertexWriter vertex(vdata, InternalName::get_vertex());
|
|
|
|
// verts 0,1,2,3
|
|
vertex.add_data3(LPoint3::rfu(left, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(left, 0.0f, inner_top));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_top));
|
|
// verts 4,5,6,7
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_top));
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, top));
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, inner_top));
|
|
// verts 8,9,10,11
|
|
vertex.add_data3(LPoint3::rfu(left, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(left, 0.0f, bottom));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(inner_left, 0.0f, bottom));
|
|
// verts 12,13,14,15
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(inner_right, 0.0f, bottom));
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, inner_bottom));
|
|
vertex.add_data3(LPoint3::rfu(right, 0.0f, bottom));
|
|
|
|
if (has_texture()) {
|
|
// Generate UV's.
|
|
PN_stdfloat left = uv_range[0];
|
|
PN_stdfloat right = uv_range[1];
|
|
PN_stdfloat bottom = uv_range[2];
|
|
PN_stdfloat top = uv_range[3];
|
|
|
|
PN_stdfloat cx = (left + right) * 0.5;
|
|
PN_stdfloat cy = (top + bottom) * 0.5;
|
|
|
|
PN_stdfloat inner_left = min(left + _uv_width[0], cx);
|
|
PN_stdfloat inner_right = max(right - _uv_width[0], cx);
|
|
PN_stdfloat inner_bottom = min(bottom + _uv_width[1], cy);
|
|
PN_stdfloat inner_top = max(top - _uv_width[1], cy);
|
|
|
|
GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
|
|
|
|
// verts 0,1,2,3
|
|
texcoord.add_data2(left, top);
|
|
texcoord.add_data2(left, inner_top);
|
|
texcoord.add_data2(inner_left, top);
|
|
texcoord.add_data2(inner_left, inner_top);
|
|
// verts 4,5,6,7
|
|
texcoord.add_data2(inner_right, top);
|
|
texcoord.add_data2(inner_right, inner_top);
|
|
texcoord.add_data2(right, top);
|
|
texcoord.add_data2(right, inner_top);
|
|
// verts 8,9,10,11
|
|
texcoord.add_data2(left, inner_bottom);
|
|
texcoord.add_data2(left, bottom);
|
|
texcoord.add_data2(inner_left, inner_bottom);
|
|
texcoord.add_data2(inner_left, bottom);
|
|
// verts 12,13,14,15
|
|
texcoord.add_data2(inner_right, inner_bottom);
|
|
texcoord.add_data2(inner_right, bottom);
|
|
texcoord.add_data2(right, inner_bottom);
|
|
texcoord.add_data2(right, bottom);
|
|
}
|
|
|
|
PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
|
|
|
|
// tristrip #1
|
|
strip->add_consecutive_vertices(0, 8);
|
|
strip->close_primitive();
|
|
|
|
// tristrip #2
|
|
strip->add_vertex(1);
|
|
strip->add_vertex(8);
|
|
strip->add_vertex(3);
|
|
strip->add_vertex(10);
|
|
strip->add_vertex(5);
|
|
strip->add_vertex(12);
|
|
strip->add_vertex(7);
|
|
strip->add_vertex(14);
|
|
strip->close_primitive();
|
|
|
|
// tristrip #3
|
|
strip->add_consecutive_vertices(8, 8);
|
|
strip->close_primitive();
|
|
|
|
CPT(RenderState) state = RenderState::make(ColorAttrib::make_flat(_color), -1);
|
|
if (has_texture()) {
|
|
state = state->set_attrib(TextureAttrib::make(get_texture()));
|
|
}
|
|
|
|
PT(Geom) geom = new Geom(vdata);
|
|
geom->add_primitive(strip);
|
|
gnode->add_geom(geom, state);
|
|
|
|
return gnode;
|
|
}
|