added working piece outline; added final tweaks for boardHandler

This commit is contained in:
Cedric Beck
2024-11-22 19:53:32 +01:00
parent 00014eeb09
commit ebdedc6494
12 changed files with 179 additions and 287 deletions

View File

@@ -6,7 +6,7 @@
<option name="WORKING_DIRECTORY" value="$MODULE_WORKING_DIR$" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="pp.mdga.client.board.*" />
<option name="PATTERN" value="pp.mdga.client.board.Outline.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
@@ -14,4 +14,4 @@
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
</component>

View File

@@ -6,6 +6,7 @@
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.post.FilterPostProcessor;
import com.jme3.renderer.lwjgl.LwjglRender;
import com.jme3.system.NanoTimer;
import pp.mdga.client.acoustic.AcousticHandler;
@@ -25,7 +26,7 @@
public class MdgaApp extends SimpleApplication {
private AnimationHandler animationHandler;
private AcousticHandler acousticHandler;
private BoardHandler boardView;
private BoardHandler boardHandler;
private DialogView dialogView;
NanoTimer test = new NanoTimer();
@@ -49,9 +50,14 @@ public static void main(String[] args) {
public void simpleInitApp() {
animationHandler = new AnimationHandler(this);
acousticHandler = new AcousticHandler(this);
boardView = new BoardHandler(this);
dialogView = new DialogView(this);
new CameraHandler(this);
//Filter für Outline: Reihenfolge CameraHandler(dlsf) -> BoardHandler -> viewPort.addProcessor einhalten!
FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
new CameraHandler(this, fpp);
boardHandler = new BoardHandler(this, fpp);
viewPort.addProcessor(fpp);
//dialogView.mainMenu();
//acousticHandler.playState(MdgaState.GAME);
@@ -69,15 +75,15 @@ public void simpleInitApp() {
testList.add(test1);
testList.add(test0);
// UUID test0_1 = UUID.randomUUID();
// UUID test1_1 = UUID.randomUUID();
// List<UUID> testList_1 = new ArrayList<>();
// testList_1.add(UUID.randomUUID());
// testList_1.add(UUID.randomUUID());
// testList_1.add(test1_1);
// testList_1.add(test0_1);
UUID test0_1 = UUID.randomUUID();
UUID test1_1 = UUID.randomUUID();
List<UUID> testList_1 = new ArrayList<>();
testList_1.add(UUID.randomUUID());
testList_1.add(UUID.randomUUID());
testList_1.add(test1_1);
testList_1.add(test0_1);
boardView.init();
// boardHandler.init();
inputManager.addMapping("h", new KeyTrigger(KeyInput.KEY_H));
inputManager.addMapping("j", new KeyTrigger(KeyInput.KEY_J));
@@ -85,17 +91,21 @@ public void simpleInitApp() {
@Override
public void onAction(String name, boolean isPressed, float tpf) {
if (name.equals("h") && isPressed) {
boardView.highlight(test0);
boardHandler.init();
}
if(name.equals("j") && isPressed){
boardView.unHighlight(test0);
boardHandler.shutdown();
}
}
}, "h", "j");
boardView.addPlayer(Color.AIRFORCE, testList);
// boardHandler.addPlayer(Color.AIRFORCE, testList);
// boardHandler.movePieceStart(test0, 0);
//
// boardHandler.addPlayer(Color.CYBER, testList_1);
// boardHandler.movePieceStart(test0_1, 10);
}
@@ -132,7 +142,7 @@ public AcousticHandler getAcousticHandler() {
}
public BoardHandler getBoardView() {
return boardView;
return boardHandler;
}
public DialogView getDialogView() {

View File

@@ -14,8 +14,8 @@ enum BoardAsset {
node_wait_black("./node_home/node_home.j3o", "./node_home/node_home_black_diff.png"),
node_home_green("./node_home/node_home.j3o", "./node_home/node_home_green_diff.png"),
node_wait_green("./node_home/node_home.j3o", "./node_home/node_home_green_diff.png"),
node_home_yellow("./node_home/node_home.j3o", "./node_home/node_home_yellow_diff.png"),
node_wait_yellow("./node_home/node_home.j3o", "./node_home/node_home_yellow_diff.png"),
node_home_yellow("./node_home/node_home.j3o", "./node_home/node_home_orange_diff.png"),
node_wait_yellow("./node_home/node_home.j3o", "./node_home/node_home_orange_diff.png"),
node_normal,
node_start("./node_normal/node_normal.j3o", "./node_normal/node_start_diff.png"),
node_bonus("./node_normal/node_normal.j3o", "./node_normal/node_bonus_diff.png"),

View File

@@ -3,6 +3,7 @@
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
@@ -31,25 +32,18 @@ public class BoardHandler {
private Map<Color, List<PieceControl>> waitingPiecesMap;
private Map<UUID, Color> pieceColor;
private final Node node;
private final OutlineHandler outlineHandler;
private Node node;
public BoardHandler(MdgaApp app) {
private FilterPostProcessor fpp;
private boolean init;
public BoardHandler(MdgaApp app, FilterPostProcessor fpp) {
if(app == null) throw new RuntimeException("app is null");
this.init = false;
this.app = app;
this.pieces = new HashMap<>();
this.colorAssetsMap = new HashMap<>();
this.infield = new ArrayList<>(40);
this.homeNodesMap = new HashMap<>();
this.waitingNodesMap = new HashMap<>();
this.waitingPiecesMap = new HashMap<>();
this.pieceColor = new HashMap<>();
this.node = new Node("Asset Node");
this.outlineHandler = new OutlineHandler(app, app.getRootNode());
app.getRootNode().attachChild(node);
this.fpp = fpp;
}
private void addFigureToPlayerMap(Color col, AssetOnMap assetOnMap) {
@@ -58,6 +52,20 @@ private void addFigureToPlayerMap(Color col, AssetOnMap assetOnMap) {
}
private void initMap() {
if (init) return;
this.init = true;
this.node = new Node("Asset Node");
app.getRootNode().attachChild(node);
this.pieces = new HashMap<>();
this.colorAssetsMap = new HashMap<>();
this.infield = new ArrayList<>(40);
this.homeNodesMap = new HashMap<>();
this.waitingNodesMap = new HashMap<>();
this.waitingPiecesMap = new HashMap<>();
this.pieceColor = new HashMap<>();
List<AssetOnMap> assetOnMaps = MapLoader.loadMap(MAP_NAME);
for (AssetOnMap assetOnMap : assetOnMaps) {
@@ -170,6 +178,8 @@ private <T, E> List<T> removeItemFromMapList(Map<E,List<T>> map, E key, T item){
//public methods****************************************************************************************************
public void addPlayer(Color color, List<UUID> uuid) {
if (!init) throw new RuntimeException("BoardHandler is not initialized");
List<AssetOnMap> playerAssets = colorAssetsMap.get(color);
if (playerAssets == null) throw new RuntimeException("Assets for Player color are not defined");
if (uuid.size() != playerAssets.size()) throw new RuntimeException("UUID array and playerAssets are not the same size");
@@ -180,7 +190,7 @@ public void addPlayer(Color color, List<UUID> uuid) {
for (int i = 0; i < playerAssets.size(); i++){
AssetOnMap assetOnMap = playerAssets.get(i);
PieceControl pieceControl = displayAndControl(assetOnMap, new PieceControl(assetOnMap.rot(), app.getAssetManager(), app));
PieceControl pieceControl = displayAndControl(assetOnMap, new PieceControl(assetOnMap.rot(), app.getAssetManager(), app, fpp));
movePieceToNode(pieceControl, waitNodes.get(i));
pieces.put(uuid.get(i), pieceControl);
@@ -192,6 +202,8 @@ public void addPlayer(Color color, List<UUID> uuid) {
}
public void moveHomePiece(UUID uuid, int index){
if (!init) throw new RuntimeException("BoardHandler is not initialized");
Color color = pieceColor.get(uuid);
if(color == null) throw new RuntimeException("uuid is not mapped to a color");
@@ -199,8 +211,6 @@ public void moveHomePiece(UUID uuid, int index){
if(homeNodesMap.size() != 4) throw new RuntimeException("HomeNodes for" + color + " are not properly defined");
PieceControl pieceControl = pieces.get(uuid);
NodeControl nodeControl = homeNodes.get(index);
movePieceToNode(pieceControl, nodeControl);
@@ -213,6 +223,8 @@ public void moveHomePiece(UUID uuid, int index){
}
public void movePieceStart(UUID uuid, int nodeIndex){
if (!init) throw new RuntimeException("BoardHandler is not initialized");
Color color = pieceColor.get(uuid);
if(color == null) throw new RuntimeException("uuid is not mapped to a color");
@@ -223,10 +235,14 @@ public void movePieceStart(UUID uuid, int nodeIndex){
}
public void movePiece(UUID uuid, int curIndex, int moveIndex){
if (!init) throw new RuntimeException("BoardHandler is not initialized");
movePiece_rek(uuid, curIndex, moveIndex);
}
public void throwPiece(UUID uuid){
if (!init) throw new RuntimeException("BoardHandler is not initialized");
Color color = pieceColor.get(uuid);
if(color == null) throw new RuntimeException("uuid is not mapped to a color");
@@ -240,18 +256,26 @@ public void throwPiece(UUID uuid){
}
public void shieldPiece(UUID uuid){
if (!init) throw new RuntimeException("BoardHandler is not initialized");
pieces.get(uuid).activateShield();
}
public void unshieldPiece(UUID uuid){
if (!init) throw new RuntimeException("BoardHandler is not initialized");
pieces.get(uuid).deactivateShield();
}
public void suppressShield(UUID uuid){
if (!init) throw new RuntimeException("BoardHandler is not initialized");
pieces.get(uuid).suppressShield();
}
public void swapPieces(UUID piece1, UUID piece2){
if (!init) throw new RuntimeException("BoardHandler is not initialized");
PieceControl piece1_control = pieces.get(piece1);
PieceControl piece2_control = pieces.get(piece2);
@@ -264,8 +288,8 @@ public void swapPieces(UUID piece1, UUID piece2){
piece1_control.setRotation(rot2);
piece2_control.setRotation(rot1);
Vector3f pos1 = piece1_control.getLocation();
Vector3f pos2 = piece2_control.getLocation();
Vector3f pos1 = piece1_control.getLocation().clone();
Vector3f pos2 = piece2_control.getLocation().clone();
piece1_control.setLocation(pos2);
piece2_control.setLocation(pos1);
@@ -276,23 +300,24 @@ public void init(){
}
public void shutdown(){
//TODO
if (!init) return;
//Wrapper node
//komische lichter
init = false;
app.getRootNode().detachChild(node);
}
//List<Pieces>
//List<NodesIndexe>
public void highlight(UUID uuid){
pieces.get(uuid).outline();
public void highlight(UUID uuid, boolean bool){
if (!init) throw new RuntimeException("BoardHandler is not initialized");
pieces.get(uuid).outline(bool);
}
public void unHighlight(UUID uuid){
if (!init) throw new RuntimeException("BoardHandler is not initialized");
pieces.get(uuid).deOutline();
}
}

View File

@@ -4,6 +4,8 @@
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.shadow.DirectionalLightShadowFilter;
import com.jme3.shadow.DirectionalLightShadowRenderer;
import pp.mdga.client.MdgaApp;
@@ -13,9 +15,11 @@ public class CameraHandler {
private static final int SHADOWMAP_SIZE = 1024 * 8;
FilterPostProcessor fpp;
public CameraHandler(MdgaApp app){
public CameraHandler(MdgaApp app, FilterPostProcessor fpp){
this.app = app;
this.fpp = fpp;
initCamera();
}
@@ -34,8 +38,8 @@ private void initCamera() {
ambient.setColor(new ColorRGBA(0.3f, 0.3f, 0.3f, 1));
app.getRootNode().addLight(ambient);
DirectionalLightShadowRenderer dlsr = new DirectionalLightShadowRenderer(app.getAssetManager(), SHADOWMAP_SIZE, 4);
dlsr.setLight(sun);
app.getViewPort().addProcessor(dlsr);
DirectionalLightShadowFilter dlsf = new DirectionalLightShadowFilter(app.getAssetManager(), SHADOWMAP_SIZE, 4);
dlsf.setLight(sun);
fpp.addFilter(dlsf);
}
}

View File

@@ -1,4 +1,4 @@
package pp.mdga.client.board;
package pp.mdga.client.board.Outline;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;

View File

@@ -1,4 +1,4 @@
package pp.mdga.client.board;
package pp.mdga.client.board.Outline;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;

View File

@@ -0,0 +1,77 @@
package pp.mdga.client.board.Outline;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.post.Filter;
import com.jme3.post.FilterPostProcessor;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import pp.mdga.game.Color;
public class SelectObjectOutliner {
private final FilterPostProcessor fpp;
private final RenderManager renderManager;
private final AssetManager assetManager;
private final Camera cam;
private final int width;
private boolean selected;
private ViewPort outlineViewport = null;
private OutlineFilter outlineFilter = null;
public SelectObjectOutliner(int width, FilterPostProcessor fpp, RenderManager renderManager, AssetManager assetManager, Camera cam) {
this.selected = false;
this.fpp = fpp;
this.renderManager = renderManager;
this.assetManager = assetManager;
this.cam = cam;
this.width = width;
}
public void deselect(Spatial model) {
if(selected){
selected = false;
hideOutlineFilterEffect(model);
}
}
public void select(Spatial model, ColorRGBA color) {
if(!selected){
selected = true;
showOutlineFilterEffect(model, width, color);
}
}
private void hideOutlineFilterEffect(Spatial model) {
outlineFilter.setEnabled(false);
outlineFilter.getOutlinePreFilter().setEnabled(false);
fpp.removeFilter(outlineFilter);
outlineViewport.detachScene(model);
renderManager.removePreView(outlineViewport);
outlineViewport = null;
}
private void showOutlineFilterEffect(Spatial model, int width, ColorRGBA color) {
outlineViewport = renderManager.createPreView("outlineViewport", cam);
FilterPostProcessor outlineFpp = new FilterPostProcessor(assetManager);
OutlinePreFilter outlinePreFilter = new OutlinePreFilter();
outlineFpp.addFilter(outlinePreFilter);
outlineViewport.attachScene(model);
outlineViewport.addProcessor(outlineFpp);
outlineFilter = new OutlineFilter(outlinePreFilter);
outlineFilter.setOutlineColor(color);
outlineFilter.setOutlineWidth(width);
fpp.addFilter(outlineFilter);
}
}

View File

@@ -1,45 +0,0 @@
package pp.mdga.client.board;
import com.jme3.math.ColorRGBA;
import com.jme3.post.FilterPostProcessor;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import pp.mdga.client.MdgaApp;
public class OutlineHandler {
private SelectObjectOutliner outlineOwn;
private SelectObjectOutliner outlineEnemy;
private static final ColorRGBA OUTLINE_OWN_COLOR = ColorRGBA.White;
private static final ColorRGBA OUTLINE_ENEMY_COLOR = ColorRGBA.Red;
private static final int OUTLINE_THICKNESS = 4;
private Node outlineNode;
public OutlineHandler(MdgaApp app, Node rootNode){
FilterPostProcessor fpp = new FilterPostProcessor(app.getAssetManager());
app.getViewPort().addProcessor(fpp);
this.outlineOwn = new SelectObjectOutliner();
this.outlineOwn.initOutliner(SelectObjectOutliner.OUTLINER_TYPE_FILTER, OUTLINE_THICKNESS, OUTLINE_OWN_COLOR, rootNode, fpp, app.getRenderManager(), app.getAssetManager(), app.getCamera());
// this.outlineEnemy = new SelectObjectOutliner();
// this.outlineEnemy.initOutliner(SelectObjectOutliner.OUTLINER_TYPE_FILTER, OUTLINE_THICKNESS, OUTLINE_ENEMY_COLOR, rootNode, fpp, app.getRenderManager(), app.getAssetManager(), app.getCamera());
}
public void outlineOwn(Spatial spatial){
this.outlineOwn.select(spatial);
}
public void outlineEnemy(Spatial spatial){
// this.outlineEnemy.select(spatial);
}
public void deOutline(Spatial spatial){
this.outlineOwn.deselect(spatial);
this.outlineEnemy.deselect(spatial);
}
}

View File

@@ -15,6 +15,7 @@
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import pp.mdga.client.MdgaApp;
import pp.mdga.client.board.Outline.SelectObjectOutliner;
public class PieceControl extends AbstractControl {
private final float initRotation;
@@ -31,10 +32,12 @@ public class PieceControl extends AbstractControl {
SelectObjectOutliner outlineOwn;
private static final ColorRGBA OUTLINE_OWN_COLOR = ColorRGBA.White;
private static final ColorRGBA OUTLINE_ENEMY_COLOR = ColorRGBA.Red;
private static final int OUTLINE_THICKNESS = 4;
private final Node parentNode;
public PieceControl(float initRotation, AssetManager assetManager, MdgaApp app){
public PieceControl(float initRotation, AssetManager assetManager, MdgaApp app, FilterPostProcessor fpp){
super();
this.parentNode = new Node();
this.initRotation = initRotation;
@@ -43,10 +46,8 @@ public PieceControl(float initRotation, AssetManager assetManager, MdgaApp app){
this.shieldMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
this.shieldMat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Alpha);
FilterPostProcessor fpp = new FilterPostProcessor(app.getAssetManager());
app.getViewPort().addProcessor(fpp);
outlineOwn = new SelectObjectOutliner();
outlineOwn.initOutliner(SelectObjectOutliner.OUTLINER_TYPE_FILTER, OUTLINE_THICKNESS, OUTLINE_OWN_COLOR, parentNode, fpp, app.getRenderManager(), app.getAssetManager(), app.getCamera());
outlineOwn = new SelectObjectOutliner(OUTLINE_THICKNESS, fpp, app.getRenderManager(), app.getAssetManager(), app.getCamera());
}
@@ -137,8 +138,9 @@ public Material getMaterial(){
return ((Geometry) this.spatial).getMaterial();
}
public void outline() {
outlineOwn.select(this.getSpatial());
public void outline(boolean enemy) {
ColorRGBA color = enemy ? OUTLINE_ENEMY_COLOR : OUTLINE_OWN_COLOR;
outlineOwn.select(this.getSpatial(), color);
}
public void deOutline() {

View File

@@ -1,181 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package pp.mdga.client.board;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.post.Filter;
import com.jme3.post.FilterPostProcessor;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
/**
*
* @author xxx
*/
public class SelectObjectOutliner {
private FilterPostProcessor fpp;
private RenderManager renderManager;
private AssetManager assetManager;
private Camera cam;
/**
*
*/
public static int OUTLINER_TYPE_FILTER=0;
/**
*
*/
public static int OUTLINER_TYPE_MATERIAL=1;
private Material wireMaterial;
private Node modelNode;
int outlinerType=OUTLINER_TYPE_FILTER;
private int width=5;
private ColorRGBA color=ColorRGBA.Yellow;
/**
*
*/
public SelectObjectOutliner()
{
}
/**
*
* @param type of filter: OUTLINER_TYPE_FILTER or OUTLINER_TYPE_MATERIAL
* @param width of the selection border
* @param color of the selection border
* @param modelNode direct node containing the spacial. Wil be used to add geometry in OUTLINER_TYPE_MATERIAL node.
* @param fpp - FilterPostProcessor to handle filtering
* @param renderManager
* @param assetManager
* @param cam - main cam
*/
public void initOutliner(int type, int width, ColorRGBA color, Node modelNode, FilterPostProcessor fpp, RenderManager renderManager,AssetManager assetManager, Camera cam)
{
outlinerType=type;
this.fpp=fpp;
this.renderManager=renderManager;
this.assetManager=assetManager;
this.cam=cam;
this.modelNode=modelNode;
this.width=width;
this.color=color;
if(outlinerType==OUTLINER_TYPE_MATERIAL)
{
wireMaterial= new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
wireMaterial.setColor("Color", color);//color
wireMaterial.getAdditionalRenderState().setWireframe(true); //we want wireframe
wireMaterial.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);//that's just because we add an alpha pulse to the selection later, this is not mandatory
wireMaterial.getAdditionalRenderState().setLineWidth(width); //you can play with this param to increase the line thickness
wireMaterial.getAdditionalRenderState().setPolyOffset(-3f,-3f); //this is trick one, offsetting the polygons
wireMaterial.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Front); // trick 2 we hide the front faces to not see the wireframe on top of the geom
}
}
/**
*
* @param model to be delected
*/
public void deselect(Spatial model)
{
if(outlinerType==OUTLINER_TYPE_FILTER)
hideOutlineFilterEffect(model);
else
hideOutlineMaterialEffect(model);
model.setUserData("OutlineSelected", false);
}
/**
*
* @param model to delected
*/
public void select(Spatial model)
{
if(outlinerType==OUTLINER_TYPE_FILTER)
showOutlineFilterEffect( model, width, color);
else
showOutlineMaterialEffect( model, width, color);
model.setUserData("OutlineSelected", true);
}
/**
*
* @param model
* @return
*/
public boolean isSelected(Spatial model)
{
if(model.getUserData("OutlineSelected")!=null && ((Boolean)model.getUserData("OutlineSelected"))==true)
return true;
else
return false;
}
private void hideOutlineMaterialEffect(Spatial model) {
Spatial geo= (Spatial)model.getUserData("OutlineGeo");
if (geo != null)
modelNode.detachChild(geo);
}
private void showOutlineMaterialEffect(Spatial model, int width, ColorRGBA color) {
Spatial geo=model.clone(false);
geo.setMaterial(wireMaterial);
model.setUserData("OutlineGeo", geo);
modelNode.attachChild(geo);
}
private void hideOutlineFilterEffect(Spatial model) {
OutlineFilter outlineFilter = model.getUserData("OutlineFilter");
if (outlineFilter != null) {
outlineFilter.setEnabled(false);
outlineFilter.getOutlinePreFilter().setEnabled(false);
fpp.removeFilter(outlineFilter);
model.setUserData("OutlineFilter", null);
}
}
private void showOutlineFilterEffect(Spatial model, int width, ColorRGBA color) {
Filter outlineFilter = model.getUserData("OutlineFilter");
OutlinePreFilter outlinePreFilter;
if (outlineFilter == null) {
ViewPort outlineViewport = renderManager.createPreView("outlineViewport", cam);
FilterPostProcessor outlinefpp = new FilterPostProcessor(assetManager);
outlinePreFilter = new OutlinePreFilter();
outlinefpp.addFilter(outlinePreFilter);
outlineViewport.attachScene(model);
outlineViewport.addProcessor(outlinefpp);
//
outlineFilter = new OutlineFilter(outlinePreFilter);
((OutlineFilter)outlineFilter).setOutlineColor(color);
((OutlineFilter)outlineFilter).setOutlineWidth(width);
model.setUserData("OutlineFilter", outlineFilter);
fpp.addFilter(outlineFilter);
} else {
outlineFilter.setEnabled(true);
//
((OutlineFilter)outlineFilter).getOutlinePreFilter().setEnabled(true);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB