Projected Textures

I wanted to learn how to place a ring under a selected object. My search led me to Projected Textures. I read the manual page on the subject and tried to copy and paste the sample and play with it, which didn’t work out so well. After reading the entire Texture section of the manual and copying and pasting and playing around I think I have something. I’ve included the code below so other’s new to this can learn more about the subject and the affects of changing some of the “projector” values.

#Learning about Projected Texturing, Terrain Decals
#Author:  brianinsuwon, brianinsuwon@yahoo.com, July 1, 2008

import direct.directbase.DirectStart
from direct.gui.OnscreenText import OnscreenText
from direct.actor.Actor import Actor
from direct.task.Task import Task
from direct.showbase.DirectObject import DirectObject
import random, sys, os, math
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *


class World(DirectObject):
                  
                        
    def __init__(self):
        
        #add screen instructions and output
        self.title = OnscreenText(text = "Learning about Projected Textures", 
                         style = 1, fg = (1,1,1,0.8), pos = (-1.2,0.9), 
                         align = TextNode.ALeft,  scale = .08) 
        self.inst1 = OnscreenText(text = "    Keys A,S,D: increases H,P,R values", 
                         style = 1, fg = (1,1,1,0.8), pos = (-1.2,0.8), 
                         align = TextNode.ALeft,  scale = .07) 
        self.inst2 = OnscreenText(text = "    Keys Z,X,C: decreases H,P,R values", 
                         style = 1, fg = (1,1,1,0.8), pos = (-1.2,0.7), 
                         align = TextNode.ALeft,  scale = .07) 
        self.inst3 = OnscreenText(text = "    Keys Q,W: increase,decrease Z value", 
                         style = 1, fg = (1,1,1,0.8), pos = (-1.2,0.6), 
                         align = TextNode.ALeft,  scale = .07) 
        self.inst4 = OnscreenText(text = "    Keys E,R: increase,decrease X value", 
                         style = 1, fg = (1,1,1,0.8), pos = (-1.2,0.5), 
                         align = TextNode.ALeft,  scale = .07) 
        self.inst5 = OnscreenText(text = "    Keys N,M: increase,decrease mapScale", 
                         style = 1, fg = (1,1,1,0.8), pos = (-1.2,0.4), 
                         align = TextNode.ALeft,  scale = .07) 
        self.inst6 = OnscreenText(text = "    Keys J,K: increase,decrease texScale", 
                         style = 1, fg = (1,1,1,0.8), pos = (-1.2,0.3), 
                         align = TextNode.ALeft,  scale = .07) 
        self.output1 = OnscreenText(text = " ", 
                         style = 1, fg = (1,1,1,0.8), pos = (-1.2,0.2), 
                         align = TextNode.ALeft,  scale = .07, mayChange=1) 
        self.output2 = OnscreenText(text = " ", 
                         style = 1, fg = (1,1,1,0.8), pos = (-1.2,0.1), 
                         align = TextNode.ALeft,  scale = .07, mayChange=1)
        self.output3 = OnscreenText(text = " ", 
                         style = 1, fg = (1,1,1,0.8), pos = (-1.2,0.0), 
                         align = TextNode.ALeft,  scale = .07, mayChange=1)
        
        #setup initial values
        self.mapScale =1
        self.texScaleU=1
        self.texScaleV=1
                
        #set the camera
        base.oobe()       
        base.disableMouse()
        base.camera.reparentTo(render)
        base.camera.setPos(0,0,1)

        #set up lights
        self.alight = AmbientLight('alight')
        self.alight.setColor(VBase4(1, 1, 1, 1))
        self.alnp = render.attachNewNode(self.alight)
        render.setLight(self.alnp)
        
        #set up my floor
            #floor was created in Blender using a subdivided plane
            #texture was applied in Blender
        self.floor = loader.loadModel('models/greenFloor2.egg')
        self.floor.reparentTo(render)
        self.floor.setPos(0,0,0)
        self.floor.setScale(self.mapScale)
        
        #set up my decal texture
            #decal was maade in gimp, using a transparent background
        self.tex = loader.loadTexture('textures/ring.png')
        self.ts = TextureStage('ts')
        self.ts.setMode(TextureStage.MDecal)
            #needed the lines below to get only 1 ring,without this, floor is covered in rings
        self.tex.setWrapU(Texture.WMBorderColor)
        self.tex.setWrapV(Texture.WMBorderColor)
        self.tex.setBorderColor(VBase4(1,1, 1, 0)) #needed to set my alpha to zero
        
        self.floor.setTexScale(self.ts, self.texScaleU, self.texScaleV)
 
        #setup the projector
        self.proj = render.attachNewNode(LensNode('proj'))
        self.lens = PerspectiveLens()
        self.proj.node().setLens(self.lens)
        self.proj.reparentTo(render)
        self.proj.setPos(0, 0, 10)
        self.proj.setHpr(0, 90, 0)
    
        self.floor.projectTexture(self.ts, self.tex, self.proj)


        #setup keyboard controls
        self.accept("escape", sys.exit)
        
        self.accept("a", self.hupF)
        self.accept("s", self.pupF)
        self.accept("d", self.rupF)
        
        self.accept("z", self.hdownF)
        self.accept("x", self.pdownF)
        self.accept("c", self.rdownF)
        
        
        self.accept("q", self.zupF)
        self.accept("w", self.zdownF)
        self.accept("e", self.xupF)
        self.accept("r", self.xdownF)
        
        self.accept("n", self.mapScaleupF)
        self.accept("m", self.mapScaledownF)
        self.accept("j", self.texScaleupF)
        self.accept("k", self.texScaledownF)
    

        
    def zupF (self):
        self.proj.setZ(self.proj.getZ()+5)
        self.updateF()
    def zdownF (self):
        self.proj.setZ(self.proj.getZ()-5)
        self.updateF()
    def xupF (self):
        self.proj.setX(self.proj.getX()+5)
        self.updateF()
    def xdownF (self):
        self.proj.setX(self.proj.getX()-5)
        self.updateF()
        
    def hupF (self):
        self.proj.setH(self.proj.getH()+5)
        self.updateF()
    def pupF (self):
        self.proj.setP(self.proj.getP()+5)
        self.updateF()
    def rupF (self):
        self.proj.setR(self.proj.getR()+5)
        self.updateF()
    def hdownF (self):
        self.proj.setH(self.proj.getH()-5)
        self.updateF()
    def pdownF (self):
        self.proj.setP(self.proj.getP()-5)
        self.updateF()
    def rdownF (self):
        self.proj.setR(self.proj.getR()-5)
        self.updateF()
        
    def mapScaleupF (self):
        self.mapScale = self.mapScale +1
        self.floor.setScale(self.mapScale)
        self.updateF()
    def mapScaledownF (self):
        self.mapScale = self.mapScale -1
        self.floor.setScale(self.mapScale)
        self.updateF()
        
    def texScaleupF (self):
        self.texScaleU = self.texScaleU +1
        self.texScaleV = self.texScaleV +1
        self.floor.setTexScale(self.ts, self.texScaleU, self.texScaleV)
        self.updateF()
    def texScaledownF (self):
        self.texScaleU = self.texScaleU -1
        self.texScaleV = self.texScaleV -1
        self.floor.setTexScale(self.ts, self.texScaleU, self.texScaleV)
        self.updateF()
 
        
    def updateF(self):
        ot1 = "Projector Position: " +   str(self.proj.getPos())      
        self.output1.setText(ot1)
        ot2 = "Projector Hpr: " +   str(self.proj.getHpr()) 
        self.output2.setText(ot2)
        ot3 = "texture scales U and V = %s , %s" %  (str(self.texScaleU), str(self.texScaleU))
        self.output3.setText(ot3)
      
        
w = World()
run()

Not to break your heart, but projecting textures will only work if the GPU supports multitextures, and you’re not crossing its limit. Have you tried multiple rings ?
discourse.panda3d.org/viewtopic.php?t=3080