Panda3D
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 
14 #include "rocketRenderInterface.h"
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  */
37 render(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  */
65 PT(Geom) RocketRenderInterface::
66 make_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  */
109 void RocketRenderInterface::
110 render_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  */
139 void RocketRenderInterface::
140 RenderGeometry(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  */
169 Rocket::Core::CompiledGeometryHandle RocketRenderInterface::
170 CompileGeometry(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  */
210 void RocketRenderInterface::
211 RenderCompiledGeometry(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  */
220 void RocketRenderInterface::
221 ReleaseCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry) {
222  delete (CompiledGeometry*) geometry;
223 }
224 
225 /**
226  * Called by Rocket when a texture is required by the library.
227  */
228 bool RocketRenderInterface::
229 LoadTexture(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  */
277 bool RocketRenderInterface::
278 GenerateTexture(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  */
322 void RocketRenderInterface::
323 ReleaseTexture(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  */
334 void RocketRenderInterface::
335 EnableScissorRegion(bool enable) {
336  _enable_scissor = enable;
337 }
338 
339 /**
340  * Called by Rocket when it wants to change the scissor region.
341  */
342 void RocketRenderInterface::
343 SetScissorRegion(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 }
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
CullHandler * get_cull_handler() const
Returns the object that will receive the culled Geoms.
Indicates a coordinate-system transform on vertices.
void setup_2d_texture()
Sets the texture as an empty 2-d texture with no dimensions.
Definition: texture.I:87
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 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.
Specifies parameters that may be passed to the loader.
Definition: loaderOptions.h:23
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
Definition: texture.h:71
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
Definition: mutexHolder.h:25
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
Definition: textureAttrib.h:31
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void render(Rocket::Core::Context *context, CullTraverser *trav)
Called by RocketNode in cull_callback.
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:1863
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The smallest atom of cull.
void ref() const
Increments the reference count of the underlying vector.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
PT(Geom) RocketRenderInterface
Called internally to make a Geom from Rocket data.
virtual void record_object(CullableObject *object, const CullTraverser *traverser)
This callback function is intended to be overridden by a derived class.
Definition: cullHandler.cxx:43
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for geometry primitives.
Definition: geom.h:54
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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:47
const TransformState * get_world_transform() const
Returns the position of the starting node relative to the camera.
Definition: cullTraverser.I:75
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
void add_data3f(float x, float y, float z)
Sets the write row to a particular 3-component value, and advances the write row.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LVecBase2 get_tex_scale() const
Returns a scale pair that is suitable for applying to geometry via NodePath::set_tex_scale(),...
Definition: texture.I:655
SceneSetup * get_scene() const
Returns the SceneSetup object.
Definition: cullTraverser.I:35
static const GeomVertexFormat * get_v3c4t2()
Returns a standard vertex format with a 2-component texture coordinate pair, a 4-component color,...
Defines a series of disconnected triangles.
Definition: geomTriangles.h:23
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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 ...
Definition: loaderOptions.h:69
Defines the properties of a named stage of the multitexture pipeline.
Definition: textureStage.h:35
void unref_delete(RefCountType *ptr)
This global helper function will unref the given ReferenceCount object, and if the reference count re...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
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
This is the data for one array of a GeomVertexData structure.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.