/** * Construct this component's scene graph. This consists of the following nodes. * * <p>parentEntity attachPoint -> localToCellNode -> Spatial, Spatial, etc. (subclass provided) */ protected void initSceneGraph() { // Attach the localToCell node to the entity localToCellNode = new Node("Local-to-cell node for frame component " + name); RenderComponent rc = ClientContextJME.getWorldManager() .getRenderManager() .createRenderComponent(localToCellNode); entity.addComponent(RenderComponent.class, rc); rc.setEntity(entity); // Attach the subclass spatials to the localToCell node final Spatial[] spatials = getSpatials(); if (spatials != null) { ClientContextJME.getWorldManager() .addRenderUpdater( new RenderUpdater() { public void update(Object arg0) { if (localToCellNode != null) { for (Spatial spatial : spatials) { localToCellNode.attachChild(spatial); } ClientContextJME.getWorldManager().addToUpdateList(localToCellNode); } } }, null, true); // Topology change. Must wait for it to complete. } }
/** * Sets the Z-buffer state on the given node. * * <p>NOTE: This method assumes it is being called in a MT-Safe manner. */ private void setZBufferState(Node node) { RenderManager rm = ClientContextJME.getWorldManager().getRenderManager(); ZBufferState zbuf = (ZBufferState) rm.createRendererState(RenderState.StateType.ZBuffer); zbuf.setEnabled(true); zbuf.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo); node.setRenderState(zbuf); }
/** Return true if we support high-quality avatars */ public static boolean supportsHighQualityAvatars() { String shaderCheck = System.getProperty("avatar.shaderCheck"); boolean shaderPass = true; // Check to see if the system supports OpenGL 2.0. If not, then // always use the low-detail avatar character RenderManager rm = ClientContextJME.getWorldManager().getRenderManager(); if (shaderCheck != null && shaderCheck.equals("true")) { shaderPass = rm.getContextCaps().GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB >= 512; } // Issue 1114: make sure the system is telling the truth about what // it supports by trying a mock shader program boolean uniformsPass = shaderPass && ShaderTest.getInstance().testShaders(); logger.warning( "Checking avatar detail level. OpenGL20: " + rm.supportsOpenGL20() + " ShaderCheck: " + shaderPass + " UniformsCheck: " + uniformsPass); // OWL issue #110 -- ignore the value of supportsOpenGL20() here. This // is known to report false negatives on at least one graphics card. // Our shader test should do an adequate job determining whether a // graphics card supports the OpenGL 2.0 features we use. // Update: fixed version of supportsOpenGL20 should properly detect // version. return rm.supportsOpenGL20() && shaderPass && uniformsPass; }
/** Changes the avatar to the given avatar on the MT Game Render Thread */ public void changeAvatar(final WlAvatarCharacter avatar) { RenderUpdater updater = new RenderUpdater() { public void update(Object arg0) { changeAvatarInternal(avatar); } }; WorldManager wm = ClientContextJME.getWorldManager(); wm.addRenderUpdater(updater, null); }
/** * Sets the localToCell translation of this component. * * @param trans The translation vector. */ public void setLocalTranslation(final Vector3f trans) { ClientContextJME.getWorldManager() .addRenderUpdater( new RenderUpdater() { public void update(Object arg0) { if (localToCellNode != null) { setLocalTranslationNoUpdater(trans); ClientContextJME.getWorldManager().addToUpdateList(localToCellNode); } } }, null); }
public void setNode3Trans(Vector3f newTrans) { node3theSpatial.setLocalTranslation(newTrans); ClientContextJME.getWorldManager().addToUpdateList(node3theSpatial); }
public void setNode3Quat(Quaternion newQuat) { node3theSpatial.setLocalRotation(newQuat); ClientContextJME.getWorldManager().addToUpdateList(node3theSpatial); }
public void setTrans(Spatial theSpatial, Vector3f newTrans) { theSpatial.setLocalTranslation(newTrans); ClientContextJME.getWorldManager().addToUpdateList(theSpatial); }
public void selectForInput(boolean selected) { if (selectedForInput == selected) return; if (avatarCharacter == null) { logger.warning("selectForInput called with null avatarCharacter"); Thread.dumpStack(); return; } logger.info("selectedForInput " + selected); selectedForInput = selected; if (avatarCharacter != null) { WorldManager wm = ClientContextJME.getWorldManager(); ((WlAvatarContext) avatarCharacter.getContext()).getBehaviorManager().setEnable(false); if (controlScheme == null && selectedForInput) { controlScheme = new DefaultCharacterControls(ClientContextJME.getWorldManager()); ((AvatarControls) wm.getUserData(AvatarControls.class)).setDefault(controlScheme); } setCollisionController(avatarCharacter); if (selectedForInput) { // Listen for avatar movement and update the cell avatarCharacter .getContext() .getController() .addCharacterMotionListener(characterMotionListener); // Listen for game context changes avatarCharacter.getContext().addGameContextListener(gameContextListener); avatarCharacter.selectForInput(); controlScheme.addCharacterToTeam(avatarCharacter); controlScheme.setCharacter(avatarCharacter); // Chain the camera processor to the avatar motion processor for // smooth animation. For animated avatars we use CharacterAnimationProcessor for the simple // avatar CharacterProcessor ProcessorCollectionComponent pcc = avatarCharacter.getComponent(ProcessorCollectionComponent.class); ProcessorComponent characterProcessor = null; ProcessorComponent characterAnimationProcessor = null; for (ProcessorComponent pc : pcc.getProcessors()) { if (pc instanceof CharacterProcessor) characterProcessor = pc; else if (pc instanceof CharacterAnimationProcessor) { characterAnimationProcessor = pc; break; } } cameraChainedProcessor = null; if (characterAnimationProcessor != null) { cameraChainedProcessor = characterAnimationProcessor; } else if (characterProcessor != null) cameraChainedProcessor = characterProcessor; if (cameraChainedProcessor != null) { cameraChainedProcessor.addToChain(ViewManager.getViewManager().getCameraProcessor()); cameraChainedProcessor.setRunInRenderer(true); } // Disable culling for local avatar, fix for issue 799 avatarCharacter.getJScene().setCullHint(CullHint.Never); } else { avatarCharacter .getContext() .getController() .removeCharacterMotionListener(characterMotionListener); avatarCharacter.getContext().removeGameContextListener(gameContextListener); if (controlScheme != null) { controlScheme.clearCharacterTeam(); } if (cameraChainedProcessor != null) { cameraChainedProcessor.removeFromChain(ViewManager.getViewManager().getCameraProcessor()); cameraChainedProcessor = null; } // Reenable culling for local avatar, fix for issue 799 avatarCharacter.getJScene().setCullHint(CullHint.Dynamic); } } else { logger.severe("The avatar was null during enableInputListeners()."); } }
/** {@inheritDoc} */ @Override public void setStatus(CellStatus status, boolean increasing) { super.setStatus(status, increasing); WlAvatarCharacter pendingAvatar = null; logger.info("AVATAR RENDERER STATUS " + status + " DIR " + increasing); // If we are increasing to the ACTIVE state, then turn everything on. // Add the listeners to the avatar Cell and set the avatar character if (status == CellStatus.ACTIVE && increasing == true) { BoundsDebugger.getInstance().add(this); if (cellMoveListener != null) { // mc should not be null, but sometimes it seems to be MovableComponent mc = cell.getComponent(MovableComponent.class); if (mc == null) { logger.severe("NULL MovableComponent in avatar " + ((AvatarCell) cell).getName()); } else { mc.removeServerCellMoveListener(cellMoveListener); } cellMoveListener = null; } // If we have not creating the avatar yet, then look for the config // component on the cell. Fetch the avatar configuration. if (avatarCharacter == null) { AvatarConfigComponent configComp = cell.getComponent(AvatarConfigComponent.class); AvatarConfigInfo avatarConfigInfo = null; if (configComp != null) { avatarConfigInfo = configComp.getAvatarConfigInfo(); } logger.info("LOADING AVATAR FOR " + avatarConfigInfo); pendingAvatar = loadAvatar(avatarConfigInfo); } else { // Otherwise remove the existing avatar from the world ClientContextJME.getWorldManager().removeEntity(avatarCharacter); pendingAvatar = null; } // Go ahead and change the avatar logger.info("CHANGING AVATAR IN SET STATUS"); changeAvatar(pendingAvatar); if (cellMoveListener == null) { cellMoveListener = new CellMoveListener() { public void cellMoved(CellTransform transform, CellMoveSource source) { if (source == CellMoveSource.REMOTE) { // System.err.println("REMOTE MOVE // "+transform.getTranslation(null)); if (avatarCharacter != null) { if (avatarCharacter.getModelInst() == null) { // Extra debug check logger.severe("MODEL INST IS NULL !"); Thread.dumpStack(); return; } if (delayedMove != null) { delayedMove = null; logger.fine( cell.getCellID() + ": remove delayed move for: " + transform.toString()); } avatarCharacter .getModelInst() .setTransform( new PTransform( transform.getRotation(null), transform.getTranslation(null), new Vector3f(1, 1, 1))); } else { logger.fine(cell.getCellID() + ": delaying move: " + transform.toString()); // we tried to move before loading the avatar. // record the new position to apply when we // actually load delayedMove = transform; } } } }; } cell.getComponent(MovableComponent.class).addServerCellMoveListener(cellMoveListener); avatarUIEventListener = new AvatarUIEventListener(); ClientContext.getInputManager().addGlobalEventListener(avatarUIEventListener); collisionChangeRequestListener = new CollisionChangeRequestListener(); ClientContext.getInputManager().addGlobalEventListener(collisionChangeRequestListener); } else if (status == CellStatus.DISK && !increasing) { BoundsDebugger.getInstance().remove(this); ClientContext.getInputManager().removeGlobalEventListener(avatarUIEventListener); ClientContext.getInputManager().removeGlobalEventListener(collisionChangeRequestListener); cell.getComponent(MovableComponent.class).removeServerCellMoveListener(cellMoveListener); avatarUIEventListener = null; cellMoveListener = null; collisionChangeRequestListener = null; } }