Panda3D
Loading...
Searching...
No Matches
rocketRenderInterface.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file rocketRenderInterface.cxx
10 * @author rdb
11 * @date 2011-11-04
12 */
13
15#include "cullableObject.h"
16#include "cullHandler.h"
17#include "geomVertexData.h"
18#include "geomVertexArrayData.h"
19#include "internalName.h"
20#include "geomVertexWriter.h"
21#include "geomTriangles.h"
22#include "colorAttrib.h"
23#include "colorBlendAttrib.h"
24#include "cullBinAttrib.h"
25#include "depthTestAttrib.h"
26#include "depthWriteAttrib.h"
27#include "scissorAttrib.h"
28#include "texture.h"
29#include "textureAttrib.h"
30#include "texturePool.h"
31
32/**
33 * Called by RocketNode in cull_callback. Invokes context->Render() and culls
34 * the result.
35 */
37render(Rocket::Core::Context* context, CullTraverser *trav) {
38 nassertv(context != nullptr);
39 MutexHolder holder(_lock);
40
41 _trav = trav;
42 _net_transform = trav->get_world_transform();
43 _net_state = RenderState::make(
44 CullBinAttrib::make("unsorted", 0),
45 DepthTestAttrib::make(RenderAttrib::M_none),
46 DepthWriteAttrib::make(DepthWriteAttrib::M_off),
47 ColorBlendAttrib::make(ColorBlendAttrib::M_add,
48 ColorBlendAttrib::O_incoming_alpha,
49 ColorBlendAttrib::O_one_minus_incoming_alpha
50 ),
51 ColorAttrib::make_vertex()
52 );
53 _dimensions = context->GetDimensions();
54
55 context->Render();
56
57 _trav = nullptr;
58 _net_transform = nullptr;
59 _net_state = nullptr;
60}
61
62/**
63 * Called internally to make a Geom from Rocket data.
64 */
65PT(Geom) RocketRenderInterface::
66make_geom(Rocket::Core::Vertex* vertices,
67 int num_vertices, int* indices, int num_indices,
68 GeomEnums::UsageHint uh, const LVecBase2 &tex_scale) {
69
71 vdata->unclean_set_num_rows(num_vertices);
72 {
73 GeomVertexWriter vwriter(vdata, InternalName::get_vertex());
74 GeomVertexWriter cwriter(vdata, InternalName::get_color());
75 GeomVertexWriter twriter(vdata, InternalName::get_texcoord());
76
77 // Write the vertex information.
78 for (int i = 0; i < num_vertices; ++i) {
79 const Rocket::Core::Vertex &vertex = vertices[i];
80
81 vwriter.add_data3f(LVector3f::right() * vertex.position.x + LVector3f::up() * vertex.position.y);
82 cwriter.add_data4i(vertex.colour.red, vertex.colour.green,
83 vertex.colour.blue, vertex.colour.alpha);
84 twriter.add_data2f(vertex.tex_coord.x * tex_scale[0],
85 (1.0f - vertex.tex_coord.y) * tex_scale[1]);
86 }
87 }
88
89 // Create a primitive and write the indices.
90 PT(GeomTriangles) triangles = new GeomTriangles(uh);
91 {
92 PT(GeomVertexArrayData) idata = triangles->modify_vertices();
93 idata->unclean_set_num_rows(num_indices);
94 GeomVertexWriter iwriter(idata, 0);
95
96 for (int i = 0; i < num_indices; ++i) {
97 iwriter.add_data1i(indices[i]);
98 }
99 }
100
101 PT(Geom) geom = new Geom(vdata);
102 geom->add_primitive(triangles);
103 return geom;
104}
105
106/**
107 * Only call this during render(). Culls a geom.
108 */
109void RocketRenderInterface::
110render_geom(const Geom* geom, const RenderState* state, const Rocket::Core::Vector2f& translation) {
111 LVector3 offset = LVector3::right() * translation.x + LVector3::up() * translation.y;
112
113 if (_enable_scissor) {
114 state = state->add_attrib(ScissorAttrib::make(_scissor));
115 rocket_cat.spam()
116 << "Rendering geom " << geom << " with state "
117 << *state << ", translation (" << offset << "), "
118 << "scissor region (" << _scissor << ")\n";
119 } else {
120 rocket_cat.spam()
121 << "Rendering geom " << geom << " with state "
122 << *state << ", translation (" << offset << ")\n";
123 }
124
125 CPT(TransformState) internal_transform =
126 _trav->get_scene()->get_cs_world_transform()->compose(
127 _net_transform->compose(TransformState::make_pos(offset)));
128
129 CullableObject *object =
130 new CullableObject(geom, _net_state->compose(state),
131 internal_transform);
132 _trav->get_cull_handler()->record_object(object, _trav);
133}
134
135/**
136 * Called by Rocket when it wants to render geometry that the application does
137 * not wish to optimize.
138 */
139void RocketRenderInterface::
140RenderGeometry(Rocket::Core::Vertex* vertices,
141 int num_vertices, int* indices, int num_indices,
142 Rocket::Core::TextureHandle thandle,
143 const Rocket::Core::Vector2f& translation) {
144
145 Texture *texture = (Texture *)thandle;
146
147 LVecBase2 tex_scale(1, 1);
148 if (texture != nullptr) {
149 tex_scale = texture->get_tex_scale();
150 }
151
152 PT(Geom) geom = make_geom(vertices, num_vertices, indices, num_indices,
153 GeomEnums::UH_stream, tex_scale);
154
155 CPT(RenderState) state;
156 if (texture != nullptr) {
157 state = RenderState::make(TextureAttrib::make(texture));
158 } else {
159 state = RenderState::make_empty();
160 }
161
162 render_geom(geom, state, translation);
163}
164
165/**
166 * Called by Rocket when it wants to compile geometry it believes will be
167 * static for the forseeable future.
168 */
169Rocket::Core::CompiledGeometryHandle RocketRenderInterface::
170CompileGeometry(Rocket::Core::Vertex* vertices,
171 int num_vertices, int* indices, int num_indices,
172 Rocket::Core::TextureHandle thandle) {
173
174 Texture *texture = (Texture *)thandle;
175
176 CompiledGeometry *c = new CompiledGeometry;
177 LVecBase2 tex_scale(1, 1);
178
179 if (texture != nullptr) {
180 rocket_cat.debug()
181 << "Compiling geom " << c->_geom << " with texture '"
182 << texture->get_name() << "'\n";
183
184 tex_scale = texture->get_tex_scale();
185
186 PT(TextureStage) stage = new TextureStage("");
187 stage->set_mode(TextureStage::M_modulate);
188
189 CPT(TextureAttrib) attr = DCAST(TextureAttrib, TextureAttrib::make());
190 attr = DCAST(TextureAttrib, attr->add_on_stage(stage, (Texture *)texture));
191
192 c->_state = RenderState::make(attr);
193
194 } else {
195 rocket_cat.debug()
196 << "Compiling geom " << c->_geom << " without texture\n";
197
198 c->_state = RenderState::make_empty();
199 }
200
201 c->_geom = make_geom(vertices, num_vertices, indices, num_indices,
202 GeomEnums::UH_static, tex_scale);
203
204 return (Rocket::Core::CompiledGeometryHandle) c;
205}
206
207/**
208 * Called by Rocket when it wants to render application-compiled geometry.
209 */
210void RocketRenderInterface::
211RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry, const Rocket::Core::Vector2f& translation) {
212
213 CompiledGeometry *c = (CompiledGeometry*) geometry;
214 render_geom(c->_geom, c->_state, translation);
215}
216
217/**
218 * Called by Rocket when it wants to release application-compiled geometry.
219 */
220void RocketRenderInterface::
221ReleaseCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry) {
222 delete (CompiledGeometry*) geometry;
223}
224
225/**
226 * Called by Rocket when a texture is required by the library.
227 */
228bool RocketRenderInterface::
229LoadTexture(Rocket::Core::TextureHandle& texture_handle,
230 Rocket::Core::Vector2i& texture_dimensions,
231 const Rocket::Core::String& source) {
232
233 // Prefer padding over scaling to avoid blurring people's pixel art.
234 LoaderOptions options;
235 if (Texture::get_textures_power_2() == ATS_none) {
236 options.set_auto_texture_scale(ATS_none);
237 } else {
238 options.set_auto_texture_scale(ATS_pad);
239 }
240
241 Filename fn = Filename::from_os_specific(source.CString());
242 PT(Texture) tex = TexturePool::load_texture(fn, 0, false, options);
243 if (tex == nullptr) {
244 texture_handle = 0;
245 texture_dimensions.x = 0;
246 texture_dimensions.y = 0;
247 return false;
248 }
249
250 tex->set_minfilter(SamplerState::FT_nearest);
251 tex->set_magfilter(SamplerState::FT_nearest);
252
253 // Since libRocket may make layout decisions based on the size of the image,
254 // it's important that we give it the original size of the image file in
255 // order to produce consistent results.
256 int width = tex->get_orig_file_x_size();
257 int height = tex->get_orig_file_y_size();
258 if (width == 0 && height == 0) {
259 // This shouldn't happen unless someone is playing very strange tricks
260 // with the TexturePool, but we might as well handle it.
261 width = tex->get_x_size();
262 height = tex->get_y_size();
263 }
264 texture_dimensions.x = width;
265 texture_dimensions.y = height;
266
267 tex->ref();
268 texture_handle = (Rocket::Core::TextureHandle) tex.p();
269
270 return true;
271}
272
273/**
274 * Called by Rocket when a texture is required to be built from an internally-
275 * generated sequence of pixels.
276 */
277bool RocketRenderInterface::
278GenerateTexture(Rocket::Core::TextureHandle& texture_handle,
279 const Rocket::Core::byte* source,
280 const Rocket::Core::Vector2i& source_dimensions) {
281
282 PT(Texture) tex = new Texture;
283 tex->setup_2d_texture(source_dimensions.x, source_dimensions.y,
284 Texture::T_unsigned_byte, Texture::F_rgba);
285
286 // Pad to nearest power of two if necessary. It may not be necessary as
287 // libRocket seems to give power-of-two sizes already, but can't hurt.
288 tex->set_size_padded(source_dimensions.x, source_dimensions.y);
289
290 PTA_uchar image = tex->modify_ram_image();
291
292 // Convert RGBA to BGRA
293 size_t src_stride = source_dimensions.x * 4;
294 size_t dst_stride = tex->get_x_size() * 4;
295 const unsigned char *src_ptr = source + (src_stride * source_dimensions.y);
296 unsigned char *dst_ptr = &image[0];
297
298 for (; src_ptr > source; dst_ptr += dst_stride) {
299 src_ptr -= src_stride;
300 for (size_t i = 0; i < src_stride; i += 4) {
301 dst_ptr[i + 0] = src_ptr[i + 2];
302 dst_ptr[i + 1] = src_ptr[i + 1];
303 dst_ptr[i + 2] = src_ptr[i];
304 dst_ptr[i + 3] = src_ptr[i + 3];
305 }
306 }
307
308 tex->set_wrap_u(SamplerState::WM_clamp);
309 tex->set_wrap_v(SamplerState::WM_clamp);
310 tex->set_minfilter(SamplerState::FT_nearest);
311 tex->set_magfilter(SamplerState::FT_nearest);
312
313 tex->ref();
314 texture_handle = (Rocket::Core::TextureHandle) tex.p();
315
316 return true;
317}
318
319/**
320 * Called by Rocket when a loaded texture is no longer required.
321 */
322void RocketRenderInterface::
323ReleaseTexture(Rocket::Core::TextureHandle texture_handle) {
324 Texture *tex = (Texture *)texture_handle;
325 if (tex != nullptr) {
326 unref_delete(tex);
327 }
328}
329
330/**
331 * Called by Rocket when it wants to enable or disable scissoring to clip
332 * content.
333 */
334void RocketRenderInterface::
335EnableScissorRegion(bool enable) {
336 _enable_scissor = enable;
337}
338
339/**
340 * Called by Rocket when it wants to change the scissor region.
341 */
342void RocketRenderInterface::
343SetScissorRegion(int x, int y, int width, int height) {
344 _scissor[0] = x / (PN_stdfloat) _dimensions.x;
345 _scissor[1] = (x + width) / (PN_stdfloat) _dimensions.x;
346 _scissor[2] = 1.0f - ((y + height) / (PN_stdfloat) _dimensions.y);
347 _scissor[3] = 1.0f - (y / (PN_stdfloat) _dimensions.y);
348}
void ref() const
Increments the reference count of the underlying vector.
virtual void record_object(CullableObject *object, const CullTraverser *traverser)
This callback function is intended to be overridden by a derived class.
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
CullHandler * get_cull_handler() const
Returns the object that will receive the culled Geoms.
const TransformState * get_world_transform() const
Returns the position of the starting node relative to the camera.
SceneSetup * get_scene() const
Returns the SceneSetup object.
The smallest atom of cull.
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
Definition filename.cxx:328
Defines a series of disconnected triangles.
This is the data for one array of a GeomVertexData structure.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
static const GeomVertexFormat * get_v3c4t2()
Returns a standard vertex format with a 2-component texture coordinate pair, a 4-component color,...
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
void add_data4i(int a, int b, int c, int d)
Sets the write row to a particular 4-component value, and advances the write row.
void add_data1i(int data)
Sets the write row to a particular 1-component value, and advances the write row.
void add_data2f(float x, float y)
Sets the write row to a particular 2-component value, and advances the write row.
void add_data3f(float x, float y, float z)
Sets the write row to a particular 3-component value, and advances the write row.
A container for geometry primitives.
Definition geom.h:54
Specifies parameters that may be passed to the loader.
set_auto_texture_scale
Set this flag to ATS_none, ATS_up, ATS_down, or ATS_pad to control how a texture is scaled from disk ...
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition mutexHolder.h:25
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition renderState.h:47
void render(Rocket::Core::Context *context, CullTraverser *trav)
Called by RocketNode in cull_callback.
const TransformState * get_cs_world_transform() const
Returns the position from the starting node relative to the camera, in the GSG's internal coordinate ...
Definition sceneSetup.I:268
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
static Texture * load_texture(const Filename &filename, int primary_file_num_channels=0, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads the given filename up into a texture, if it has not already been loaded, and returns the new te...
Definition texturePool.I:70
Defines the properties of a named stage of the multitexture pipeline.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition texture.h:72
void setup_2d_texture()
Sets the texture as an empty 2-d texture with no dimensions.
Definition texture.I:88
LVecBase2 get_tex_scale() const
Returns a scale pair that is suitable for applying to geometry via NodePath::set_tex_scale(),...
Definition texture.I:656
static AutoTextureScale get_textures_power_2()
This flag returns ATS_none, ATS_up, or ATS_down and controls the scaling of textures in general.
Definition texture.I:1864
Indicates a coordinate-system transform on vertices.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.