00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <rve_render_server/batching/points_material_generator.h>
00031 #include <rve_render_server/material_definition.h>
00032 #include <rve_render_server/ogre_material_generator.h>
00033 #include <rve_render_server/batching/points_renderer_desc.h>
00034 #include <rve_render_server/init.h>
00035 #include <rve_render_server/renderer.h>
00036
00037 #include <rve_msgs/Points.h>
00038
00039 #include <sstream>
00040
00041 #include <OGRE/OgreRoot.h>
00042 #include <OGRE/OgreMaterialManager.h>
00043 #include <OGRE/OgreTextureManager.h>
00044 #include <OGRE/OgreTexture.h>
00045 #include <OGRE/OgreGpuProgramManager.h>
00046 #include <OGRE/OgreHighLevelGpuProgramManager.h>
00047 #include <OGRE/OgreTechnique.h>
00048 #include <OGRE/OgrePass.h>
00049
00050 namespace rve_render_server
00051 {
00052
00053 std::string descToStringID(const PointsRendererDesc& desc, bool alpha)
00054 {
00055 std::stringstream ss;
00056 ss << "GenPoints_" << (uint32_t)desc.type;
00057
00058 if (desc.has_orientations)
00059 {
00060 ss << "Orientation";
00061 }
00062
00063 if (desc.has_scales)
00064 {
00065 ss << "Scales";
00066 }
00067 else
00068 {
00069 ss << "Scale " << std::setprecision(3) << desc.scale.x << desc.scale.y << desc.scale.z;
00070 }
00071
00072 if (alpha)
00073 {
00074 ss << "Alpha";
00075 }
00076
00077 return ss.str();
00078 }
00079
00080 void fillGenericGPVP(ShaderDefinition& def)
00081 {
00082 def.input("float4", "position", "POSITION");
00083 def.input("float4", "color", "COLOR");
00084 def.input("float4", "t0", "TEXCOORD0");
00085 def.input("float4", "t1", "TEXCOORD1");
00086 def.input("float4", "t2", "TEXCOORD2");
00087 def.input("float4", "point_id", "SPECULAR");
00088 def.outputs.push_back(def.inputs[0]);
00089 def.outputs.push_back(def.inputs[1]);
00090 def.outputs.push_back(def.inputs[2]);
00091 def.outputs.push_back(def.inputs[3]);
00092 def.outputs.push_back(def.inputs[4]);
00093 def.output("float4", "point_id", "TEXCOORD4");
00094 def.body =
00095 " out_position = in_position;\n"
00096 " out_color = in_color;\n"
00097 " out_t0 = in_t0;\n"
00098 " out_t1 = in_t1;\n"
00099 " out_t2 = in_t2;\n"
00100 " out_point_id = in_point_id;\n";
00101 }
00102
00103 static std::string toString(uint32_t i)
00104 {
00105 std::stringstream ss;
00106 ss << i;
00107 return ss.str();
00108 }
00109
00110 void fillVertexShaderDefinition(const PointsRendererDesc& desc, ShaderDefinition& def)
00111 {
00112 bool supports_geometry_programs = getRenderer()->useGeometryShaders();
00113
00114 if (supports_geometry_programs && desc.type != rve_msgs::Points::TYPE_POINTS)
00115 {
00116 fillGenericGPVP(def);
00117 return;
00118 }
00119
00120 def.include("quaternion.cg");
00121
00122 if (desc.type == rve_msgs::Points::TYPE_POINTS)
00123 {
00124
00125 }
00126 else if (desc.type == rve_msgs::Points::TYPE_BILLBOARDS
00127 || desc.type == rve_msgs::Points::TYPE_BILLBOARD_SPHERES)
00128 {
00129 def.include("point_cloud_billboard_vp.cg");
00130 }
00131 else if (desc.type == rve_msgs::Points::TYPE_BOXES)
00132 {
00133 def.include("point_cloud_box_vp.cg");
00134 }
00135
00136 def.input("float4", "position", "POSITION");
00137 def.input("float4", "color", "COLOR");
00138 def.input("float4", "point_id", "SPECULAR");
00139 def.input("float3", "normal", "NORMAL");
00140
00141 uint32_t tex_coord_index = 0;
00142 if (desc.type != rve_msgs::Points::TYPE_POINTS)
00143 {
00144 if (!supports_geometry_programs)
00145 {
00146 def.input("float3", "offset", "TEXCOORD" + toString(tex_coord_index++));
00147 }
00148
00149 if (desc.has_normals)
00150 {
00151 def.input("float3", "face_normal", "TEXCOORD" + toString(tex_coord_index++));
00152 }
00153
00154 if (desc.has_orientations)
00155 {
00156 def.input("float4", "orientation", "TEXCOORD" + toString(tex_coord_index++));
00157 }
00158 }
00159 else
00160 {
00161 if (desc.has_normals)
00162 {
00163 def.input("float3", "face_normal", "TEXCOORD" + toString(tex_coord_index++));
00164 }
00165 }
00166
00167 if (desc.has_scales)
00168 {
00169 def.input("float4", "scale", "TEXCOORD" + toString(tex_coord_index++));
00170 }
00171
00172 def.output("float4", "position", "POSITION");
00173 def.output("float3", "view_pos", "TEXCOORD0");
00174 def.output("float3", "offset", "TEXCOORD1");
00175 def.output("float3", "normal", "TEXCOORD2");
00176 def.output("float4", "color", "TEXCOORD3");
00177 def.output("float4", "point_id", "TEXCOORD4");
00178
00179 def.uniform("float4", "camera_pos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE, 0);
00180 def.uniform("float4x4", "worldviewproj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX, 0);
00181 def.uniform("float4x4", "worldview", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX, 0);
00182
00183
00184 std::stringstream ss;
00185 if (!desc.has_scales)
00186 {
00187 def.uniform("float4", "size", Ogre::GpuProgramParameters::ACT_CUSTOM, PointsRendererDesc::CustomParam_Size);
00188 }
00189 else
00190 {
00191 ss << " float4 size = in_scale;\n";
00192 }
00193
00194 if (desc.type == rve_msgs::Points::TYPE_POINTS)
00195 {
00196 ss << " float4 pos = in_position;\n";
00197 if (desc.has_orientations)
00198 {
00199 ss << " float3 normal = quaternionRotate(in_orientation, float3(0.0, 0.0, -1.0));\n";
00200 }
00201 else if (desc.has_normals)
00202 {
00203 ss << " float3 normal = in_face_normal;\n";
00204 }
00205 else
00206 {
00207 ss << " float3 normal = normalize(camera_pos.xyz - pos.xyz);\n";
00208 }
00209 }
00210 else if (desc.type == rve_msgs::Points::TYPE_BILLBOARDS)
00211 {
00212 if (desc.has_orientations)
00213 {
00214 ss << " PosAndNormal posn = calculateBillboardVertexPositionAndNormalQuat(in_position, in_offset.xy, in_orientation, camera_pos, size);\n";
00215 }
00216 else if (desc.has_normals)
00217 {
00218 ss << " PosAndNormal posn = calculateBillboardVertexPositionAndNormal(in_position, in_offset.xy, in_face_normal, camera_pos, size);\n";
00219 }
00220 else
00221 {
00222 ss << " PosAndNormal posn = calculateBillboardVertexPositionAndNormal(in_position, in_offset.xy, camera_pos, size);\n";
00223 }
00224 ss << " float4 pos = posn.pos;\n";
00225 ss << " float3 normal = posn.normal;\n";
00226 }
00227 else if (desc.type == rve_msgs::Points::TYPE_BILLBOARD_SPHERES)
00228 {
00229 if (desc.has_orientations)
00230 {
00231 ss << " PosAndNormal posn = calculateBillboardSpheresVertexPositionAndNormalQuat(in_position, in_offset.xy, in_orientation, camera_pos, size);\n";
00232 }
00233 else if (desc.has_normals)
00234 {
00235 ss << " PosAndNormal posn = calculateBillboardSpheresVertexPositionAndNormal(in_position, in_offset.xy, in_face_normal, camera_pos, size);\n";
00236 }
00237 else
00238 {
00239 ss << " PosAndNormal posn = calculateBillboardSpheresVertexPositionAndNormal(in_position, in_offset.xy, camera_pos, size);\n";
00240 }
00241 ss << " float4 pos = posn.pos;\n";
00242 ss << " float3 normal = posn.normal;\n";
00243 }
00244 else if (desc.type == rve_msgs::Points::TYPE_BOXES)
00245 {
00246 if (desc.has_orientations)
00247 {
00248 ss << " PosAndNormal posn = calculateBoxVertexPositionAndNormal(in_position, in_offset.xyz, in_normal, in_orientation, worldviewproj, size);\n";
00249 }
00250 else
00251 {
00252 ss << " PosAndNormal posn = calculateBoxVertexPositionAndNormal(in_position, in_offset.xyz, in_normal, worldviewproj, size);\n";
00253 }
00254 ss << " float4 pos = posn.pos;\n";
00255 ss << " float3 normal = posn.normal;\n";
00256 }
00257
00258 ss << " out_position = mul(worldviewproj, pos);\n" << std::endl;
00259 ss << " out_normal = mul(worldview, float4(normal, 0)).xyz;\n" << std::endl;
00260 ss << " out_view_pos = mul(worldview, pos).xyz;\n" << std::endl;
00261 ss << " out_color = in_color;\n";
00262 ss << " out_point_id = in_point_id;\n";
00263 if (!supports_geometry_programs && desc.type != rve_msgs::Points::TYPE_POINTS)
00264 {
00265 ss << " out_offset = in_offset;\n";
00266 }
00267
00268 def.body = ss.str();
00269 }
00270
00271 void fillFragmentShaderDefinition(const PointsRendererDesc& desc, ShaderDefinition& def)
00272 {
00273 if (desc.type == rve_msgs::Points::TYPE_POINTS)
00274 {
00275
00276 }
00277 else if (desc.type == rve_msgs::Points::TYPE_BILLBOARDS
00278 || desc.type == rve_msgs::Points::TYPE_BILLBOARD_SPHERES)
00279 {
00280 def.include("point_cloud_billboard_fp.cg");
00281 }
00282 else if (desc.type == rve_msgs::Points::TYPE_BOXES)
00283 {
00284 def.include("point_cloud_box_fp.cg");
00285 }
00286
00287 def.input("float3", "view_pos", "TEXCOORD0");
00288 def.input("float3", "offset", "TEXCOORD1");
00289 def.input("float3", "normal", "TEXCOORD2");
00290 def.input("float4", "color", "TEXCOORD3");
00291
00292 std::stringstream ss;
00293 ss << " float3 normal = in_normal;" << std::endl;
00294 if (desc.type == rve_msgs::Points::TYPE_POINTS)
00295 {
00296 ss << "float4 color = in_color;\n";
00297 }
00298 else if (desc.type == rve_msgs::Points::TYPE_BILLBOARDS)
00299 {
00300 ss << "float4 color = calculateBillboardColorWithEdge(in_color, in_offset);\n";
00301 }
00302 else if (desc.type == rve_msgs::Points::TYPE_BILLBOARD_SPHERES)
00303 {
00304 ss << "ColorAndNormal can = calculateBillboardSphereColorAndNormal(in_color, in_offset);\n";
00305 ss << "float4 color = can.color;\n";
00306 ss << "normal = can.normal;\n";
00307 }
00308 else if (desc.type == rve_msgs::Points::TYPE_BOXES)
00309 {
00310 ss << "float4 color = calculateBoxColorWithEdge(in_color, in_offset);\n";
00311 }
00312
00313 def.body = ss.str();
00314 }
00315
00316 void fillPickingFragmentShaderDefinition(const PointsRendererDesc& desc, ShaderDefinition& def)
00317 {
00318 if (desc.type == rve_msgs::Points::TYPE_BILLBOARD_SPHERES)
00319 {
00320 def.include("point_cloud_billboard_fp.cg");
00321 }
00322
00323 def.input("float4", "point_id", "TEXCOORD4");
00324 def.uniform("float4", "renderable_id", Ogre::GpuProgramParameters::ACT_CUSTOM, PointsRendererDesc::CustomParam_RenderableID);
00325
00326 std::stringstream ss;
00327 ss << " float4 object_id = renderable_id;\n";
00328 ss << " float4 object_extra = in_point_id;\n";
00329 def.body = ss.str();
00330 }
00331
00332 void fillGeometryShaderDefinition(const PointsRendererDesc& desc, ShaderDefinition& def)
00333 {
00334 def.geom_input = "POINT";
00335 def.geom_output = "TRIANGLE_OUT";
00336
00337 def.include("quaternion.cg");
00338
00339 if (desc.type == rve_msgs::Points::TYPE_POINTS)
00340 {
00341 ROS_ASSERT_MSG(false, "Shouldn't be generating geometry shaders for TYPE_POINTS");
00342
00343 }
00344 else if (desc.type == rve_msgs::Points::TYPE_BILLBOARDS
00345 || desc.type == rve_msgs::Points::TYPE_BILLBOARD_SPHERES)
00346 {
00347 def.include("point_cloud_billboard_gp.cg");
00348 }
00349 else if (desc.type == rve_msgs::Points::TYPE_BOXES)
00350 {
00351 def.include("point_cloud_box_gp.cg");
00352 }
00353
00354 def.input("float4", "position", "POSITION");
00355 def.input("float4", "color", "COLOR");
00356
00357 uint32_t tex_coord_num = 0;
00358
00359 if (desc.has_normals)
00360 {
00361 def.input("float3", "normal", "TEXCOORD" + toString(tex_coord_num++));
00362 }
00363 else if (desc.has_orientations)
00364 {
00365 def.input("float4", "orientation", "TEXCOORD" + toString(tex_coord_num++));
00366 }
00367
00368 if (desc.has_scales)
00369 {
00370 def.input("float4", "scale", "TEXCOORD" + toString(tex_coord_num++));
00371 }
00372 else
00373 {
00374 def.uniform("float4", "size", Ogre::GpuProgramParameters::ACT_CUSTOM, PointsRendererDesc::CustomParam_Size);
00375 }
00376
00377 def.input("float4", "point_id", "TEXCOORD4");
00378
00379 def.uniform("float4", "camera_pos", Ogre::GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE, 0);
00380 def.uniform("float4x4", "worldviewproj", Ogre::GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX, 0);
00381 def.uniform("float4x4", "worldview", Ogre::GpuProgramParameters::ACT_WORLDVIEW_MATRIX, 0);
00382
00383
00384 std::stringstream ss;
00385
00386 if (desc.has_scales)
00387 {
00388 ss << " float4 size = in_scale[0];\n";
00389 }
00390
00391 if (desc.type == rve_msgs::Points::TYPE_BILLBOARDS)
00392 {
00393 if (desc.has_orientations)
00394 {
00395 ss << " emitBillboardVerticesQuat(in_position[0], in_color[0], in_orientation[0], worldviewproj, worldview, camera_pos, size, in_point_id[0]);\n";
00396 }
00397 else if (desc.has_normals)
00398 {
00399 ss << " emitBillboardVertices(in_position[0], in_color[0], in_normal[0], worldviewproj, worldview, camera_pos, size, in_point_id[0]);\n";
00400 }
00401 else
00402 {
00403 ss << " emitBillboardVertices(in_position[0], in_color[0], worldviewproj, worldview, camera_pos, size, in_point_id[0]);\n";
00404 }
00405 }
00406 else if (desc.type == rve_msgs::Points::TYPE_BILLBOARD_SPHERES)
00407 {
00408 if (desc.has_orientations)
00409 {
00410 ss << " emitBillboardSphereVerticesQuat(in_position[0], in_color[0], in_orientation[0], worldviewproj, worldview, camera_pos, size, in_point_id[0]);\n";
00411 }
00412 else if (desc.has_normals)
00413 {
00414 ss << " emitBillboardSphereVertices(in_position[0], in_color[0], in_normal[0], worldviewproj, worldview, camera_pos, size, in_point_id[0]);\n";
00415 }
00416 else
00417 {
00418 ss << " emitBillboardSphereVertices(in_position[0], in_color[0], worldviewproj, worldview, camera_pos, size, in_point_id[0]);\n";
00419 }
00420 }
00421 else if (desc.type == rve_msgs::Points::TYPE_BOXES)
00422 {
00423 if (desc.has_orientations)
00424 {
00425 ss << " emitBoxVertices(in_position[0], in_color[0], in_orientation[0], worldviewproj, worldview, size);\n";
00426 }
00427 else
00428 {
00429 ss << " emitBoxVertices(in_position[0], in_color[0], worldviewproj, worldview, size);\n";
00430 }
00431 }
00432
00433 def.body = ss.str();
00434 }
00435
00436 std::pair<Ogre::MaterialPtr, Ogre::MaterialPtr> generateMaterialsForPoints(const PointsRendererDesc& desc)
00437 {
00438 std::string material_name_opaque = descToStringID(desc, false);
00439 std::string material_name_alpha = descToStringID(desc, true);
00440
00441 MaterialDefinition mat_def;
00442 fillVertexShaderDefinition(desc, mat_def.vertex_def);
00443 fillFragmentShaderDefinition(desc, mat_def.fragment_def);
00444 fillPickingFragmentShaderDefinition(desc, mat_def.picking_fragment_def);
00445
00446 bool supports_geometry_programs = getRenderer()->useGeometryShaders();
00447 if (supports_geometry_programs && desc.type != rve_msgs::Points::TYPE_POINTS)
00448 {
00449 fillGeometryShaderDefinition(desc, mat_def.geometry_def);
00450 mat_def.has_geometry_shader = true;
00451 }
00452
00453 mat_def.name = material_name_opaque;
00454 Ogre::MaterialPtr mat_opaque = generateOgreMaterial(mat_def);
00455 mat_opaque->setPointSize(5);
00456 mat_opaque->setCullingMode(Ogre::CULL_NONE);
00457
00458 mat_def.name = material_name_alpha;
00459 mat_def.transparent = true;
00460 Ogre::MaterialPtr mat_alpha = generateOgreMaterial(mat_def);
00461 mat_alpha->setPointSize(5);
00462 mat_alpha->setCullingMode(Ogre::CULL_NONE);
00463
00464 return std::make_pair(mat_opaque, mat_alpha);
00465 }
00466
00467 }
00468