def update_normal(self): position = self.object.getPos() orientation = self.object.getQuat() displacement = Vec3(*self.delta_location) dp, dr, dh = [degrees(a) for a in self.delta_rotation] rotation = Vec3(dh, dp, dr) rotation_quat = Quat() rotation_quat.setHpr(rotation) if self.use_local_rotation: orientation = rotation_quat * orientation else: orientation *= rotation_quat if self.use_local_location: position += orientation.xform(displacement) else: position += displacement self.object.setPos(position) self.object.setQuat(orientation)
def drawItem(self, drawResourcesFactories, x, y, tileCenter, collision, seed=True, scale=1.0): v = drawResourcesFactories.values() if len(v) < 1: return tile = v[0].getTile() if seed: random.seed((x, y)) exists = random.random() if exists < 0.9: return quat = Quat() quat.setHpr((random.random() * 360, 0, 0)) height = tile.height(x, y) if height is None: return heightOffset = -0.4 # make sure whole bottom of tree is in ground pos = Vec3(x, y, height + heightOffset) - tileCenter self.drawTree( (pos, quat, 0, list(0 for x in drawResourcesFactories.iterkeys()), 0), drawResourcesFactories, collision, scale=scale, )
def drawItem(self, drawResourcesFactories, x, y, tileCenter, collision, seed=True, scale=1.0): v = drawResourcesFactories.values() if len(v) < 1: return tile = v[0].getTile() if seed: random.seed((x, y)) exists = random.random() if exists < .9: return quat = Quat() quat.setHpr((random.random() * 360, 0, 0)) height = tile.height(x, y) if height is None: return heightOffset = -0.4 # make sure whole bottom of tree is in ground pos = Vec3(x, y, height + heightOffset) - tileCenter self.drawTree( (pos, quat, 0, list( 0 for x in drawResourcesFactories.iterkeys()), 0), drawResourcesFactories, collision, scale=scale)
def __updateParticleParent(self): if not CIGlobals.isNodePathOk(self.waterStreamParent): return time = globalClock.getFrameTime() streamPos = self.waterStreamParent.getPos(render) distance = self.sprayParticleDist if self.isLocal(): camQuat = camera.getQuat(render) pFrom = camera.getPos(render) push = (streamPos - pFrom).length() pFrom += camQuat.xform(Vec3.forward()) * push pTo = pFrom + camQuat.xform( Vec3.forward()) * (self.sprayParticleDist + (pFrom - streamPos).length()) hitPos = Point3(pTo) result = base.physicsWorld.rayTestClosest(pFrom, pTo, CIGlobals.WorldGroup) if result.hasHit(): node = result.getNode() hitPos = result.getHitPos() distance = (hitPos - streamPos).length() if time - self.lastSprayTime >= self.SprayTraceIval and not self.released: if result.hasHit(): self.__doSplat(distance, hitPos) self.getFPSCam().addViewPunch( Vec3(random.uniform(-0.6, 0.6), random.uniform(0.25, 1.0), 0.0)) self.primaryFirePress(True) self.lastSprayTime = time else: pFrom = self.avatar.getPos(render) + self.avatar.getEyePoint() + ( 1, 0, 0) quat = Quat() quat.setHpr( self.avatar.getHpr(render) + (0, self.avatar.lookPitch, 0)) pTo = pFrom + quat.xform( Vec3.forward()) * (self.sprayParticleDist + (pFrom - streamPos).length()) hitPos = Point3(pTo) hit = PhysicsUtils.rayTestClosestNotMe( self.avatar, pFrom, pTo, CIGlobals.WorldGroup | CIGlobals.LocalAvGroup) if hit is not None: hitPos = hit.getHitPos() distance = (hitPos - streamPos).length() self.waterStreamParent.lookAt(render, hitPos) if self.sprayParticle: system = self.sprayParticle.getParticlesNamed('particles-1') # Make the particles die off at the hit point. lifespan = min( 1, distance / self.sprayParticleDist) * self.sprayParticleLife system.factory.setLifespanBase(lifespan)
def _angleRandomAxis(inQuat, angle, maxAngle): q=Quat() angleRange=0.125 nangle = angle + math.pi * (angleRange * random.random() - angleRange/2) #power of 1/2 here makes distrobution even withint a circle # (makes larger bends are more likley as they are further spread) ammount=(random.random()**(1.0/2))*maxAngle q.setHpr((math.sin(nangle)*ammount,math.cos(nangle)*ammount,0)) return inQuat*q
def _angleRandomAxis(quat, angle, maxBend=30): q = Quat() #power of 2 here makes distribution even withint a circle # (makes larger bends are more likley as they are further spread) bendAngle = (random.random()**2) * maxBend #gauss might be more realistic but actually is far from perfect #bendAngle=clamp(random.gauss(0,maxBend*0.5),0,maxBend) q.setHpr((angle, bendAngle, 0)) return q * quat
def _angleRandomAxis(inQuat, angle, maxAngle): q = Quat() angleRange = 0.125 nangle = angle + math.pi * (angleRange * random.random() - angleRange / 2) #power of 1/2 here makes distrobution even withint a circle # (makes larger bends are more likley as they are further spread) ammount = (random.random()**(1.0 / 2)) * maxAngle q.setHpr((math.sin(nangle) * ammount, math.cos(nangle) * ammount, 0)) return inQuat * q
def _randomBend(inQuat, maxAngle=20): q = Quat() angle = random.random() * 2 * math.pi #power of 1/2 here makes distrobution even withint a circle # (makes larger bends are more likley as they are further spread) ammount = (math.sqrt(random.random())) * maxAngle q.setHpr((math.sin(angle) * ammount, math.cos(angle) * ammount, 0)) return inQuat * q
def setView(self, x, y, z, h, p, r): self.viewOrigin = Vec3(x, y, z) self.viewAngles = Vec3(h, p, r) quat = Quat() quat.setHpr(self.viewAngles) self.viewAngleVectors = [ quat.getRight(), quat.getForward(), quat.getUp() ]
def _randomBend(inQuat, maxAngle=20): q=Quat() angle=random.random()*2*math.pi #power of 1/2 here makes distrobution even withint a circle # (makes larger bends are more likley as they are further spread) ammount=(math.sqrt(random.random()))*maxAngle q.setHpr((math.sin(angle)*ammount,math.cos(angle)*ammount,0)) return inQuat*q
def start(self): Gag.start(self) self.hitSfx.play() gag = self.gag if self.isLocal(): vm = self.getViewModel() fpsCam = self.getFPSCam() fpsCam.setVMAnimTrack( Sequence(ActorInterval(vm, "sg_shoot_begin"), ActorInterval(vm, "sg_shoot_end"), Func(vm.loop, "sg_idle"))) gag = self.getVMGag() nozzle = gag.find("**/joint_nozzle") if self.isLocal() and base.localAvatar.battleControls: if base.localAvatar.isFirstPerson(): self.getFPSCam().resetViewPunch() self.getFPSCam().addViewPunch( Vec3(random.uniform(-0.6, 0.6), random.uniform(-0.25, -0.5), 0.0)) startPos = camera.getPos(render) else: startPos = nozzle.getPos(render) hitPos = PhysicsUtils.getHitPosFromCamera() else: startPos = nozzle.getPos(render) quat = Quat() quat.setHpr( self.avatar.getHpr(render) + (0, self.avatar.lookPitch, 0)) hitPos = quat.xform(Vec3.forward() * 10000) hit = PhysicsUtils.rayTestClosestNotMe( self.avatar, startPos, hitPos, CIGlobals.WorldGroup | CIGlobals.LocalAvGroup) if hit is not None: hitPos = hit.getHitPos() pellet = WaterPellet(self.isLocal()) pellet.addToWorld(nozzle.getPos(render), lookAt=hitPos, velo=Vec3.forward() * self.pelletSpeed) if self.isLocal(): base.localAvatar.sendUpdate('usedGag', [self.id])
def makeMuzzleFlash(node, pos, hpr, scale, color=(1, 1, 1, 1)): import random from panda3d.core import Quat, Point3 from src.coginvasion.base.MuzzleParticle import MuzzleParticle quat = Quat() quat.setHpr(hpr) forward = quat.getForward() scale = random.uniform(scale - 0.25, scale + 0.25) #scale = clamp(scale, 0.5, 8.0) for i in xrange(1, 9): offset = Point3(pos) + (forward * (i * (2 / 16.0) * scale)) size = (random.uniform(6 / 16.0, 9 / 16.0) * (12 - (i)) / 9) * scale roll = random.randint(0, 360) dur = 0.035 p = MuzzleParticle(size, size, roll, color, dur) p.reparentTo(node) p.setPos(offset) p.setHpr(hpr)
def getUnitCircle(): global UnitCircle if not UnitCircle: segs = LineSegs('unitCircle') vertices = LEUtils.circle(0, 0, 1, 64) angles = [Vec3(0, 0, 0), Vec3(90, 0, 0), Vec3(0, 90, 0)] for angle in angles: quat = Quat() quat.setHpr(angle) for i in range(len(vertices)): x1, y1 = vertices[i] x2, y2 = vertices[(i + 1) % len(vertices)] pFrom = quat.xform(Vec3(x1, 0, y1)) pTo = quat.xform(Vec3(x2, 0, y2)) segs.moveTo(pFrom) segs.drawTo(pTo) UnitCircle = NodePath(segs.create()) UnitCircle.setAntialias(AntialiasAttrib.MLine) UnitCircle.setLightOff(1) UnitCircle.setFogOff(1) UnitCircle.hide(DirectRender.ShadowCameraBitmask | DirectRender.ReflectionCameraBitmask) return UnitCircle
def get_unit(hpr): q = Quat() q.setHpr(hpr) return q.xform(Vec3(0, 1, 0))
def __updateTask(self, task): # TODO -- This function does a lot of math, I measured it to take .5 ms on my laptop # That's a lot of time for something miniscule like sway and bob. dt = globalClock.getDt() time = globalClock.getFrameTime() if base.localAvatar.isFirstPerson(): eyePoint = base.localAvatar.getEyePoint() if base.localAvatar.walkControls.crouching: eyePoint[2] = eyePoint[2] / 2.0 eyePoint[2] = CIGlobals.lerpWithRatio(eyePoint[2], self.lastEyeHeight, 0.4) self.lastEyeHeight = eyePoint[2] camRootAngles = Vec3(0) # Mouse look around mw = base.mouseWatcherNode if mw.hasMouse(): md = base.win.getPointer(0) center = Point2(base.win.getXSize() / 2, base.win.getYSize() / 2) xDist = md.getX() - center.getX() yDist = md.getY() - center.getY() sens = self.__getMouseSensitivity() angular = -(xDist * sens) / dt base.localAvatar.walkControls.controller.setAngularMovement( angular) camRootAngles.setY(self.lastPitch - yDist * sens) if camRootAngles.getY() > FPSCamera.MaxP: camRootAngles.setY(FPSCamera.MaxP) yDist = 0 elif camRootAngles.getY() < FPSCamera.MinP: yDist = 0 camRootAngles.setY(FPSCamera.MinP) base.win.movePointer(0, int(center.getX()), int(center.getY())) if base.localAvatar.isFirstPerson(): # Camera / viewmodel bobbing vmBob = Point3(0) vmAngles = Vec3(0) vmRaise = Point3(0) camBob = Point3(0) maxSpeed = base.localAvatar.walkControls.BattleRunSpeed * 16.0 speed = base.localAvatar.walkControls.speeds.length() * 16.0 speed = max(-maxSpeed, min(maxSpeed, speed)) bobOffset = CIGlobals.remapVal(speed, 0, maxSpeed, 0.0, 1.0) self.bobTime += (time - self.lastBobTime) * bobOffset self.lastBobTime = time # Calculate the vertical bob cycle = self.bobTime - int( self.bobTime / self.BobCycleMax) * self.BobCycleMax cycle /= self.BobCycleMax if cycle < self.BobUp: cycle = math.pi * cycle / self.BobUp else: cycle = math.pi + math.pi * (cycle - self.BobUp) / (1.0 - self.BobUp) verticalBob = speed * 0.005 verticalBob = verticalBob * 0.3 + verticalBob * 0.7 * math.sin( cycle) verticalBob = max(-7.0, min(4.0, verticalBob)) verticalBob /= 16.0 # Calculate the lateral bob cycle = self.bobTime - int( self.bobTime / self.BobCycleMax * 2) * self.BobCycleMax * 2 cycle /= self.BobCycleMax * 2 if cycle < self.BobUp: cycle = math.pi * cycle / self.BobUp else: cycle = math.pi + math.pi * (cycle - self.BobUp) / (1.0 - self.BobUp) lateralBob = speed * 0.005 lateralBob = lateralBob * 0.3 + lateralBob * 0.7 * math.sin(cycle) lateralBob = max(-7.0, min(4.0, lateralBob)) lateralBob /= 16.0 # Apply bob, but scaled down a bit vmBob.set(lateralBob * 0.8, 0, verticalBob * 0.1) # Z bob a bit more vmBob[2] += verticalBob * 0.1 # Bob the angles vmAngles[2] += verticalBob * 0.5 vmAngles[1] -= verticalBob * 0.4 vmAngles[0] -= lateralBob * 0.3 # ================================================================ # Viewmodel lag/sway angles = self.camRoot.getHpr(render) quat = Quat() quat.setHpr(angles) invQuat = Quat() invQuat.invertFrom(quat) maxVMLag = 1.5 lagforward = quat.getForward() if dt != 0.0: lagdifference = lagforward - self.lastFacing lagspeed = 5.0 lagdiff = lagdifference.length() if (lagdiff > maxVMLag) and (maxVMLag > 0.0): lagscale = lagdiff / maxVMLag lagspeed *= lagscale self.lastFacing = CIGlobals.extrude(self.lastFacing, lagspeed * dt, lagdifference) self.lastFacing.normalize() lfLocal = invQuat.xform(lagdifference) vmBob = CIGlobals.extrude(vmBob, 5.0 / 16.0, lfLocal * -1.0) pitch = angles[1] if pitch > 180: pitch -= 360 elif pitch < -180: pitch += 360 vmBob = CIGlobals.extrude(vmBob, pitch * (0.035 / 16), Vec3.forward()) vmBob = CIGlobals.extrude(vmBob, pitch * (0.03 / 16), Vec3.right()) vmBob = CIGlobals.extrude(vmBob, pitch * (0.02 / 16), Vec3.up()) # ================================================================ vmRaise.set( 0, 0, 0 ) #(0, abs(camRootAngles.getY()) * -0.002, camRootAngles.getY() * 0.002) camBob.set(0, 0, 0) # Apply bob, raise, and sway to the viewmodel. self.viewModel.setPos(vmBob + vmRaise + self.lastVMPos) self.vmRoot2.setHpr(vmAngles) self.camRoot.setPos(eyePoint + camBob) newPitch = camRootAngles.getY() if abs(newPitch - self.lastPitch) > self.PitchUpdateEpsilon: # Broadcast where our head is looking head = base.localAvatar.getPart("head") if head and not head.isEmpty(): # Constrain the head pitch a little bit so it doesn't look like their head snapped headPitch = max(-47, newPitch) headPitch = min(75, headPitch) base.localAvatar.b_setLookPitch(headPitch) self.lastPitch = newPitch if base.localAvatar.isFirstPerson(): # Apply punch angle self.decayPunchAngle() camRootAngles += self.punchAngle self.camRoot.setHpr(camRootAngles) return task.cont
def getUpHPR(hpr): q = Quat() q.setHpr(VBase3(math.degrees(hpr.h), math.degrees(hpr.p), math.degrees(hpr.r))) v = q.getUp() return SP3(v.x, v.y, v.z)
def invRotate(self, point): quat = Quat() quat.setHpr(self.getViewHpr()) return LEUtils.makeForwardAxis(point, quat)
def getViewMatrix(self): quat = Quat() quat.setHpr(self.getViewHpr()) mat = Mat4() quat.extractToMatrix(mat) return mat
def cameraLerp(self, i): pos, hpr = cameraLerps[i] quat = Quat() quat.setHpr(hpr) camera.posQuatInterval(1.2, pos, quat).start()
def getViewQuat(self): quat = Quat() quat.setHpr(self.getViewHpr())
def drawTree(self, base, drawResourcesFactories, collision, scale=1.0): age = random.random()**3.5 to = 12 * age if to < 3: return leafScaler = age**.5 leafSize = 10.0 * self.scalar * leafScaler * scale maxbend = 40 + random.random() * 20 forks = int(to / 2 - 1) lengthList = [] numCopiesList = [] radiusList = [] currR = age * 1.0 * (random.random() * 2 + 1) forkCount = 0 lengthScale = 2.0 * scale for i in xrange(forks + 1): currR *= 1 / math.sqrt(2) endR = currR * .9 * .9 if i == forks: endR = 0 forkCount = 0 if i < 2: lengthList.extend([lengthScale, lengthScale, lengthScale]) numCopiesList.extend([forkCount, 0, 0]) radiusList.extend([currR, currR * .9, endR]) else: lengthList.extend([lengthScale * 3]) numCopiesList.extend([forkCount]) radiusList.extend([endR]) forkCount = 2 + (i % 2) doLeaves = True dotCount = 1 stack = [base] LODs = list(drawResourcesFactories.keys()) angleDatas = [] for LODnum, LOD in enumerate(LODs): drawResourcesFactory = drawResourcesFactories[LOD] if LOD == self.minLOD: numVertices = 2 elif LOD == self.lowLOD: numVertices = 3 elif LOD == self.midLOD: numVertices = 4 else: numVertices = 6 #cache some info needed for placeing the vertexes angleData = [] if self.barkTexture: vNum = numVertices + 1 else: vNum = numVertices for i in xrange(vNum): #doubles the last vertex to fix UV seam angle = -2 * i * math.pi / numVertices angleData.append( (math.cos(angle), math.sin(angle), 1.0 * i / numVertices)) angleDatas.append(angleData) bottom = True if collision: cNode = CollisionNode('cnode') cnodePath = NodePath(cNode) cnodePath.reparentTo(collision) cnodePath.setCollideMask(collisionUtil.groundMask) #cnodePath.show() while stack: pos, quat, depth, previousRows, sCoord = stack.pop() length = lengthList[depth] sCoord += length / 4.0 radius = radiusList[depth] perp1 = quat.getRight() perp2 = quat.getForward() startRows = [] for LODnum, LOD in enumerate(LODs): drawResourcesFactory = drawResourcesFactories[LOD] previousRow = previousRows[LODnum] angleData = angleDatas[LODnum] vNum = len(angleData) if LOD == self.minLOD: cutoffRadius = .7 elif LOD == self.lowLOD: cutoffRadius = .5 elif LOD == self.midLOD: cutoffRadius = .1 else: cutoffRadius = -1 trunkResources = drawResourcesFactory.getDrawResources( self.trunkDataIndex[LOD]) lines = trunkResources.getGeomTristrips() vertWriter = trunkResources.getWriter("vertex") normalWriter = trunkResources.getWriter("normal") if self.barkTexture: texWriter = trunkResources.getWriter("texcoord") # else: # colorWriter = trunkResources.getWriter("color") startRow = vertWriter.getWriteRow() startRows.append(startRow) if radius > cutoffRadius: #this draws the body of the tree. This draws a ring of vertices and connects the rings with #triangles to form the body. #vertex information is written here for cos, sin, tex in angleData: adjCircle = pos + (perp1 * cos + perp2 * sin) * radius * self.scalar normal = perp1 * cos + perp2 * sin normalWriter.addData3f(normal) vertWriter.addData3f(adjCircle) if self.barkTexture is not None: texWriter.addData2f(tex, sCoord) # else: # colorWriter.addData4f(.4,.3,.3,1) #we cant draw quads directly so we use Tristrips if not bottom: for i in xrange(vNum): lines.addVertices(i + previousRow, i + startRow) if not self.barkTexture: lines.addVertices(previousRow, startRow) lines.closePrimitive() bottom = False if depth + 1 < len(lengthList): #move foward along the correct axis newPos = pos + quat.getUp() * length * self.scalar # if makeColl: # self.makeColl(pos, newPos, radiusList[depth]) numCopies = numCopiesList[depth] if numCopies: angleOffset = random.random() * 2 * math.pi for i in xrange(numCopies): newQuat = _angleRandomAxis( quat, 2 * math.pi * i / numCopies + angleOffset, maxbend) newPos2 = pos + newQuat.getUp() * length * self.scalar stack.append( (newPos2, newQuat, depth + 1, startRows, sCoord)) if collision: tube = CollisionTube(Point3(pos), Point3(newPos2), radius) cNode.addSolid(tube) else: #just make another branch connected to this one with a small variation in direction stack.append((newPos, _randomBend(quat, 20), depth + 1, startRows, sCoord)) if collision: tube = CollisionTube(Point3(pos), Point3(newPos), radius) cNode.addSolid(tube) elif doLeaves: q = Quat() q.setHpr((random.random() * 2 * math.pi, 0, 0)) quat = quat * q up = quat.getUp() down = -up # size s = leafSize dir1 = perp1 * s dir2 = perp2 * s bend = -up * (s / 4.0) v0 = pos + dir1 v1 = pos + dir2 + bend v2 = pos - dir1 v3 = pos - dir2 + bend norm1 = dir1.cross(dir2 + bend) norm1.normalize() norm2 = dir1.cross(dir2 - bend) norm2.normalize() for LOD, drawResourcesFactory in drawResourcesFactories.iteritems( ): leafResources = drawResourcesFactory.getDrawResources( self.leafDataIndex[LOD]) leafTri = leafResources.getGeomTriangles() n1 = norm1 n2 = norm2 upVec = up leafVertexWriter = leafResources.getWriter("vertex") leafNormalWriter = leafResources.getWriter("normal") if self.leafTexture: leafTexcoordWriter = leafResources.getWriter( "texcoord") else: leafColorWriter = leafResources.getWriter("color") if self.doTangentsAndBinormals: leafTangentWriter = leafResources.getWriter("tangent") leafBinormalWriter = leafResources.getWriter( "binormal") for x in range(2): leafRow = leafVertexWriter.getWriteRow() leafVertexWriter.addData3f(v0) leafVertexWriter.addData3f(v1) leafVertexWriter.addData3f(v2) leafVertexWriter.addData3f(v3) if self.leafTexture is not None: n = dotCount leafTexcoordWriter.addData2f(0, 0) leafTexcoordWriter.addData2f(0, n) leafTexcoordWriter.addData2f(n, n) leafTexcoordWriter.addData2f(n, 0) else: leafColorWriter.addData4f(.5, .4, .0, 1) leafColorWriter.addData4f(.0, .4, .0, 1) leafColorWriter.addData4f(.5, .4, .0, 1) leafColorWriter.addData4f(.0, .4, .0, 1) if x == 1: # back sides upVec = -up n1 = -norm1 n2 = -norm2 leafTri.addVertices(leafRow + 1, leafRow, leafRow + 2) leafTri.addVertices(leafRow + 2, leafRow, leafRow + 3) else: leafTri.addVertices(leafRow, leafRow + 1, leafRow + 2) leafTri.addVertices(leafRow, leafRow + 2, leafRow + 3) leafNormalWriter.addData3f(upVec) leafNormalWriter.addData3f(n1) leafNormalWriter.addData3f(upVec) leafNormalWriter.addData3f(n2) if self.doTangentsAndBinormals: # TODO : This is just a random guess. Make it actually correct tangent = norm1.cross(dir1 + dir2) tangent.normalize() binormalCenter = upVec.cross(tangent) binormal1 = n1.cross(tangent) binormal2 = n2.cross(tangent) leafTangentWriter.addData3f(tangent) leafTangentWriter.addData3f(tangent) leafTangentWriter.addData3f(tangent) leafTangentWriter.addData3f(tangent) leafBinormalWriter.addData3f(binormalCenter) leafBinormalWriter.addData3f(binormal1) leafBinormalWriter.addData3f(binormalCenter) leafBinormalWriter.addData3f(binormal2)
def drawFern(self,LOD,pos,quat,drawResourcesFactory,scale=1.0): scalar=random.random() scale*=scalar if scale<.3: return count=int((scalar**.7)*12) if scale<.8: if LOD==self.lowLOD: return else: if LOD==self.midLOD: return leafResources=drawResourcesFactory.getDrawResources(self.leafDataIndex[LOD]) leafTri=leafResources.getGeomTriangles() vertexWriter=leafResources.getWriter("vertex") normalWriter=leafResources.getWriter("normal") if self.leafTexture: texcoordWriter = leafResources.getWriter("texcoord") scale*=self.scalar*3 q2=Quat() q3=Quat() for i in xrange(count): p=(random.random()**2)*60+20 h=random.random()*360 q2.setHpr((h,p,0)) q3.setHpr((h,p-20-p/4,0)) length1=scale*4 length2=scale*3 f=q2.getForward()*length1 r=q2.getRight()*scale*.5 f2=q3.getForward()*length2+f norm0=q2.getUp() norm2=q3.getUp() norm1=norm0+norm2 norm1.normalize() for x in range(2): leafRow = vertexWriter.getWriteRow() vertexWriter.addData3f(pos) vertexWriter.addData3f(pos+f+r) vertexWriter.addData3f(pos+f-r) vertexWriter.addData3f(pos+f2) if self.leafTexture: texcoordWriter.addData2f(0,0) texcoordWriter.addData2f(0,1) texcoordWriter.addData2f(1,0) texcoordWriter.addData2f(1,1) if x==1: # back sides norm0=-norm0 norm1=-norm1 norm2=-norm2 leafTri.addVertices(leafRow+1,leafRow,leafRow+2) leafTri.addVertices(leafRow+3,leafRow+1,leafRow+2) else: leafTri.addVertices(leafRow,leafRow+1,leafRow+2) leafTri.addVertices(leafRow+1,leafRow+3,leafRow+2) normalWriter.addData3f(norm0) normalWriter.addData3f(norm1) normalWriter.addData3f(norm1) normalWriter.addData3f(norm2)
def drawTree(self,base,drawResourcesFactories,collision,scale=1.0): age=random.random()**3.5 to = 12*age if to<3: return leafScaler=age**.5 leafSize=10.0*self.scalar*leafScaler*scale maxbend=40+random.random()*20 forks=int(to/2-1) lengthList=[] numCopiesList=[] radiusList=[] currR=age*1.0*(random.random()*2+1) forkCount=0 lengthScale=2.0*scale for i in xrange(forks+1): currR*=1/math.sqrt(2) endR=currR*.9*.9 if i==forks: endR=0 forkCount=0 if i<2: lengthList.extend([lengthScale,lengthScale,lengthScale]) numCopiesList.extend([forkCount,0,0]) radiusList.extend([currR,currR*.9,endR]) else: lengthList.extend([lengthScale*3]) numCopiesList.extend([forkCount]) radiusList.extend([endR]) forkCount=2+(i%2) doLeaves=True dotCount=1 stack = [base] LODs=list(drawResourcesFactories.keys()) angleDatas=[] for LODnum,LOD in enumerate(LODs): drawResourcesFactory=drawResourcesFactories[LOD] if LOD==self.minLOD: numVertices=2 elif LOD==self.lowLOD: numVertices=3 elif LOD==self.midLOD: numVertices=4 else: numVertices=6 #cache some info needed for placeing the vertexes angleData=[] if self.barkTexture: vNum=numVertices+1 else: vNum=numVertices for i in xrange(vNum): #doubles the last vertex to fix UV seam angle=-2 * i * math.pi / numVertices angleData.append((math.cos(angle),math.sin(angle),1.0*i / numVertices)) angleDatas.append(angleData) bottom=True if collision: cNode=CollisionNode('cnode') cnodePath = NodePath(cNode) cnodePath.reparentTo(collision) cnodePath.setCollideMask(collisionUtil.groundMask) #cnodePath.show() while stack: pos, quat, depth, previousRows, sCoord = stack.pop() length = lengthList[depth] sCoord += length/4.0 radius=radiusList[depth] perp1 = quat.getRight() perp2 = quat.getForward() startRows=[] for LODnum,LOD in enumerate(LODs): drawResourcesFactory=drawResourcesFactories[LOD] previousRow=previousRows[LODnum] angleData=angleDatas[LODnum] vNum=len(angleData) if LOD==self.minLOD: cutoffRadius=.7 elif LOD==self.lowLOD: cutoffRadius=.5 elif LOD==self.midLOD: cutoffRadius=.1 else: cutoffRadius=-1 trunkResources=drawResourcesFactory.getDrawResources(self.trunkDataIndex[LOD]) lines = trunkResources.getGeomTristrips() vertWriter = trunkResources.getWriter("vertex") normalWriter = trunkResources.getWriter("normal") if self.barkTexture: texWriter = trunkResources.getWriter("texcoord") # else: # colorWriter = trunkResources.getWriter("color") startRow = vertWriter.getWriteRow() startRows.append(startRow) if radius>cutoffRadius: #this draws the body of the tree. This draws a ring of vertices and connects the rings with #triangles to form the body. #vertex information is written here for cos,sin,tex in angleData: adjCircle = pos + (perp1 * cos + perp2 * sin) * radius * self.scalar normal = perp1 * cos + perp2 * sin normalWriter.addData3f(normal) vertWriter.addData3f(adjCircle) if self.barkTexture is not None: texWriter.addData2f(tex,sCoord) # else: # colorWriter.addData4f(.4,.3,.3,1) #we cant draw quads directly so we use Tristrips if not bottom: for i in xrange(vNum): lines.addVertices(i + previousRow,i + startRow) if not self.barkTexture: lines.addVertices(previousRow,startRow) lines.closePrimitive() bottom=False if depth + 1 < len(lengthList): #move foward along the correct axis newPos = pos + quat.getUp() * length * self.scalar # if makeColl: # self.makeColl(pos, newPos, radiusList[depth]) numCopies = numCopiesList[depth] if numCopies: angleOffset=random.random()*2*math.pi for i in xrange(numCopies): newQuat= _angleRandomAxis(quat, 2 * math.pi * i / numCopies+angleOffset, maxbend) newPos2=pos + newQuat.getUp() * length * self.scalar stack.append((newPos2,newQuat, depth + 1, startRows, sCoord)) if collision: tube = CollisionTube(Point3(pos),Point3(newPos2),radius) cNode.addSolid(tube) else: #just make another branch connected to this one with a small variation in direction stack.append((newPos, _randomBend(quat, 20), depth + 1, startRows, sCoord)) if collision: tube = CollisionTube(Point3(pos),Point3(newPos),radius) cNode.addSolid(tube) elif doLeaves: q=Quat() q.setHpr((random.random()*2*math.pi,0,0)) quat=quat*q up=quat.getUp() down=-up # size s=leafSize dir1=perp1*s dir2=perp2*s bend=-up*(s/4.0) v0=pos+dir1 v1=pos+dir2+bend v2=pos-dir1 v3=pos-dir2+bend norm1=dir1.cross(dir2+bend) norm1.normalize() norm2=dir1.cross(dir2-bend) norm2.normalize() for LOD,drawResourcesFactory in drawResourcesFactories.iteritems(): leafResources=drawResourcesFactory.getDrawResources(self.leafDataIndex[LOD]) leafTri=leafResources.getGeomTriangles() n1=norm1 n2=norm2 upVec=up leafVertexWriter=leafResources.getWriter("vertex") leafNormalWriter=leafResources.getWriter("normal") if self.leafTexture: leafTexcoordWriter = leafResources.getWriter("texcoord") else: leafColorWriter = leafResources.getWriter("color") for x in range(2): leafRow = leafVertexWriter.getWriteRow() leafVertexWriter.addData3f(v0) leafVertexWriter.addData3f(v1) leafVertexWriter.addData3f(v2) leafVertexWriter.addData3f(v3) if self.leafTexture is not None: n=dotCount leafTexcoordWriter.addData2f(0,0) leafTexcoordWriter.addData2f(0,n) leafTexcoordWriter.addData2f(n,n) leafTexcoordWriter.addData2f(n,0) else: leafColorWriter.addData4f(.5,.4,.0,1) leafColorWriter.addData4f(.0,.4,.0,1) leafColorWriter.addData4f(.5,.4,.0,1) leafColorWriter.addData4f(.0,.4,.0,1) if x==1: # back sides upVec=-up n1=-norm1 n2=-norm2 leafTri.addVertices(leafRow+1,leafRow,leafRow+2) leafTri.addVertices(leafRow+2,leafRow,leafRow+3) else: leafTri.addVertices(leafRow,leafRow+1,leafRow+2) leafTri.addVertices(leafRow,leafRow+2,leafRow+3) leafNormalWriter.addData3f(upVec) leafNormalWriter.addData3f(n1) leafNormalWriter.addData3f(upVec) leafNormalWriter.addData3f(n2)
def release(self): Gag.release(self) base.audio3d.attachSoundToObject(self.woosh, self.gag) base.playSfx(self.woosh, node=self.gag) if self.isLocal() and base.localAvatar.battleControls: if base.localAvatar.isFirstPerson(): # Add a small kick to the camera to give more feedback self.getFPSCam().addViewPunch( Vec3(random.uniform(.5, 1), random.uniform(-.5, -1), 0)) startPos = camera.getPos(render) + camera.getQuat( render).xform(Vec3.right()) push = 0.0 else: startPos = self.handJoint.getPos(render) push = (startPos - camera.getPos(render)).length() hitPos = PhysicsUtils.getHitPosFromCamera() else: startPos = self.handJoint.getPos(render) quat = Quat() quat.setHpr( self.avatar.getHpr(render) + (0, self.avatar.lookPitch, 0)) hitPos = quat.xform(Vec3.forward() * self.power) hit = PhysicsUtils.rayTestClosestNotMe( self.avatar, startPos, hitPos, CIGlobals.WorldGroup | CIGlobals.LocalAvGroup) if hit is not None: hitPos = hit.getHitPos() throwDir = (hitPos - startPos).normalized() endPos = startPos + (throwDir * self.power) - (0, 0, 90) entity = self.gag if not entity: entity = self.build() gagRoot = render.attachNewNode('gagRoot') gagRoot.setPos(startPos) entity.reparentTo(render) entity.setPos(0, 0, 0) entity.headsUp(throwDir) rot = entity.getHpr(render) entity.reparentTo(gagRoot) entity.setHpr(rot[0], -90, 0) self.gag = None if not self.handJoint: self.handJoint = self.avatar.find('**/def_joint_right_hold') track = FlightProjectileInterval(gagRoot, startPos=startPos, endPos=endPos, gravityMult=1.07, duration=2.5) event = self.avatar.uniqueName('throwIvalDone') + '-' + str( hash(entity)) track.setDoneEvent(event) base.acceptOnce(event, self.__handlePieIvalDone, [entity]) track.start() if self.isLocal(): collider = self.buildCollisions(entity) self.entities.append([gagRoot, track, collider]) base.localAvatar.sendUpdate('usedGag', [self.id]) else: self.entities.append([gagRoot, track, NodePath()]) self.reset()
def rotate(self, point): quat = Quat() quat.setHpr(self.getViewHpr()) return quat.xform(point)
def __updateParticleParent(self, task=None): time = globalClock.getFrameTime() streamPos = self.waterStreamParent.getPos(render) distance = self.sprayParticleDist if self.isLocal(): if base.localAvatar.backpack.getSupply(self.id) <= 0: base.localAvatar.b_gagThrow(self.id) return task.done camQuat = camera.getQuat(render) pFrom = camera.getPos(render) push = (streamPos - pFrom).length() pFrom += camQuat.xform(Vec3.forward()) * push pTo = pFrom + camQuat.xform( Vec3.forward()) * (self.sprayParticleDist + (pFrom - streamPos).length()) hitPos = Point3(pTo) result = base.physicsWorld.rayTestClosest(pFrom, pTo, CIGlobals.WorldGroup) if result.hasHit(): node = result.getNode() hitPos = result.getHitPos() distance = (hitPos - streamPos).length() if time - self.lastDmgTime >= self.dmgIval: self._handleSprayCollision(NodePath(node), hitPos, distance) self.lastDmgTime = time if time - self.lastSprayTime >= self.dmgIval: self.getFPSCam().addViewPunch( Vec3(random.uniform(-0.6, 0.6), random.uniform(0.25, 1.0), 0.0)) base.localAvatar.sendUpdate('usedGag', [self.id]) self.lastSprayTime = time else: pFrom = self.avatar.getPos(render) + self.avatar.getEyePoint() + ( 1, 0, 0) quat = Quat() quat.setHpr( self.avatar.getHpr(render) + (0, self.avatar.lookPitch, 0)) pTo = pFrom + quat.xform( Vec3.forward()) * (self.sprayParticleDist + (pFrom - streamPos).length()) hitPos = Point3(pTo) hit = PhysicsUtils.rayTestClosestNotMe( self.avatar, pFrom, pTo, CIGlobals.WorldGroup | CIGlobals.LocalAvGroup) if hit is not None: hitPos = hit.getHitPos() distance = (hitPos - streamPos).length() self.waterStreamParent.lookAt(render, hitPos) if self.sprayParticle: system = self.sprayParticle.getParticlesNamed('particles-1') # Make the particles die off at the hit point. lifespan = min( 1, distance / self.sprayParticleDist) * self.sprayParticleLife system.factory.setLifespanBase(lifespan) if task: return task.cont
def drawFern(self, LOD, pos, quat, drawResourcesFactory, scale=1.0): scalar = random.random() scale *= scalar if scale < .3: return count = int((scalar**.7) * 12) if scale < .8: if LOD == self.lowLOD: return else: if LOD == self.midLOD: return leafResources = drawResourcesFactory.getDrawResources( self.leafDataIndex[LOD]) leafTri = leafResources.getGeomTriangles() vertexWriter = leafResources.getWriter("vertex") normalWriter = leafResources.getWriter("normal") if self.leafTexture: texcoordWriter = leafResources.getWriter("texcoord") scale *= self.scalar * 3 q2 = Quat() q3 = Quat() for i in xrange(count): p = (random.random()**2) * 60 + 20 h = random.random() * 360 q2.setHpr((h, p, 0)) q3.setHpr((h, p - 20 - p / 4, 0)) length1 = scale * 4 length2 = scale * 3 f = q2.getForward() * length1 r = q2.getRight() * scale * .5 f2 = q3.getForward() * length2 + f norm0 = q2.getUp() norm2 = q3.getUp() norm1 = norm0 + norm2 norm1.normalize() for x in range(2): leafRow = vertexWriter.getWriteRow() vertexWriter.addData3f(pos) vertexWriter.addData3f(pos + f + r) vertexWriter.addData3f(pos + f - r) vertexWriter.addData3f(pos + f2) if self.leafTexture: texcoordWriter.addData2f(0, 0) texcoordWriter.addData2f(0, 1) texcoordWriter.addData2f(1, 0) texcoordWriter.addData2f(1, 1) if x == 1: # back sides norm0 = -norm0 norm1 = -norm1 norm2 = -norm2 leafTri.addVertices(leafRow + 1, leafRow, leafRow + 2) leafTri.addVertices(leafRow + 3, leafRow + 1, leafRow + 2) else: leafTri.addVertices(leafRow, leafRow + 1, leafRow + 2) leafTri.addVertices(leafRow + 1, leafRow + 3, leafRow + 2) normalWriter.addData3f(norm0) normalWriter.addData3f(norm1) normalWriter.addData3f(norm1) normalWriter.addData3f(norm2)