simplex3d.engine.graphics.GraphicsContext.scala Maven / Gradle / Ivy
/*
* Simplex3dEngine - Core Module
* Copyright (C) 2011-2012, Aleksey Nikiforov
*
* This file is part of Simplex3dEngine.
*
* Simplex3dEngine is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Simplex3dEngine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
package simplex3d.engine
package graphics
import java.lang.Integer
import java.util.HashMap
import scala.reflect.runtime.universe._
import simplex3d.math.types._
import simplex3d.data._
import simplex3d.engine.util._
import simplex3d.engine.scene._
abstract class GraphicsContext {
type Geometry <: graphics.Geometry
type Material <: graphics.Material
type Environment <: graphics.Environment
def mkGeometry() :Geometry
def mkMaterial(controllerContext: ControllerContext) :Material
def mkEnvironment(controllerContext: ControllerContext) :Environment
final def namespace: Set[String] = combinedNamespace
private[this] final var combinedNamespace: Set[String] = null
private[this] final val uniformMap = new HashMap[String, (Int, Int)]
private[this] final val attributeMap = new HashMap[String, Integer]
private[this] var initialized = false
protected def init() {
if (initialized) throw new IllegalStateException("Already initialized.")
initialized = true
val geometry = mkGeometry()
val material = mkMaterial(null)
val environment = mkEnvironment(null)
// Initialize namespace.
val geomNames = geometry.attributeNames
val predefNames = PredefinedUniforms.BindingNames
val matNames = material.uniformNames
val envNames = environment.propertyNames
val attributeNamespace = geomNames.toSet
val uniformNamespace = predefNames.toSet ++ matNames ++ envNames
combinedNamespace = attributeNamespace ++ uniformNamespace
if (attributeNamespace.size < geomNames.size) {
throw new Error(
"Duplicate attribute names: " +
(geomNames.filterNot(e => attributeNamespace.contains(e))).distinct.mkString(", ") +
"."
)
}
if (uniformNamespace.size < predefNames.size + matNames.size + envNames.size) {
throw new Error(
"Duplicate uniform names: " +
(predefNames ++ matNames ++ envNames).filterNot(e => uniformNamespace.contains(e)).distinct.mkString(", ") +
"."
)
}
if (combinedNamespace.size < attributeNamespace.size + uniformNamespace.size) {
throw new Error(
"Name collision between attributes and uniforms: " +
(attributeNamespace.toList ++ uniformNamespace).filterNot(e => combinedNamespace.contains(e)).
distinct.mkString(", ") +
"."
)
}
// Initialize uniform map.
def registerUniforms(origin: Int, names: ReadArray[String]) {
for (i <- 0 until names.size) {
uniformMap.put(names(i), (origin, i))
}
}
registerUniforms(UniformOrigin.Predefined, PredefinedUniforms.BindingNames)
registerUniforms(UniformOrigin.Material, material.uniformNames)
registerUniforms(UniformOrigin.Environment, environment.propertyNames)
// Initialize attribute map.
for (i <- 0 until geometry.attributeNames.length) {
attributeMap.put(geometry.attributeNames(i), i)
}
}
def resolveRootUniform(
name: String,
predefined: ReadPredefinedUniforms,
material: graphics.Material,
environment: graphics.Environment,
programUniforms: Map[String, Value[UncheckedBinding]]
) :AnyRef = {
val originAndId = uniformMap.get(name)
if (originAndId == null) {
val option = programUniforms.get(name)
if (option.isDefined) option.get.get else null
}
else {
val origin = originAndId._1
val id = originAndId._2
origin match {
case UniformOrigin.Predefined =>
predefined.bindings(id)
case UniformOrigin.Material =>
val prop = material.uniforms(id)
if (prop.isDefined) prop.get else null
case UniformOrigin.Environment =>
val prop = environment.properties(id)
if (prop.isDefined) prop.get.binding else null
}
}
}
def resolveUniformPath(
path: String,
predefined: ReadPredefinedUniforms,
material: graphics.Material,
environment: graphics.Environment,
programUniforms: Map[String, Value[UncheckedBinding]]
) :AnyRef = {
path match {
case PathUtil.NameIndexRest(name, index, rest) =>
val res = resolveRootUniform(name, predefined, material, environment, programUniforms)
PathUtil.resolveAsList(index.toInt, rest, res)
case PathUtil.NameRest(name, rest) =>
val res = resolveRootUniform(name, predefined, material, environment, programUniforms)
PathUtil.resolveAsValue(rest, res)
case _ =>
null
}
}
def resolveAttributePath(
path: String,
geometry: graphics.Geometry
) :Attributes[Format, Raw] = {
val id = attributeMap.get(path)
if (id == null) null else {
val binding = geometry.attributes(id)
if (!binding.isDefined) null else binding.get
}
}
def collectKeys(geometry: graphics.Geometry, material: graphics.Material, worldEnvironment: graphics.Environment)
:(HashMap[ListNameKey, Integer], HashMap[String, Object], IndexedSeq[Boolean], IndexedSeq[Class[Object]]) =
{
val lists = new HashMap[ListNameKey, Integer]
val enums = new HashMap[String, Object]
val materialKey = new Array[Boolean](material.uniforms.size)
val envKey = new Array[Class[Object]](worldEnvironment.properties.size)
{
var i = 0; while (i < material.uniforms.size) {
val prop = material.uniforms(i)
val name = material.uniformNames(i)
if (prop.isDefined) prop.get match {
case seq: BindingSeq[_] => seq.collectKeys(name, new ListNameKey("", name), lists, enums)
case enum: EnumRef[_] => enum.collectKeys(name, enums)
case s: Struct => s.collectKeys(name, lists, enums)
case _ => // do nothing
}
materialKey(i) = prop.isDefined
i += 1
}
}
{
var i = 0; while (i < worldEnvironment.properties.size) {
val prop = worldEnvironment.properties(i)
val name = worldEnvironment.propertyNames(i)
if (prop.isDefined) {
val binding = prop.get.binding
binding match {
case seq: BindingSeq[_] => seq.collectKeys(name, new ListNameKey("", name), lists, enums)
case s: Struct => s.collectKeys(name, lists, enums)
case _ => // do nothing
}
envKey(i) = binding.getClass.asInstanceOf[Class[Object]]
}
i += 1
}
}
geometry.primitive.get.mode.collectKeys("primitive.mode", enums)
(lists, enums, materialKey, envKey)
}
def samplerRemapping(material: graphics.Material, worldEnvironment: graphics.Environment)
:HashMap[String, String] =
{
val remapping = new HashMap[String, String]
var i = 0; while (i < material.uniforms.size) {
val prop = material.uniforms(i)
val name = material.uniformNames(i)
if (prop.isDefined) prop.get match {
case seq: BindingSeq[_] if seq.elementTag.tpe <:< Types.Struct =>
seq.samplerRemapping(name, remapping)
case s: Struct =>
s.samplerRemapping(name, remapping)
case _ =>
// do nothing
}
i += 1
}
i = 0; while (i < worldEnvironment.properties.size) {
val prop = worldEnvironment.properties(i)
val name = worldEnvironment.propertyNames(i)
if (prop.isDefined) prop.get.binding match {
case seq: BindingSeq[_] if seq.elementTag.tpe <:< Types.Struct =>
seq.samplerRemapping(name, remapping)
case s: Struct =>
s.samplerRemapping(name, remapping)
case _ =>
// do nothing
}
i += 1
}
remapping
}
}
object MinimalGraphicsContext extends GraphicsContext {
type Geometry = graphics.Geometry
type Material = graphics.Material
type Environment = graphics.Environment
def mkGeometry() =
new prototype.Geometry { init(this.getClass) }
def mkMaterial(controllerContext: ControllerContext) =
new prototype.Material(controllerContext) { init(this.getClass) }
def mkEnvironment(controllerContext: ControllerContext) =
new prototype.Environment(controllerContext) { init(this.getClass) }
init()
override def resolveRootUniform(
name: String,
predefined: ReadPredefinedUniforms,
material: graphics.Material,
environment: graphics.Environment,
programUniforms: Map[String, Value[UncheckedBinding]]
) :AnyRef = {
var id = PathUtil.find(predefined.bindingNames, name)
if (id >= 0) return predefined.bindings(id)
id = PathUtil.find(material.uniformNames, name)
if (id >= 0) {
val prop = material.uniforms(id)
return (if (prop.isDefined) prop.get else null)
}
id = PathUtil.find(environment.propertyNames, name)
if (id >= 0) {
val prop = environment.properties(id)
return (if (prop.isDefined) prop.get.binding else null)
}
val option = programUniforms.get(name)
return (if (option.isDefined) option.get.get else null)
}
override def resolveAttributePath(
path: String,
geometry: graphics.Geometry
) :Attributes[Format, Raw] = {
val id = PathUtil.find(geometry.attributeNames, path)
if (id < 0) null
else {
val binding = geometry.attributes(id)
if (!binding.isDefined) null else binding.get
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy