Panda3D
 All Classes Functions Variables Enumerations
rocketRenderInterface.cxx
00001 // Filename: rocketRenderInterface.cxx
00002 // Created by:  rdb (04Nov11)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "rocketRenderInterface.h"
00016 #include "cullableObject.h"
00017 #include "cullHandler.h"
00018 #include "geomVertexData.h"
00019 #include "geomVertexArrayData.h"
00020 #include "internalName.h"
00021 #include "geomVertexWriter.h"
00022 #include "geomTriangles.h"
00023 #include "colorBlendAttrib.h"
00024 #include "cullBinAttrib.h"
00025 #include "depthTestAttrib.h"
00026 #include "depthWriteAttrib.h"
00027 #include "scissorAttrib.h"
00028 #include "texture.h"
00029 #include "textureAttrib.h"
00030 #include "texturePool.h"
00031 
00032 ////////////////////////////////////////////////////////////////////
00033 //     Function: RocketRenderInterface::render
00034 //       Access: Public
00035 //  Description: Called by RocketNode in cull_callback.  Invokes
00036 //               context->Render() and culls the result.
00037 ////////////////////////////////////////////////////////////////////
00038 void RocketRenderInterface::
00039 render(Rocket::Core::Context* context, CullTraverser *trav) {
00040   nassertv(context != NULL);
00041   MutexHolder holder(_lock);
00042 
00043   _trav = trav;
00044   _net_transform = trav->get_world_transform();
00045   _net_state = RenderState::make(
00046     CullBinAttrib::make("unsorted", 0),
00047     DepthTestAttrib::make(RenderAttrib::M_none),
00048     DepthWriteAttrib::make(DepthWriteAttrib::M_off),
00049     ColorBlendAttrib::make(ColorBlendAttrib::M_add,
00050       ColorBlendAttrib::O_incoming_alpha,
00051       ColorBlendAttrib::O_one_minus_incoming_alpha
00052     )
00053   );
00054   _dimensions = context->GetDimensions();
00055 
00056   context->Render();
00057 
00058   _trav = NULL;
00059   _net_transform = NULL;
00060   _net_state = NULL;
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: RocketRenderInterface::make_geom
00065 //       Access: Protected
00066 //  Description: Called internally to make a Geom from Rocket data.
00067 ////////////////////////////////////////////////////////////////////
00068 PT(Geom) RocketRenderInterface::
00069 make_geom(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, GeomEnums::UsageHint uh) {
00070   PT(GeomVertexData) vdata = new GeomVertexData("", GeomVertexFormat::get_v3c4t2(), uh);
00071   vdata->unclean_set_num_rows(num_vertices);
00072   {
00073     GeomVertexWriter vwriter(vdata, InternalName::get_vertex());
00074     GeomVertexWriter cwriter(vdata, InternalName::get_color());
00075     GeomVertexWriter twriter(vdata, InternalName::get_texcoord());
00076 
00077     // Write the vertex information.
00078     for (int i = 0; i < num_vertices; ++i) {
00079       const Rocket::Core::Vertex &vertex = vertices[i];
00080 
00081       vwriter.add_data3f(LVector3f::right() * vertex.position.x + LVector3f::up() * vertex.position.y);
00082       cwriter.add_data4i(vertex.colour.red, vertex.colour.green,
00083                          vertex.colour.blue, vertex.colour.alpha);
00084       twriter.add_data2f(vertex.tex_coord.x, 1.0f - vertex.tex_coord.y);
00085     }
00086   }
00087 
00088   // Create a primitive and write the indices.
00089   PT(GeomTriangles) triangles = new GeomTriangles(uh);
00090   {
00091     PT(GeomVertexArrayData) idata = triangles->modify_vertices();
00092     idata->unclean_set_num_rows(num_indices);
00093     GeomVertexWriter iwriter(idata, 0);
00094 
00095     for (int i = 0; i < num_indices; ++i) {
00096       iwriter.add_data1i(indices[i]);
00097     }
00098   }
00099 
00100   PT(Geom) geom = new Geom(vdata);
00101   geom->add_primitive(triangles);
00102   return geom;
00103 }
00104 
00105 ////////////////////////////////////////////////////////////////////
00106 //     Function: RocketRenderInterface::render_geom
00107 //       Access: Protected
00108 //  Description: Only call this during render().  Culls a geom.
00109 ////////////////////////////////////////////////////////////////////
00110 void RocketRenderInterface::
00111 render_geom(const Geom* geom, const RenderState* state, const Rocket::Core::Vector2f& translation) {
00112   LVector3 offset = LVector3::right() * translation.x + LVector3::up() * translation.y;
00113 
00114   if (_enable_scissor) {
00115     state = state->add_attrib(ScissorAttrib::make(_scissor));
00116     rocket_cat.spam()
00117       << "Rendering geom " << geom << " with state "
00118       << *state << ", translation (" << offset << "), "
00119       << "scissor region (" << _scissor << ")\n";
00120   } else {
00121     rocket_cat.spam()
00122       << "Rendering geom " << geom << " with state "
00123       << *state << ", translation (" << offset << ")\n";
00124   }
00125 
00126   CPT(TransformState) net_transform, modelview_transform;
00127   net_transform = _net_transform->compose(TransformState::make_pos(offset));
00128   modelview_transform = _trav->get_world_transform()->compose(net_transform);
00129 
00130   CullableObject *object =
00131     new CullableObject(geom, _net_state->compose(state),
00132                        net_transform, modelview_transform,
00133                        _trav->get_gsg());
00134   _trav->get_cull_handler()->record_object(object, _trav);
00135 }
00136 
00137 ////////////////////////////////////////////////////////////////////
00138 //     Function: RocketRenderInterface::RenderGeometry
00139 //       Access: Protected
00140 //  Description: Called by Rocket when it wants to render geometry
00141 //               that the application does not wish to optimize.
00142 ////////////////////////////////////////////////////////////////////
00143 void RocketRenderInterface::
00144 RenderGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture, const Rocket::Core::Vector2f& translation) {
00145   PT(Geom) geom = make_geom(vertices, num_vertices, indices, num_indices, GeomEnums::UH_stream);
00146 
00147   CPT(RenderState) state;
00148   if ((Texture*) texture != (Texture*) NULL) {
00149     state = RenderState::make(TextureAttrib::make((Texture*) texture));
00150   } else {
00151     state = RenderState::make_empty();
00152   }
00153 
00154   render_geom(geom, state, translation);
00155 }
00156 
00157 ////////////////////////////////////////////////////////////////////
00158 //     Function: RocketRenderInterface::CompileGeometry
00159 //       Access: Protected      
00160 //  Description: Called by Rocket when it wants to compile geometry
00161 //               it believes will be static for the forseeable future.
00162 ////////////////////////////////////////////////////////////////////
00163 Rocket::Core::CompiledGeometryHandle RocketRenderInterface::
00164 CompileGeometry(Rocket::Core::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rocket::Core::TextureHandle texture) {
00165 
00166   CompiledGeometry *c = new CompiledGeometry;
00167   c->_geom = make_geom(vertices, num_vertices, indices, num_indices, GeomEnums::UH_static);
00168 
00169   if ((Texture*) texture != (Texture*) NULL) {
00170     PT(TextureStage) stage = new TextureStage("");
00171     stage->set_mode(TextureStage::M_modulate);
00172 
00173     CPT(TextureAttrib) attr = DCAST(TextureAttrib, TextureAttrib::make());
00174     attr = DCAST(TextureAttrib, attr->add_on_stage(stage, (Texture*) texture));
00175 
00176     c->_state = RenderState::make(attr);
00177 
00178     rocket_cat.debug()
00179       << "Compiled geom " << c->_geom << " with texture '"
00180       << ((Texture*) texture)->get_name() << "'\n";
00181   } else {
00182     c->_state = RenderState::make_empty();
00183 
00184     rocket_cat.debug()
00185       << "Compiled geom " << c->_geom << " without texture\n";
00186   }
00187 
00188   return (Rocket::Core::CompiledGeometryHandle) c;
00189 }
00190 
00191 ////////////////////////////////////////////////////////////////////
00192 //     Function: RocketRenderInterface::RenderCompiledGeometry
00193 //       Access: Protected
00194 //  Description: Called by Rocket when it wants to render
00195 //               application-compiled geometry.
00196 ////////////////////////////////////////////////////////////////////
00197 void RocketRenderInterface::
00198 RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry, const Rocket::Core::Vector2f& translation) {
00199 
00200   CompiledGeometry *c = (CompiledGeometry*) geometry;
00201   render_geom(c->_geom, c->_state, translation);
00202 }
00203 
00204 ////////////////////////////////////////////////////////////////////
00205 //     Function: RocketRenderInterface::ReleaseCompiledGeometry
00206 //       Access: Protected
00207 //  Description: Called by Rocket when it wants to release
00208 //               application-compiled geometry.
00209 ////////////////////////////////////////////////////////////////////
00210 void RocketRenderInterface::
00211 ReleaseCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry) {
00212   delete (CompiledGeometry*) geometry;
00213 }
00214 
00215 ////////////////////////////////////////////////////////////////////
00216 //     Function: RocketRenderInterface::LoadTexture
00217 //       Access: Protected
00218 //  Description: Called by Rocket when a texture is required by the
00219 //               library.
00220 ////////////////////////////////////////////////////////////////////
00221 bool RocketRenderInterface::
00222 LoadTexture(Rocket::Core::TextureHandle& texture_handle,
00223             Rocket::Core::Vector2i& texture_dimensions,
00224             const Rocket::Core::String& source) {
00225 
00226   PT(Texture) tex = TexturePool::load_texture(Filename::from_os_specific(source.CString()));
00227   if (tex == NULL) {
00228     texture_handle = 0;
00229     texture_dimensions.x = 0;
00230     texture_dimensions.y = 0;
00231     return false;
00232   }
00233 
00234   texture_dimensions.x = tex->get_x_size();
00235   texture_dimensions.y = tex->get_y_size();
00236   tex->ref();
00237   texture_handle = (Rocket::Core::TextureHandle) tex.p();
00238 
00239   return true;
00240 }
00241 
00242 ////////////////////////////////////////////////////////////////////
00243 //     Function: RocketRenderInterface::GenerateTexture
00244 //       Access: Protected
00245 //  Description: Called by Rocket when a texture is required to be
00246 //               built from an internally-generated sequence of pixels.
00247 ////////////////////////////////////////////////////////////////////
00248 bool RocketRenderInterface::
00249 GenerateTexture(Rocket::Core::TextureHandle& texture_handle,
00250                 const Rocket::Core::byte* source,
00251                 const Rocket::Core::Vector2i& source_dimensions) {
00252 
00253   PT(Texture) tex = new Texture;
00254   tex->setup_2d_texture(source_dimensions.x, source_dimensions.y,
00255                         Texture::T_unsigned_byte, Texture::F_rgba);
00256   PTA_uchar image = tex->modify_ram_image();
00257 
00258   // Convert RGBA to BGRA
00259   size_t row_size = source_dimensions.x * 4;
00260   size_t y2 = image.size();
00261   for (size_t y = 0; y < image.size(); y += row_size) {
00262     y2 -= row_size;
00263     for (size_t i = 0; i < row_size; i += 4) {
00264       image[y2 + i + 0] = source[y + i + 2];
00265       image[y2 + i + 1] = source[y + i + 1];
00266       image[y2 + i + 2] = source[y + i];
00267       image[y2 + i + 3] = source[y + i + 3];
00268     }
00269   }
00270 
00271   tex->set_wrap_u(Texture::WM_clamp);
00272   tex->set_wrap_v(Texture::WM_clamp);
00273 
00274   tex->ref();
00275   texture_handle = (Rocket::Core::TextureHandle) tex.p();
00276 
00277   return true;
00278 }
00279 
00280 ////////////////////////////////////////////////////////////////////
00281 //     Function: RocketRenderInterface::ReleaseTexture
00282 //       Access: Protected
00283 //  Description: Called by Rocket when a loaded texture is no longer
00284 //               required.
00285 ////////////////////////////////////////////////////////////////////
00286 void RocketRenderInterface::
00287 ReleaseTexture(Rocket::Core::TextureHandle texture_handle) {
00288   Texture* tex = (Texture*) texture_handle;
00289   if (tex != (Texture*) NULL) {
00290     tex->unref();
00291   }
00292 }
00293 
00294 ////////////////////////////////////////////////////////////////////
00295 //     Function: RocketRenderInterface::EnableScissorRegion
00296 //       Access: Protected
00297 //  Description: Called by Rocket when it wants to enable or disable
00298 //               scissoring to clip content.
00299 ////////////////////////////////////////////////////////////////////
00300 void RocketRenderInterface::
00301 EnableScissorRegion(bool enable) {
00302   _enable_scissor = enable;
00303 }
00304 
00305 ////////////////////////////////////////////////////////////////////
00306 //     Function: RocketRenderInterface::SetScissorRegion
00307 //       Access: Protected
00308 //  Description: Called by Rocket when it wants to change the
00309 //               scissor region.
00310 ////////////////////////////////////////////////////////////////////
00311 void RocketRenderInterface::
00312 SetScissorRegion(int x, int y, int width, int height) {
00313   _scissor[0] = x / (PN_stdfloat) _dimensions.x;
00314   _scissor[1] = (x + width) / (PN_stdfloat) _dimensions.x;
00315   _scissor[2] = 1.0f - ((y + height) / (PN_stdfloat) _dimensions.y);
00316   _scissor[3] = 1.0f - (y / (PN_stdfloat) _dimensions.y);
00317 }
 All Classes Functions Variables Enumerations