Commit b3682032 authored by Sebastien Barre's avatar Sebastien Barre
Browse files

first stab at text actor 3D (texture-based text actor that can be placed anywhere)

parent cff6ac56
......@@ -93,6 +93,7 @@ vtkSelectVisiblePoints.cxx
vtkTesting.cxx
vtkTextActor.cxx
# vtkTextActor2D.cxx
vtkTextActor3D.cxx
vtkTextMapper.cxx
vtkTextProperty.cxx
vtkTexture.cxx
......
package require vtk
package require vtkinteraction
# Renderer, renwin
vtkRenderer ren1
ren1 SetBackground 0.1 0.2 0.4
vtkRenderWindow renWin
renWin AddRenderer ren1
renWin SetSize 600 600
# The Tk render widget
set vtkw [vtkTkRenderWidget .ren -width 600 -height 600 -rw renWin]
::vtk::bind_tk_render_widget $vtkw
pack $vtkw -side top -fill both -expand yes
# Base text property
vtkTextProperty base_text_prop
base_text_prop SetFontSize 24
base_text_prop ShadowOn
base_text_prop SetColor 1.0 0.0 0.0
base_text_prop SetFontFamilyToArial
set base_scale 0.005
# The text actors
set text_actors {}
# Add a sphere
proc add_sphere {} {
vtkSphereSource obj_source
vtkPolyDataMapper obj_mapper
obj_mapper SetInput [obj_source GetOutput]
vtkActor obj_actor
obj_actor SetMapper obj_mapper
[obj_actor GetProperty] SetRepresentationToWireframe
ren1 AddActor obj_actor
}
# Add one text actor, centered
proc add_one_text_actor {} {
global base_scale text_actors
vtkTextActor3D ia
ia SetInput "This is a test"
ia SetScale $base_scale
lappend text_actors ia
set tprop [ia GetTextProperty]
$tprop ShallowCopy base_text_prop
}
# Add many text actor
proc add_many_text_actors {} {
global base_scale text_actors
vtkColorTransferFunction lut
lut SetColorSpaceToHSV
lut AddRGBPoint 0.0 0.0 1.0 1.0
lut AddRGBPoint 1.0 1.0 1.0 1.0
for {set i 0} {$i < 10} {incr i} {
set name "ia$i"
vtkTextActor3D $name
$name SetInput " This is a test ($i)"
$name SetScale $base_scale
$name SetOrientation 0 [expr $i * 36] 0
lappend text_actors $name
set tprop [$name GetTextProperty]
$tprop ShallowCopy base_text_prop
set value [expr $i / 10.0]
eval $tprop SetColor [lut GetColor $value]
eval $tprop SetColor [lut GetRedValue $value] [lut GetGreenValue $value] [lut GetBlueValue $value]
}
lut Delete
}
# Add control of orientation
set scale_orientation [scale .orientation \
-from 0 -to 360 -res 1 \
-orient horizontal \
-label "Text orientation:" \
-command update_text_actors]
$scale_orientation set [base_text_prop GetOrientation]
pack $scale_orientation -side top -fill x -expand n
# Add control of font size
set scale_font_size [scale .font_size \
-from 5 -to 150 -res 1 \
-orient horizontal \
-label "Font Size:" \
-command update_text_actors]
$scale_font_size set [base_text_prop GetFontSize]
pack $scale_font_size -side top -fill x -expand n
# Add control of scale
set scale_scale [scale .scale \
-from 0 -to 100 -res 1 \
-orient horizontal \
-label "Actor scale:" \
-command update_text_actors]
$scale_scale set [expr $base_scale * 10000.0]
pack $scale_scale -side top -fill x -expand n
# Update all text actors
proc update_text_actors {dummy} {
global scale_orientation scale_font_size scale_scale
set orientation [$scale_orientation get]
set font_size [$scale_font_size get]
set scale [expr [$scale_scale get] / 10000.0]
global text_actors
foreach actor $text_actors {
$actor SetScale $scale
set tprop [$actor GetTextProperty]
$tprop SetFontSize $font_size
$tprop SetOrientation $orientation
}
renWin Render
}
# Create and add all text actors
if {0} {
add_sphere
add_one_text_actor
} {
add_many_text_actors
set cam [ren1 GetActiveCamera]
$cam Elevation 30
$cam Dolly 0.3
}
foreach actor $text_actors {
ren1 AddActor $actor
}
# Interact
ren1 ResetCamera
renWin Render
wm protocol . WM_DELETE_WINDOW ::vtk::cb_exit
tkwait window .
vtkCommand DeleteAllObject
/*=========================================================================
Program: Visualization Toolkit
Module: vtkTextActor3D.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkTextActor3D.h"
#include "vtkObjectFactory.h"
#include "vtkCamera.h"
#include "vtkImageActor.h"
#include "vtkImageData.h"
#include "vtkTransform.h"
#include "vtkTextProperty.h"
#include "vtkRenderer.h"
#include "vtkWindow.h"
#include "vtkFreeTypeUtilities.h"
#include "vtkMatrix4x4.h"
#include "vtkMath.h"
vtkCxxRevisionMacro(vtkTextActor3D, "1.1");
vtkStandardNewMacro(vtkTextActor3D);
vtkCxxSetObjectMacro(vtkTextActor3D, TextProperty, vtkTextProperty);
// ----------------------------------------------------------------------------
vtkTextActor3D::vtkTextActor3D()
{
this->Input = NULL;
this->ImageActor = NULL;
this->ImageData = NULL;
this->TextProperty = NULL;
this->BuildTime.Modified();
this->SetTextProperty(vtkTextProperty::New());
this->TextProperty->Delete();
}
// --------------------------------------------------------------------------
vtkTextActor3D::~vtkTextActor3D()
{
this->SetTextProperty(NULL);
this->SetInput(NULL);
if (this->ImageActor)
{
this->ImageActor->Delete();
this->ImageActor = NULL;
}
if (this->ImageData)
{
this->ImageData->Delete();
this->ImageData = NULL;
}
}
// --------------------------------------------------------------------------
void vtkTextActor3D::ShallowCopy(vtkProp *prop)
{
vtkTextActor3D *a = vtkTextActor3D::SafeDownCast(prop);
if (a != NULL)
{
this->SetInput(a->GetInput());
this->SetTextProperty(a->GetTextProperty());
}
this->Superclass::ShallowCopy(prop);
}
// --------------------------------------------------------------------------
double* vtkTextActor3D::GetBounds()
{
if (this->ImageActor)
{
return this->ImageActor->GetBounds();
}
return NULL;
}
// --------------------------------------------------------------------------
void vtkTextActor3D::ReleaseGraphicsResources(vtkWindow *win)
{
if (this->ImageActor)
{
this->ImageActor->ReleaseGraphicsResources(win);
}
this->Superclass::ReleaseGraphicsResources(win);
}
// --------------------------------------------------------------------------
int vtkTextActor3D::RenderOverlay(vtkViewport *viewport)
{
int rendered_something = 0;
if (this->UpdateImageActor() && this->ImageActor)
{
rendered_something += this->ImageActor->RenderOverlay(viewport);
}
return rendered_something;
}
// --------------------------------------------------------------------------
int vtkTextActor3D::RenderTranslucentGeometry(vtkViewport *viewport)
{
int rendered_something = 0;
if (this->UpdateImageActor() && this->ImageActor)
{
rendered_something +=
this->ImageActor->RenderTranslucentGeometry(viewport);
}
return rendered_something;
}
// --------------------------------------------------------------------------
int vtkTextActor3D::RenderOpaqueGeometry(vtkViewport *viewport)
{
int rendered_something = 0;
if (this->UpdateImageActor() && this->ImageActor)
{
rendered_something +=
this->ImageActor->RenderOpaqueGeometry(viewport);
}
return rendered_something;
}
// --------------------------------------------------------------------------
int vtkTextActor3D::UpdateImageActor()
{
// Need text prop
if (!this->TextProperty)
{
vtkErrorMacro(<<"Need a text property to render text actor");
return 0;
}
// No input, don't render
if (!this->Input)
{
return 0;
}
// Do we need to (re-)render the text ?
// Yes if:
// - instance has been modified since last build
// - text prop has been modified since last build
// - ImageData ivar has not been allocated yet
if (this->GetMTime() > this->BuildTime ||
this->TextProperty->GetMTime() > this->BuildTime ||
!this->ImageData)
{
//cout << "Need to re-render " << this->GetMTime() << ", " << this->TextProperty->GetMTime() << ", " << this->BuildTime << endl;
this->BuildTime.Modified();
// Get the bounding box of the text to render
vtkFreeTypeUtilities *fu = vtkFreeTypeUtilities::GetInstance();
if (!fu)
{
vtkErrorMacro(<<"Failed getting the FreeType utilities instance");
return 0;
}
int text_bbox[4];
fu->GetBoundingBox(this->TextProperty, this->Input, text_bbox);
if (!fu->IsBoundingBoxValid(text_bbox))
{
return 0;
}
// The bounding box was the area that is going to be filled with pixels
// given a text origin of (0, 0). Now get the real size we need, i.e.
// the full extent from the origin to the bounding box.
int text_size[2];
text_size[0] = (text_bbox[1] - text_bbox[0] + 1) + abs(text_bbox[0]);
text_size[1] = (text_bbox[3] - text_bbox[2] + 1) + abs(text_bbox[2]);
// If the RGBA image data is too small, resize it to the next power of 2
// WARNING: at this point, since this image is going to be a texture
// we should limit its size or query the hardware
if (!this->ImageData)
{
this->ImageData = vtkImageData::New();
this->ImageData->SetScalarTypeToUnsignedChar();
this->ImageData->SetNumberOfScalarComponents(4);
this->ImageData->SetSpacing(1.0, 1.0, 1.0);
}
// If the current image data is too small to render the text,
// or more than twice as big (too hungry), then resize
int img_dims[3], new_img_dims[3];
this->ImageData->GetDimensions(img_dims);
if (img_dims[0] < text_size[0] || img_dims[1] < text_size[1] ||
text_size[0] * 2 < img_dims[0] || text_size[1] * 2 < img_dims[0])
{
new_img_dims[0] = 1 << (int)ceil(log((double)text_size[0]) / log(2.0));
new_img_dims[1] = 1 << (int)ceil(log((double)text_size[1]) / log(2.0));
new_img_dims[2] = 1;
if (new_img_dims[0] != img_dims[0] ||
new_img_dims[1] != img_dims[1] ||
new_img_dims[2] != img_dims[2])
{
//cout << "I need: " << text_size[0] << "x" << text_size[1] << ", I resize to: " << new_img_dims[0] << "x" << new_img_dims[1] << endl;
this->ImageData->SetDimensions(new_img_dims);
this->ImageData->AllocateScalars();
this->ImageData->UpdateInformation();
this->ImageData->SetUpdateExtent(this->ImageData->GetWholeExtent());
this->ImageData->PropagateUpdateExtent();
if (this->ImageActor)
{
this->ImageActor->SetDisplayExtent(
this->ImageData->GetWholeExtent());
}
}
}
// Render inside the image data
int x = (text_bbox[0] < 0 ? -text_bbox[0] : 0);
int y = (text_bbox[2] < 0 ? -text_bbox[2] : 0);
#if 0
char *ptr = (char*)this->ImageData->GetScalarPointer();
int nb_comp = this->ImageData->GetNumberOfScalarComponents();
char *ptr_end = ptr + this->ImageData->GetNumberOfPoints() * nb_comp;
memset(ptr, 0, ptr_end - ptr);
ptr += nb_comp - 1;
while (ptr < ptr_end)
{
*ptr = 255.0;
ptr += nb_comp;
}
#else
memset(this->ImageData->GetScalarPointer(),
0,
(this->ImageData->GetNumberOfPoints() *
this->ImageData->GetNumberOfScalarComponents()));
#endif
if (!fu->RenderString(
this->TextProperty, this->Input, x, y, this->ImageData))
{
vtkErrorMacro(<<"Failed rendering text to buffer");
return 0;
}
// Set the image data origin so that oriented text is placed properly
// Also take shadow into account, we want the text to be on the baseline
if (this->TextProperty->GetShadow())
{
// this is wrong
//x += this->TextProperty->GetShadowOffset()[0];
//y += this->TextProperty->GetShadowOffset()[1];
}
this->ImageData->SetOrigin(-x, -y, 0);
}
// Associate the image data (should be up to date now) to the image actor
if (!this->ImageActor)
{
this->ImageActor = vtkImageActor::New();
this->ImageActor->InterpolateOn();
}
this->ImageActor->SetInput(this->ImageData);
// Position the actor
// Which one is faster ?
#if 1
vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
this->GetMatrix(matrix);
this->ImageActor->SetUserMatrix(matrix);
matrix->Delete();
#else
this->ImageActor->SetPosition(this->GetPosition());
this->ImageActor->SetScale(this->GetScale());
this->ImageActor->SetOrientation(this->GetOrientation());
#endif
return 1;
}
// --------------------------------------------------------------------------
void vtkTextActor3D::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
if (this->TextProperty)
{
os << indent << "Text Property:\n";
this->TextProperty->PrintSelf(os, indent.GetNextIndent());
}
else
{
os << indent << "Text Property: (none)\n";
}
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkTextActor3D.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// .NAME vtkTextActor3D - An actor that displays text.
// .SECTION Description
// The input text is rendered into a buffer, which in turn is used as a
// texture applied onto a quad (a vtkImageActor is used under the hood).
// .SECTION Warning
// This class is experimental at the moment.
// - The orientation is not optimized, the quad should be oriented, not
// the text itself when it is rendered in the buffer (we end up with
// excessively big textures for 45 degrees angles).
// This will be fixed first.
// - No checking is done at the moment regarding hardware texture size limits.
// - Alignment is not supported (soon).
// - Multiline is not supported.
//
// .SECTION See Also
// vtkProp3D
#ifndef __vtkTextActor3D_h
#define __vtkTextActor3D_h
#include "vtkProp3D.h"
class vtkImageActor;
class vtkImageData;
class vtkTextProperty;
class VTK_RENDERING_EXPORT vtkTextActor3D : public vtkProp3D
{
public:
static vtkTextActor3D *New();
vtkTypeRevisionMacro(vtkTextActor3D,vtkProp3D);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Set the text string to be displayed.
vtkSetStringMacro(Input);
vtkGetStringMacro(Input);
// Description:
// Set/Get the text property.
virtual void SetTextProperty(vtkTextProperty *p);
vtkGetObjectMacro(TextProperty,vtkTextProperty);
// Description:
// Shallow copy of this text actor. Overloads the virtual
// vtkProp method.
void ShallowCopy(vtkProp *prop);
// Description:
// Get the bounds for this Prop3D as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
virtual double *GetBounds();
//BTX
// Description:
// WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE
// DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS.
// Release any graphics resources that are being consumed by this actor.
// The parameter window could be used to determine which graphic
// resources to release.
virtual void ReleaseGraphicsResources(vtkWindow *);
// Description:
// WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE
// DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS.
// Draw the text actor to the screen.
int RenderOpaqueGeometry(vtkViewport* viewport);
int RenderTranslucentGeometry(vtkViewport* viewport);
int RenderOverlay(vtkViewport* viewport);
//ETX
protected:
vtkTextActor3D();
~vtkTextActor3D();
char *Input;
vtkImageActor *ImageActor;
vtkImageData *ImageData;
vtkTextProperty *TextProperty;
vtkTimeStamp BuildTime;
virtual int UpdateImageActor();
private:
vtkTextActor3D(const vtkTextActor3D&); // Not implemented.
void operator=(const vtkTextActor3D&); // Not implemented.
};
#endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment