Home

hersto:  TextureTextLine.wrl

Source of TextureTextLine.wrl:

Here is a link for right-clicking and downloading the file: TextureTextLine.wrl (13.4 K Byte),

and below is its content to view online.


#VRML V2.0 utf8



WorldInfo
{
    title "Copyright (C) 2002 by Herbert Stocker (AKA hersto)"

    info 
    [
"       The original versions of the PROTO TextureTextLine was written
        by me, Herbert Stocker. 

        The original versions and some test and demonstration Worlds can
        be found at http://www.hersto.de/ .
"

"       You can use and modify the PROTO in this file if you keep the credit
        information valid and if you don't remove the link to the originating
        site http://www.hersto.de/ .

        In brief, keep this WorldInfo node along with the Proto.
"

"       Please send a message to hersto@hersto.de where you describe how you
        use or improved the nodes. Especially if you included the improved
        versions.
"
    ]
}




#
#EXTERNPROTO TextureTextLine
#[
#    exposedField SFString text         # ""
#    exposedField SFVec2f  size         # .7 1
#    exposedField SFString allign       # "LEFT"  # or "CENTER" or "RIGHT"
#
#    field        SFBool   singleSided  # TRUE # Would prefer an SFBool twoSided, but type conversion or semantics conversion cannot be performed with the IS statement.
#
#    # configuration parameters that describe the font texture
#    field    SFFloat   baseLine        # .2   # multiplied with size.y this is the distance of the base line to the bottom of letters like g, p, q, etc.
#
#    field    SFInt32   firstChar       # 32   # utf8 code of it. (Ok, only ascii code is supported for the text field).
#    field    SFInt32   numCharsHorz    # 16
#    field    SFInt32   numCharsVert    # 14
#
#    field    SFInt32   imageWidth      # 512
#    field    SFInt32   imageHeight     # 448
#
#
#    eventOut     SFBool   isLoaded 
#]
#  "TextureTextLine.wrl#TextureTextLine"
#


PROTO TextureTextLine
[
    exposedField SFString text ""
    exposedField SFVec2f  size .7 1
    exposedField SFString allign "LEFT"  # or "CENTER" or "RIGHT"

    field        SFBool   singleSided TRUE # Would prefer an SFBool twoSided, but type conversion or semantics conversion cannot be performed with the IS statement.


    # configuration parameters that describe the font texture # TBD: should be moved to an external PROTO similar to the FontStyle node.
    field    SFFloat   baseLine       .2   # multiplied with size.y this is the distance of the base line to the bottom of letters like g, p, q, etc.

    field    SFInt32   firstChar      32   # utf8 code of it. (Ok, it's ascii code).
    field    SFInt32   numCharsHorz   16
    field    SFInt32   numCharsVert   14

    field    SFInt32   imageWidth     512
    field    SFInt32   imageHeight    448

    eventOut     SFBool   isLoaded 

    field MFString credits "Initial idea and copyright by Herbert Stocker, http://www.hersto.com/"
]
{
    DEF IFS IndexedFaceSet
    {
        coord DEF Coord Coordinate
        {
        }

        texCoord DEF TexCoord TextureCoordinate
        {
        }

        solid IS singleSided
    }

    PROTO EFFS 
    [
    exposedField SFString text ""
    exposedField SFVec2f  size .7 1
    exposedField SFString allign "LEFT"
    ]
      { Group {} }

    DEF EFFS EFFS
    {
        text     IS text
        size     IS size
        allign   IS allign
    }



    DEF Worker Script
    {
        #interface
        field    SFNode    effs USE EFFS
        eventIn  SFString  set_text 
        eventIn  SFVec2f   set_size 
        eventIn  SFString  set_allign

        eventOut MFVec3f   coord_changed
        eventOut MFInt32   coordIdx_changed
        eventOut MFVec2f   texCoord_changed
        eventOut MFInt32   textCoordIdx_changed
        eventOut SFBool    solid_changed


        #config
        # TBD: these #config parameters should be specifyable on the PROTO interface.
        field    SFFloat   baseLine       IS baseLine

        field    SFInt32   firstChar      IS firstChar
        field    SFInt32   numCharsHorz   IS numCharsHorz
        field    SFInt32   numCharsVert   IS numCharsVert

        field    SFInt32   imageWidth     IS imageWidth
        field    SFInt32   imageHeight    IS imageHeight
        

        #internal
        field    SFString  text           ""
        field    SFVec2f   size           .7 1
        field    SFInt32   allign         0   # = cAllignLeft

        field    SFBool    haveNewText    FALSE
        field    SFBool    haveNewSize    FALSE
        field    SFBool    haveNewAllign  FALSE

        field    SFInt32   cAllignLeft    0
        field    SFInt32   cAllignCenter  1
        field    SFInt32   cAllignRight   2

        field    SFBool   IsCosmo         FALSE

        field    SFInt32  PixelPerCharHorz 0
        field    SFInt32  PixelPerCharVert 0


        url "vrmlscript:

        // Is there any function that returns the utf8 value of a character? 
        // Could be usefull now. 

        // Since I don't know of any, I'm doing it on my own. 
        // And since utf8 is such a large range, we do it only for extended ascii, 
        // i.e. for values from 32 to 255. I.e. for one of the old character setst that
        // were in use before utf8 (unicode) came.

        function ascii(ch)
        {
            if(IsCosmo)
            {
                // Cosmo even can't compare two strings. ARGH!
                // Why is the specification of the VRML standard (and VrmlScript) so incomplete! AARRGGHH!

                // So we have to do linear search. What kind of software design is this!!!
                for(var C= 32; C<256; C++ )
                {
                    if(ch == chr(C))
        return C;
                }
            }


            // we do successive approximation:
            var Min= 0;
            var Max= 256;

            while(Max - Min > 1)
            {
                var Mid= Math.floor((Min + Max) / 2);

                if(ch < chr(Mid))
                    Max= Mid;
                else
                    Min= Mid;
            }

        return Min;
        }


        function chr(asc)
        {
        return ascii2Char[Math.floor(asc / 16)].charAt(asc % 16);
        }


        function Update()
        {

            if(haveNewText || haveNewSize || haveNewAllign)
            {
                var Shift= allign == cAllignLeft?   0               :(
                           allign == cAllignCenter? text.length / 2 :(
                           allign == cAllignRight?  text.length     :   
                                                    0             ));

                var BottomY=      baseLine  * -size.y;
                var TopY=    (1 - baseLine) *  size.y;

                var Coord= new MFVec3f;
                Coord.length= text.length * 2 + 2;

                for(var CharNo= 0; CharNo<=text.length; CharNo++ )
                {
                    Coord[CharNo * 2 + 0].x= (CharNo - Shift) * size.x;
                    Coord[CharNo * 2 + 0].y= TopY;

                    Coord[CharNo * 2 + 1].x= Coord[CharNo * 2 + 0].x;
                    Coord[CharNo * 2 + 1].y= BottomY;
                }

                coord_changed= Coord;

            }



            if(haveNewText)
            {
                var CoordIdx= new MFInt32;
                CoordIdx.length= text.length * 5;

                // write only the left two edges of each letter to Coord. (The right ones are the left ones of the next character, of course)
                for(var CharNo= 0; CharNo<text.length; CharNo++ )
                {
                    // Also create a face for each letter.
                    CoordIdx[CharNo * 5 + 0]= CharNo * 2 + 0;
                    CoordIdx[CharNo * 5 + 1]= CharNo * 2 + 1;
                    CoordIdx[CharNo * 5 + 2]= CharNo * 2 + 3;
                    CoordIdx[CharNo * 5 + 3]= CharNo * 2 + 2;
                    CoordIdx[CharNo * 5 + 4]= -1;
                }

                coordIdx_changed= CoordIdx;

                // Now do the texture coords:
                var Coord= new MFVec2f;
                Coord.length= text.length * 4;

                // We reuse CoordIdx, because it has already the correct length
                // and because it already has the -1 values at the proper positions.
                
                for(var CharNo= 0; CharNo<text.length; CharNo++ )
                {
                    var asc= ascii(text.charAt(CharNo));
                    var TopLeft= new SFVec2f(                ((asc - firstChar) % numCharsHorz) / numCharsHorz
                                            , 1 - (Math.floor((asc - firstChar) / numCharsHorz) / numCharsVert)
                                            );

                    // Top Left
                    Coord[CharNo * 4 + 0].x= TopLeft.x;
                    Coord[CharNo * 4 + 0].y= TopLeft.y;

                    // Bottom Left
                    Coord[CharNo * 4 + 1].x= TopLeft.x;
                    Coord[CharNo * 4 + 1].y= TopLeft.y - 1/numCharsVert;

                    // Top Right
                    Coord[CharNo * 4 + 2].x= TopLeft.x + 1/numCharsHorz;
                    Coord[CharNo * 4 + 2].y= TopLeft.y;

                    // Bottom Right
                    Coord[CharNo * 4 + 3].x= TopLeft.x + 1/numCharsHorz;
                    Coord[CharNo * 4 + 3].y= TopLeft.y - 1/numCharsVert;


                    CoordIdx[CharNo * 5 + 0]= CharNo * 4 + 0;
                    CoordIdx[CharNo * 5 + 1]= CharNo * 4 + 1;
                    CoordIdx[CharNo * 5 + 2]= CharNo * 4 + 3;
                    CoordIdx[CharNo * 5 + 3]= CharNo * 4 + 2;
                }

                texCoord_changed= Coord;
                textCoordIdx_changed= CoordIdx;
            }


        }



        function initialize()
        {
            IsCosmo=   Browser.getName() == 'CosmoPlayer'      // TBD: adjust this string to what Cosmo Player returns.
                    || Browser.getName() == 'NexternetPlayer'
                    ;

            PixelPerCharHorz= imageWidth / numCharsHorz;
            PixelPerCharVert= imageHeight / numCharsVert;

            text=   effs.text;
            size=   effs.size;
            allign= effs.allign == 'LEFT'?    cAllignLeft   :(
                    effs.allign == 'CENTER'?  cAllignCenter :(
                    effs.allign == 'RIGHT'?   cAllignRight  :   cAllignLeft ));

	
			
			// This is a workaround for old Contact versions:
			// EXTERNPROTO initialization parameters seam to not work correctly.
			if(!size.x && !size.y)
				size= new SFVec2f(.7, 1);




            oldSize=   size;
            oldAllign= allign;

            haveNewText=   true;
            haveNewSize=   true;
            haveNewAllign= true;
            Update();

        }

        function set_text(t)
        {
            text= t;
            haveNewText= true;

        }


        function set_size(s)
        {
            size= s;
            haveNewSize= true;
        }
        

        function set_allign(a)
        {
            allign= a == 'LEFT'?    cAllignLeft   :(
                    a == 'CENTER'?  cAllignCenter :(
                    a == 'RIGHT'?   cAllignRight  :   cAllignLeft ));

            haveNewAllign= true;

        }



        function eventsProcessed()
        {
            Update();
        }


        "


            # ... and since I don't know of a function that does the reverse,
            #     we have to keep a table for that.  Hope it works. (and Hope no text editor mangles this literal.)
        field MFString ascii2Char 
        [   
            "                "
            "                "
            " !\"#$%&'()*+,-./"
            "0123456789:;<=>?"
            "@ABCDEFGHIJKLMNO"
            "PQRSTUVWXYZ[\]^_"
            "`abcdefghijklmno"
            "pqrstuvwxyz{|}~"
            ""
            ""
            ""
            ""
            ""
            ""
            ""
            ""
        ]


    }

    ROUTE EFFS.text TO Worker.set_text
    ROUTE EFFS.size TO Worker.set_size
    ROUTE EFFS.allign TO Worker.set_allign

    ROUTE Worker.coord_changed TO Coord.point
    ROUTE Worker.coordIdx_changed TO IFS.set_coordIndex
    ROUTE Worker.texCoord_changed TO TexCoord.point
    ROUTE Worker.textCoordIdx_changed TO IFS.set_texCoordIndex
#    ROUTE Worker.solid_changed TO IFS.solid



	DEF	LastNode Script
	{
		eventOut SFBool	isLoaded IS	isLoaded 

		url	"vrmlscript:

		function initialize()
		{
			isLoaded= true;
		}		


		"
	}
}


Shape
{
    appearance Appearance {
        material Material {
            diffuseColor .55 .09 .05
            specularColor .29 .31 .05
            emissiveColor .21 .03 .02
            ambientIntensity .0267
            shininess .19
        }

        texture ImageTexture
        {
            url "OCR-1.5.png"
        }
    }

    geometry TextureTextLine
    {
        text "Hellow Orld!"
    }
}


Shape
{
    appearance Appearance {
        material Material {
            diffuseColor .02 .24 .53
            specularColor .32 .4 .4
            emissiveColor .01 .12 .27
            ambientIntensity .0333
            shininess .54
        }
    }

    geometry Sphere
    {
        radius .1 
    }
}


NavigationInfo 
{
    type "EXAMINE"
}


__.-.__
end of document