/*
* JaamSim Discrete Event Simulation
* Copyright (C) 2012 Ausenco Engineering Canada Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jaamsim.font;
import java.util.HashMap;
import com.jogamp.opengl.GL2GL3;
import com.jaamsim.math.Color4d;
import com.jaamsim.math.Ray;
import com.jaamsim.math.Vec3d;
import com.jaamsim.render.Camera;
import com.jaamsim.render.OverlayRenderable;
import com.jaamsim.render.RenderUtils;
import com.jaamsim.render.Renderer;
import com.jaamsim.render.Shader;
import com.jaamsim.render.VisibilityInfo;
public class OverlayString implements OverlayRenderable {
private TessFont _font;
private String _contents;
private final float[] _color;
private double _height;
private double _x, _y;
private boolean _alignRight, _alignBottom;
private VisibilityInfo _visInfo;
private static HashMap<Integer, Integer> VAOMap = new HashMap<>();
public OverlayString(TessFont font, String contents, Color4d color,
double height, double x, double y,
boolean alignRight, boolean alignBottom, VisibilityInfo visInfo) {
_font = font;
_contents = contents;
if (_contents == null) {
_contents = "";
}
_color = color.toFloats();
_height = height;
_x = x; _y = y;
_alignRight = alignRight; _alignBottom = alignBottom;
_visInfo = visInfo;
}
@Override
public void render(int contextID, Renderer renderer,
double windowWidth, double windowHeight, Camera cam, Ray pickRay) {
Vec3d renderedSize = _font.getStringSize(_height, _contents);
double x = _x;
double y = _y;
if (_alignRight) {
x = windowWidth - _x - renderedSize.x;
}
if (!_alignBottom) {
y = windowHeight - _y - renderedSize.y;
}
GL2GL3 gl = renderer.getGL();
if (!VAOMap.containsKey(contextID)) {
setupVAO(contextID, renderer);
}
int vao = VAOMap.get(contextID);
gl.glBindVertexArray(vao);
// Render the string
Shader s = renderer.getShader(Renderer.ShaderHandle.OVERLAY_FONT);
s.useShader(gl);
int prog = s.getProgramHandle();
int colorVar = gl.glGetUniformLocation(prog, "color");
gl.glUniform4fv(colorVar, 1, _color, 0);
int posVar = gl.glGetAttribLocation(prog, "position");
gl.glEnableVertexAttribArray(posVar);
gl.glBindBuffer(GL2GL3.GL_ARRAY_BUFFER, _font.getGLBuffer(gl));
gl.glVertexAttribPointer(posVar, 2, GL2GL3.GL_FLOAT, false, 0, 0);
gl.glBindBuffer(GL2GL3.GL_ARRAY_BUFFER, 0);
int offsetVar = gl.glGetUniformLocation(prog, "offset");
float scaleY = (float)(2 * _height / (windowHeight * _font.getNominalHeight()));
float scaleX = scaleY * (float)(windowHeight/windowWidth);
int scaleVar = gl.glGetUniformLocation(prog, "scale");
gl.glUniform2f(scaleVar, scaleX, scaleY);
float offsetX = (float)(2*x/windowWidth - 1);
float offsetY = (float)(2*y/windowHeight - 1);
gl.glDisable(GL2GL3.GL_CULL_FACE);
for (int cp : RenderUtils.stringToCodePoints(_contents)) {
TessChar tc = _font.getTessChar(cp);
if (tc == null) {
assert(false);
continue;
}
gl.glUniform2f(offsetVar, offsetX, offsetY);
gl.glDrawArrays(GL2GL3.GL_TRIANGLES, tc.getStartIndex(), tc.getNumVerts());
offsetX += tc.getAdvance()*scaleX;
}
gl.glEnable(GL2GL3.GL_CULL_FACE);
}
private void setupVAO(int contextID, Renderer renderer) {
GL2GL3 gl = renderer.getGL();
int vao = renderer.generateVAO(contextID, gl);
VAOMap.put(contextID, vao);
}
@Override
public boolean renderForView(int viewID, Camera cam) {
return _visInfo.isVisible(viewID);
}
}