Adding DU meshes.

This commit is contained in:
Jonathas Costa
2017-10-08 16:42:09 -04:00
parent 2999dcb96e
commit 4ab735b883
5 changed files with 700 additions and 198 deletions

View File

@@ -109,6 +109,8 @@ function postInitialization()
openspace.setPropertyValue("Stars Labels.renderable.Enabled", false)
openspace.setPropertyValue("Stars Labels - Alternate.renderable.Enabled", false)
openspace.setPropertyValue("Tully Galaxies.renderable.Enabled", false)
openspace.setPropertyValue("Tully Galaxies Pics.renderable.Enabled", false)
openspace.setPropertyValue("Constellations EXGAL.renderable.Enabled", false)
openspace.setPropertyValue("Earth.RenderableGlobe.Atmosphere", true)
openspace.setPropertyValue("Earth.RenderableGlobe.Debug.LevelByProjectedAreaElseDistance", false)
@@ -142,52 +144,53 @@ return {
Modules = {
-- # Solar system objects
"sun",
"mercury",
"venus",
--"mercury",
--"venus",
"earth",
--"moon",
"mars",
"jupiter",
"saturn",
"uranus",
--"mars",
--"jupiter",
--"saturn",
--"uranus",
--"neptune",
-- "satellites"
"constellationbounds",
"grids",
--"constellationbounds",
--"grids",
-- # Milkyway objects
"stars/digitaluniverse",
"alternatestarlabels/digitaluniverse",
"starlabels/digitaluniverse",
--"alternatestarlabels/digitaluniverse",
--"starlabels/digitaluniverse",
-- "stars/denver",
"milkyway/digitaluniverse",
--"milkyway/eso",
"globularclusters/digitaluniverse",
"kepler/digitaluniverse",
"pulsars/digitaluniverse",
"exoplanets/digitaluniverse",
"dwarfs/digitaluniverse",
"openclusters/digitaluniverse",
"obassociations/digitaluniverse",
"planetarynebulae/digitaluniverse",
"supernovaremnants/digitaluniverse",
"h2regions/digitaluniverse",
--"globularclusters/digitaluniverse",
--"kepler/digitaluniverse",
--"pulsars/digitaluniverse",
--"exoplanets/digitaluniverse",
--"dwarfs/digitaluniverse",
--"openclusters/digitaluniverse",
--"obassociations/digitaluniverse",
--"planetarynebulae/digitaluniverse",
--"supernovaremnants/digitaluniverse",
--"h2regions/digitaluniverse",
-- # Extragalactic objects
"groups/digitaluniverse",
"clusters/digitaluniverse",
"voids/digitaluniverse",
"superclusters/digitaluniverse",
"localdwarfs/digitaluniverse",
"abell/digitaluniverse",
"2mass/digitaluniverse",
"6dF/digitaluniverse",
"2dF/digitaluniverse",
"quasars/digitaluniverse",
"sloandss/digitaluniverse",
"constellations/digitaluniverse",
--"groups/digitaluniverse",
--"clusters/digitaluniverse",
--"voids/digitaluniverse",
--"superclusters/digitaluniverse",
--"localdwarfs/digitaluniverse",
--"abell/digitaluniverse",
--"2mass/digitaluniverse",
--"6dF/digitaluniverse",
--"2dF/digitaluniverse",
--"quasars/digitaluniverse",
--"sloandss/digitaluniverse",
--"tully/digitaluniverse",
"backgroundradiation/digitaluniverse",
--"backgroundradiation/digitaluniverse",
}
}

View File

@@ -54,8 +54,10 @@ void DigitalUniverseModule::internalInitialize() {
std::vector<documentation::Documentation> DigitalUniverseModule::documentations() const {
return {
RenderablePoints::Documentation()
//RenderablePointsSprinte::Documentation()
RenderablePoints::Documentation(),
RenderableBillboardsCloud::Documentation(),
RenderablePlanesCloud::Documentation(),
RenderableDUMeshes::Documentation()
};
}

View File

@@ -36,13 +36,18 @@
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <glm/gtx/string_cast.hpp>
#include <glm/glm.hpp>
#include <array>
#include <fstream>
#include <stdint.h>
namespace {
const char* _loggerCat = "RenderablePoints";
const char* _loggerCat = "RenderableDUMeshes";
const char* KeyFile = "File";
const char* keyColor = "Color";
const char* keyUnit = "Unit";
@@ -55,7 +60,7 @@ namespace {
const char* GigalightyearUnit = "Gly";
const int8_t CurrentCacheVersion = 1;
const double PARSEC = 0.308567756E17;
const float PARSEC = 0.308567756E17;
static const openspace::properties::Property::PropertyInfo TransparencyInfo = {
"Transparency",
@@ -76,6 +81,44 @@ namespace {
"Color",
"This value is used to define the color of the astronomical object."
};
static const openspace::properties::Property::PropertyInfo TextColorInfo = {
"TextColor",
"Text Color",
"The text color for the astronomical object."
};
static const openspace::properties::Property::PropertyInfo TextSizeInfo = {
"TextSize",
"Text Size",
"The text size for the astronomical object labels."
};
static const openspace::properties::Property::PropertyInfo LabelFileInfo = {
"LabelFile",
"Label File",
"The path to the label file that contains information about the astronomical "
"objects being rendered."
};
static const openspace::properties::Property::PropertyInfo LabelMinSizeInfo = {
"TextMinSize",
"Text Min Size",
"The minimal size (in pixels) of the text for the labels for the astronomical "
"objects being rendered."
};
static const openspace::properties::Property::PropertyInfo DrawElementsInfo = {
"DrawElements",
"Draw Elements",
"Enables/Disables the drawing of the astronomical objects."
};
static const openspace::properties::Property::PropertyInfo TransformationMatrixInfo = {
"TransformationMatrix",
"Transformation Matrix",
"Transformation matrix to be applied to each astronomical object."
};
} // namespace
namespace openspace {
@@ -83,12 +126,12 @@ namespace openspace {
documentation::Documentation RenderableDUMeshes::Documentation() {
using namespace documentation;
return {
"RenderablePoints",
"digitaluniverse_renderablepoints",
"RenderableDUMeshes",
"digitaluniverse_renderabledumeshes",
{
{
"Type",
new StringEqualVerifier("RenderablePoints"),
new StringEqualVerifier("RenderableDUMeshes"),
Optional::No
},
{
@@ -115,7 +158,37 @@ namespace openspace {
new DoubleVerifier,
Optional::Yes,
ScaleFactorInfo.description
}
},
{
TextColorInfo.identifier,
new DoubleVector4Verifier,
Optional::Yes,
TextColorInfo.description
},
{
TextSizeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
TextSizeInfo.description
},
{
LabelFileInfo.identifier,
new StringVerifier,
Optional::Yes,
LabelFileInfo.description
},
{
LabelMinSizeInfo.identifier,
new IntVerifier,
Optional::Yes,
LabelMinSizeInfo.description
},
{
TransformationMatrixInfo.identifier,
new Matrix4x4Verifier<double>,
Optional::Yes,
TransformationMatrixInfo.description
},
}
};
}
@@ -123,16 +196,30 @@ namespace openspace {
RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _hasSpeckFile(false)
, _dataIsDirty(true)
, _textColorIsDirty(true)
, _hasLabel(false)
, _labelDataIsDirty(true)
, _textMinSize(0)
, _alphaValue(TransparencyInfo, 1.f, 0.f, 1.f)
, _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 64.f)
, _pointColor(ColorInfo, glm::vec3(1.f, 0.4f, 0.2f), glm::vec3(0.f, 0.f, 0.f), glm::vec3(1.0f, 1.0f, 1.0f))
//, _pointColor(ColorInfo, glm::vec3(1.f, 0.4f, 0.2f), glm::vec3(0.f, 0.f, 0.f), glm::vec3(1.0f, 1.0f, 1.0f))
, _textColor(
TextColorInfo,
glm::vec4(1.0f, 1.0, 1.0f, 1.f),
glm::vec4(0.f),
glm::vec4(1.f)
)
, _textSize(TextSizeInfo, 8.0, 0.5, 24.0)
, _drawElements(DrawElementsInfo, true)
, _program(nullptr)
, _fontRenderer(nullptr)
, _font(nullptr)
, _speckFile("")
, _labelFile("")
, _unit(Parsec)
, _nValuesPerAstronomicalObject(0)
, _vao(0)
, _vbo(0)
, _nValuesPerAstronomicalObject(0)
{
using File = ghoul::filesystem::File;
@@ -142,8 +229,13 @@ namespace openspace {
"RenderableDUMeshes"
);
_speckFile = absPath(dictionary.value<std::string>(KeyFile));
if (dictionary.hasKey(KeyFile)) {
_speckFile = absPath(dictionary.value<std::string>(KeyFile));
_hasSpeckFile = true;
_drawElements.onChange([&]() {
_hasSpeckFile = _hasSpeckFile == true ? false : true; });
addProperty(_drawElements);
}
if (dictionary.hasKey(keyUnit)) {
std::string unit = dictionary.value<std::string>(keyUnit);
@@ -174,10 +266,10 @@ namespace openspace {
}
}
if (dictionary.hasKey(keyColor)) {
/*if (dictionary.hasKey(keyColor)) {
_pointColor = dictionary.value<glm::vec3>(keyColor);
}
addProperty(_pointColor);
addProperty(_pointColor);*/
if (dictionary.hasKey(TransparencyInfo.identifier)) {
_alphaValue = static_cast<float>(
@@ -193,31 +285,72 @@ namespace openspace {
}
addProperty(_scaleFactor);
if (dictionary.hasKey(LabelFileInfo.identifier)) {
_labelFile = absPath(dictionary.value<std::string>(
LabelFileInfo.identifier
));
_hasLabel = true;
if (dictionary.hasKey(TextColorInfo.identifier)) {
_textColor = dictionary.value<glm::vec4>(TextColorInfo.identifier);
_hasLabel = true;
}
_textColor.setViewOption(properties::Property::ViewOptions::Color);
addProperty(_textColor);
_textColor.onChange([&]() { _textColorIsDirty = true; });
if (dictionary.hasKey(TextSizeInfo.identifier)) {
_textSize = dictionary.value<float>(TextSizeInfo.identifier);
}
addProperty(_textSize);
if (dictionary.hasKey(LabelMinSizeInfo.identifier)) {
_textMinSize = static_cast<int>(dictionary.value<float>(LabelMinSizeInfo.identifier));
}
}
if (dictionary.hasKey(TransformationMatrixInfo.identifier)) {
_transformationMatrix = dictionary.value<glm::dmat4>(TransformationMatrixInfo.identifier);
}
}
bool RenderableDUMeshes::isReady() const {
return (_program != nullptr) && (!_fullData.empty());
return (_program != nullptr) && (!_fullData.empty() || (!_labelData.empty()));
}
void RenderableDUMeshes::initialize() {
RenderEngine& renderEngine = OsEng.renderEngine();
_program = renderEngine.buildRenderProgram("RenderableDUMeshes",
"${MODULE_DIGITALUNIVERSE}/shaders/points_vs.glsl",
"${MODULE_DIGITALUNIVERSE}/shaders/points_fs.glsl");// ,
//"${MODULE_DIGITALUNIVERSE}/shaders/points_ge.glsl");
"${MODULE_DIGITALUNIVERSE}/shaders/dumesh_vs.glsl",
"${MODULE_DIGITALUNIVERSE}/shaders/dumesh_fs.glsl");
bool success = loadData();
if (!success) {
throw ghoul::RuntimeError("Error loading data");
return;
}
createMeshes();
if (_hasLabel) {
if (_fontRenderer == nullptr)
_fontRenderer = std::unique_ptr<ghoul::fontrendering::FontRenderer>(
ghoul::fontrendering::FontRenderer::createProjectionSubjectText());
if (_font == nullptr) {
size_t _fontSize = 30;
_font = OsEng.fontManager().font("Mono", static_cast<float>(_fontSize),
ghoul::fontrendering::FontManager::Outline::Yes, ghoul::fontrendering::FontManager::LoadGlyphs::No);
}
}
}
void RenderableDUMeshes::deinitialize() {
glDeleteBuffers(1, &_vbo);
_vbo = 0;
glDeleteVertexArrays(1, &_vao);
_vao = 0;
for (auto pair : _renderingMeshesMap) {
glDeleteVertexArrays(1, &pair.second.vao);
glDeleteBuffers(1, &pair.second.vbo);
}
RenderEngine& renderEngine = OsEng.renderEngine();
if (_program) {
renderEngine.removeRenderProgram(_program);
@@ -225,120 +358,218 @@ namespace openspace {
}
}
void RenderableDUMeshes::render(const RenderData& data, RendererTasks&) {
void RenderableDUMeshes::renderMeshes(const RenderData& data, const glm::dmat4& modelViewMatrix,
const glm::dmat4& projectionMatrix) {
// Saving current OpenGL state
GLboolean blendEnabled = glIsEnabled(GL_BLEND);
GLenum blendEquationRGB;
GLenum blendEquationAlpha;
GLenum blendDestAlpha;
GLenum blendDestRGB;
GLenum blendSrcAlpha;
GLenum blendSrcRGB;
glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB);
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha);
glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha);
glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB);
glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha);
glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB);
glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(false);
_program->activate();
glm::dmat4 modelMatrix = glm::dmat4(1.0);
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
_program->setIgnoreUniformLocationError(IgnoreError::Yes);
_program->setUniform("modelViewProjectionTransform", glm::dmat4(data.camera.projectionMatrix()) *
data.camera.combinedViewMatrix() * modelMatrix);
_program->setUniform("color", _pointColor);
_program->setUniform("modelViewProjectionTransform", glm::dmat4(projectionMatrix) * modelViewMatrix);
_program->setUniform("alphaValue", _alphaValue);
_program->setUniform("scaleFactor", _scaleFactor);
//setPscUniforms(*_program.get(), data.camera, data.position);
//_program->setUniform("scaling", scaling);
for (auto pair : _renderingMeshesMap) {
glBindVertexArray(pair.second.vao);
switch (pair.second.style)
{
case Solid:
break;
case Wire:
glDrawArrays(GL_LINE_STRIP, 0, 6);
break;
case Point:
glDrawArrays(GL_POINTS, 0, 6);
break;
default:
break;
}
}
glEnable(GL_PROGRAM_POINT_SIZE);
glBindVertexArray(_vao);
const GLsizei nAstronomicalObjects = static_cast<GLsizei>(_fullData.size() / _nValuesPerAstronomicalObject);
glDrawArrays(GL_POINTS, 0, nAstronomicalObjects);
glDisable(GL_PROGRAM_POINT_SIZE);
glBindVertexArray(0);
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
_program->setIgnoreUniformLocationError(IgnoreError::No);
_program->deactivate();
// Restores blending state
glBlendEquationSeparate(blendEquationRGB, blendEquationAlpha);
glBlendFuncSeparate(blendSrcRGB, blendDestRGB, blendSrcAlpha, blendDestAlpha);
glDepthMask(true);
if (!blendEnabled) {
glDisable(GL_BLEND);
}
}
void RenderableDUMeshes::renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix,
const glm::vec3& orthoRight, const glm::vec3& orthoUp) {
RenderEngine& renderEngine = OsEng.renderEngine();
_fontRenderer->setFramebufferSize(renderEngine.renderingResolution());
float scale = 0.0;
switch (_unit) {
case Meter:
scale = 1.0;
break;
case Kilometer:
scale = 1e3;
break;
case Parsec:
scale = PARSEC;
break;
case Kiloparsec:
scale = 1e3 * PARSEC;
break;
case Megaparsec:
scale = 1e6 * PARSEC;
break;
case Gigaparsec:
scale = 1e9 * PARSEC;
break;
case GigalightYears:
scale = 306391534.73091 * PARSEC;
break;
}
for (const auto pair : _labelData) {
//glm::vec3 scaledPos(_transformationMatrix * glm::dvec4(pair.first, 1.0));
glm::vec3 scaledPos(pair.first);
scaledPos *= scale;
_fontRenderer->render(
*_font,
scaledPos,
_textColor,
pow(10.0, _textSize.value()),
_textMinSize,
modelViewProjectionMatrix,
orthoRight,
orthoUp,
"%s",
pair.second.c_str());
}
}
void RenderableDUMeshes::render(const RenderData& data, RendererTasks&) {
glm::dmat4 modelMatrix =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation
glm::dmat4(data.modelTransform.rotation) * // Spice rotation
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale));
glm::dmat4 modelViewMatrix = data.camera.combinedViewMatrix() * modelMatrix;
glm::mat4 projectionMatrix = data.camera.projectionMatrix();
glm::dmat4 modelViewProjectionMatrix = glm::dmat4(projectionMatrix) * modelViewMatrix;
glm::vec3 lookup = data.camera.lookUpVectorWorldSpace();
glm::vec3 viewDirection = data.camera.viewDirectionWorldSpace();
glm::vec3 right = glm::cross(viewDirection, lookup);
glm::vec3 up = glm::cross(right, viewDirection);
glm::dmat4 worldToModelTransform = glm::inverse(modelMatrix);
glm::vec3 orthoRight = glm::normalize(glm::vec3(worldToModelTransform * glm::vec4(right, 0.0)));
glm::vec3 orthoUp = glm::normalize(glm::vec3(worldToModelTransform * glm::vec4(up, 0.0)));
if (_hasSpeckFile) {
renderMeshes(data, modelViewMatrix, projectionMatrix);
}
if (_hasLabel) {
renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp);
}
}
void RenderableDUMeshes::update(const UpdateData&) {
if (_dataIsDirty) {
LDEBUG("Regenerating data");
createDataSlice();
int size = static_cast<int>(_slicedData.size());
if (_vao == 0) {
glGenVertexArrays(1, &_vao);
LDEBUG("Generating Vertex Array id '" << _vao << "'");
}
if (_vbo == 0) {
glGenBuffers(1, &_vbo);
LDEBUG("Generating Vertex Buffer Object id '" << _vbo << "'");
}
glBindVertexArray(_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(
GL_ARRAY_BUFFER,
size * sizeof(double),
&_slicedData[0],
GL_STATIC_DRAW
);
GLint positionAttrib = _program->attributeLocation("in_position");
const size_t nAstronomicalObjects = _fullData.size() / _nValuesPerAstronomicalObject;
const size_t nValues = _slicedData.size() / nAstronomicalObjects;
GLsizei stride = static_cast<GLsizei>(sizeof(double) * nValues);
glEnableVertexAttribArray(positionAttrib);
glVertexAttribLPointer(
positionAttrib,
4,
GL_DOUBLE,
0,
nullptr
);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
_dataIsDirty = false;
}
}
bool RenderableDUMeshes::loadData() {
std::string _file = _speckFile;
std::string cachedFile = FileSys.cacheManager()->cachedFilename(
_file,
ghoul::filesystem::CacheManager::Persistent::Yes
);
bool success = false;
if (_hasSpeckFile) {
std::string _file = _speckFile;
std::string cachedFile = FileSys.cacheManager()->cachedFilename(
_file,
ghoul::filesystem::CacheManager::Persistent::Yes
);
bool hasCachedFile = FileSys.fileExists(cachedFile);
if (hasCachedFile) {
LINFO("Cached file '" << cachedFile << "' used for Speck file '" << _file << "'");
bool hasCachedFile = FileSys.fileExists(cachedFile);
//if (hasCachedFile) {
// LINFO("Cached file '" << cachedFile << "' used for Speck file '" << _file << "'");
bool success = loadCachedFile(cachedFile);
if (success) {
return true;
// success = loadCachedFile(cachedFile);
// if (!success) {
// FileSys.cacheManager()->removeCacheFile(_file);
// // Intentional fall-through to the 'else' computation to generate the cache
// // file for the next run
// }
//}
//else
{
LINFO("Cache for Speck file '" << _file << "' not found");
LINFO("Loading Speck file '" << _file << "'");
success = readSpeckFile();
if (!success) {
return false;
}
LINFO("Saving cache");
success &= saveCachedFile(cachedFile);
}
}
std::string labelFile = _labelFile;
if (!labelFile.empty()) {
std::string cachedFile = FileSys.cacheManager()->cachedFilename(
labelFile,
ghoul::filesystem::CacheManager::Persistent::Yes
);
bool hasCachedFile = FileSys.fileExists(cachedFile);
if (hasCachedFile) {
LINFO("Cached file '" << cachedFile << "' used for Label file '" << labelFile << "'");
success &= loadCachedFile(cachedFile);
if (!success) {
FileSys.cacheManager()->removeCacheFile(labelFile);
// Intentional fall-through to the 'else' computation to generate the cache
// file for the next run
}
}
else {
FileSys.cacheManager()->removeCacheFile(_file);
// Intentional fall-through to the 'else' computation to generate the cache
// file for the next run
LINFO("Cache for Label file '" << labelFile << "' not found");
LINFO("Loading Label file '" << labelFile << "'");
success &= readLabelFile();
if (!success) {
return false;
}
}
}
else {
LINFO("Cache for Speck file '" << _file << "' not found");
}
LINFO("Loading Speck file '" << _file << "'");
bool success = readSpeckFile();
if (!success) {
return false;
}
LINFO("Saving cache");
success = saveCachedFile(cachedFile);
return success;
}
@@ -351,7 +582,7 @@ namespace openspace {
return false;
}
_nValuesPerAstronomicalObject = 0;
int meshIndex = 0;
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
@@ -361,13 +592,16 @@ namespace openspace {
std::streampos position = file.tellg();
std::getline(file, line);
std::cout << "=== Current position: " << file.tellg() << std::endl;
if (file.eof()) {
break;
}
if (line[0] == '#' || line.empty()) {
continue;
}
if (line.substr(0, 7) != "datavar" &&
line.substr(0, 10) != "texturevar" &&
line.substr(0, 7) != "texture")
if (line.substr(0, 4) != "mesh")
{
// we read a line that doesn't belong to the header, so we have to jump back
// before the beginning of the current line
@@ -375,34 +609,161 @@ namespace openspace {
break;
}
if (line.substr(0, 7) == "datavar") {
// datavar lines are structured as follows:
// datavar # description
// where # is the index of the data variable; so if we repeatedly overwrite
// the 'nValues' variable with the latest index, we will end up with the total
// number of values (+3 since X Y Z are not counted in the Speck file index)
if (line.substr(0, 4) == "mesh") {
// mesh lines are structured as follows:
// mesh -t texnum -c colorindex -s style {
// where textnum is the index of the texture;
// colorindex is the index of the color for the mesh
// and style is solid, wire or point (for now we support only wire)
std::stringstream str(line);
RenderingMesh mesh;
mesh.meshIndex = meshIndex;
std::string dummy;
str >> dummy;
str >> _nValuesPerAstronomicalObject;
_nValuesPerAstronomicalObject += 1; // We want the number, but the index is 0 based
str >> dummy; // mesh command
dummy.clear();
str >> dummy; // texture index command?
do {
if (dummy == "-t") {
dummy.clear();
str >> mesh.textureIndex; // texture index
}
else if (dummy == "-c") {
dummy.clear();
str >> mesh.colorIndex; // color index command
}
else if (dummy == "-s") {
dummy.clear();
str >> dummy; // style value command
if (dummy == "solid") {
mesh.style = Solid;
}
else if (dummy == "wire") {
mesh.style = Wire;
}
else if (dummy == "point") {
mesh.style = Point;
}
else {
mesh.style = INVALID;
break;
}
}
dummy.clear();
str >> dummy;
} while (dummy != "{");
std::getline(file, line);
std::stringstream dim(line);
dim >> mesh.numU; // numU
dim >> mesh.numV; // numV
// We can now read the vertices data:
for (int l = 0; l < mesh.numU * mesh.numV; ++l) {
std::getline(file, line);
if (line.substr(0, 1) != "}") {
std::stringstream lineData(line);
for (int i = 0; i < 7; ++i) {
GLfloat value;
lineData >> value;
bool errorReading = lineData.rdstate() & std::ifstream::failbit;
if (!errorReading) {
mesh.vertices.push_back(value);
}
else {
break;
}
}
}
else {
break;
}
}
std::getline(file, line);
if (line.substr(0, 1) == "}") {
_renderingMeshesMap.insert({ meshIndex++, mesh });
}
else {
return false;
}
}
}
return true;
}
bool RenderableDUMeshes::readLabelFile() {
std::string _file = _labelFile;
std::ifstream file(_file);
if (!file.good()) {
LERROR("Failed to open Label file '" << _file << "'");
return false;
}
// The beginning of the speck file has a header that either contains comments
// (signaled by a preceding '#') or information about the structure of the file
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
std::string line = "";
while (true) {
std::streampos position = file.tellg();
std::getline(file, line);
if (line[0] == '#' || line.empty()) {
continue;
}
if (line.substr(0, 9) != "textcolor")
{
// we read a line that doesn't belong to the header, so we have to jump back
// before the beginning of the current line
file.seekg(position);
continue;
}
if (line.substr(0, 9) == "textcolor") {
// textcolor lines are structured as follows:
// textcolor # description
// where # is color text defined in configuration file
std::stringstream str(line);
// TODO: handle cases of labels with different colors
break;
}
}
_nValuesPerAstronomicalObject += 3; // X Y Z are not counted in the Speck file indices
do {
std::vector<float> values(_nValuesPerAstronomicalObject);
std::getline(file, line);
if (line.size() == 0)
continue;
std::stringstream str(line);
for (int i = 0; i < _nValuesPerAstronomicalObject; ++i) {
str >> values[i];
glm::vec3 position;
for (auto j = 0; j < 3; ++j) {
str >> position[j];
}
_fullData.insert(_fullData.end(), values.begin(), values.end());
std::string dummy;
str >> dummy; // text keyword
std::string label;
str >> label;
dummy.clear();
while (str >> dummy) {
label += " " + dummy;
dummy.clear();
}
glm::vec3 transformedPos = glm::vec3(_transformationMatrix * glm::dvec4(position, 1.0));
_labelData.push_back(std::make_pair(transformedPos, label));
} while (!file.eof());
return true;
@@ -464,40 +825,130 @@ namespace openspace {
return false;
}
}
void RenderableDUMeshes::createDataSlice() {
_slicedData.clear();
for (size_t i = 0; i < _fullData.size(); i += _nValuesPerAstronomicalObject) {
glm::dvec3 p = glm::dvec3(_fullData[i + 0], _fullData[i + 1], _fullData[i + 2]);
void RenderableDUMeshes::createMeshes() {
/*
if (_dataIsDirty && _hasSpeckFile) {
LDEBUG("Creating planes");
// Converting untis
if (_unit == Kilometer) {
p *= 1E3;
}
else if (_unit == Parsec) {
p *= PARSEC;
}
else if (_unit == Kiloparsec) {
p *= 1E3 * PARSEC;
}
else if (_unit == Megaparsec) {
p *= 1E6 * PARSEC;
}
else if (_unit == Gigaparsec) {
p *= 1E9 * PARSEC;
}
else if (_unit == GigalightYears) {
p *= 306391534.73091 * PARSEC;
for (int p = 0; p < _fullData.size(); p += _nValuesPerAstronomicalObject) {
glm::vec4 transformedPos = glm::vec4(_transformationMatrix *
glm::dvec4(_fullData[p + 0], _fullData[p + 1], _fullData[p + 2], 1.0));
// Plane vectors u and v
glm::vec4 u = glm::vec4(_transformationMatrix *
glm::dvec4(
_fullData[p + _planeStartingIndexPos + 0],
_fullData[p + _planeStartingIndexPos + 1],
_fullData[p + _planeStartingIndexPos + 2],
1.0));
u /= 2.f;
u.w = 0.0;
glm::vec4 v = glm::vec4(_transformationMatrix *
glm::dvec4(
_fullData[p + _planeStartingIndexPos + 3],
_fullData[p + _planeStartingIndexPos + 4],
_fullData[p + _planeStartingIndexPos + 5],
1.0));
v /= 2.f;
v.w = 0.0;
RenderingPlane plane;
plane.planeIndex = _fullData[p + _textureVariableIndex];
// JCC: Ask Abbott about these points refeering to a non-existing texture.
if (plane.planeIndex == 30) {
//std::cout << "--- Creating planes - index: " << plane.planeIndex << std::endl;
plane.planeIndex = 0;
}
glGenVertexArrays(1, &plane.vao);
glGenBuffers(1, &plane.vbo);
glm::vec4 vertex0 = transformedPos - u - v; // same as 3
glm::vec4 vertex1 = transformedPos + u + v; // same as 5
glm::vec4 vertex2 = transformedPos - u + v;
glm::vec4 vertex4 = transformedPos + u - v;
float scale = 0.0;
switch (_unit) {
case Meter:
scale = 1.0;
break;
case Kilometer:
scale = 1e3;
break;
case Parsec:
scale = PARSEC;
break;
case Kiloparsec:
scale = 1e3 * PARSEC;
break;
case Megaparsec:
scale = 1e6 * PARSEC;
break;
case Gigaparsec:
scale = 1e9 * PARSEC;
break;
case GigalightYears:
scale = 306391534.73091 * PARSEC;
break;
}
vertex0 *= static_cast<float>(scale);
vertex1 *= static_cast<float>(scale);
vertex2 *= static_cast<float>(scale);
vertex4 *= static_cast<float>(scale);
GLfloat vertexData[] = {
// x y z w s t
vertex0.x, vertex0.y, vertex0.z, 1.f, 0.f, 0.f,
vertex1.x, vertex1.y, vertex1.z, 1.f, 1.f, 1.f,
vertex2.x, vertex2.y, vertex2.z, 1.f, 0.f, 1.f,
vertex0.x, vertex0.y, vertex0.z, 1.f, 0.f, 0.f,
vertex4.x, vertex4.y, vertex4.z, 1.f, 1.f, 0.f,
vertex1.x, vertex1.y, vertex1.z, 1.f, 1.f, 1.f,
};
std::memcpy(plane.vertexData, vertexData, sizeof(vertexData));
glBindVertexArray(plane.vao);
glBindBuffer(GL_ARRAY_BUFFER, plane.vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(plane.vertexData), plane.vertexData, GL_STATIC_DRAW);
// in_position
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0,
4,
GL_FLOAT,
GL_FALSE,
sizeof(GLfloat) * 6,
nullptr
);
// texture coords
glEnableVertexAttribArray(1);
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
sizeof(GLfloat) * 6,
reinterpret_cast<GLvoid*>(sizeof(GLfloat) * 4)
);
_renderingPlanesMap.insert({ plane.planeIndex, plane });
}
glm::dvec4 position(p, 1.0);
glBindVertexArray(0);
for (auto j = 0; j < 4; ++j) {
_slicedData.push_back(position[j]);
}
_dataIsDirty = false;
}
}
if (_hasLabel && _labelDataIsDirty) {
_labelDataIsDirty = false;
}
*/
}
} // namespace openspace

View File

@@ -32,8 +32,10 @@
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/vector/vec3property.h>
#include <openspace/properties/vector/vec4property.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <ghoul/font/fontrenderer.h>
namespace ghoul::filesystem {
class File;
@@ -45,7 +47,6 @@ namespace ghoul::opengl {
} // namespace ghoul::opengl
namespace openspace {
namespace documentation { struct Documentation; }
class RenderableDUMeshes : public Renderable {
@@ -76,32 +77,77 @@ namespace openspace {
GigalightYears = 6
};
void createDataSlice();
enum MeshType {
Solid = 0,
Wire = 1,
Point = 2,
INVALID = 9
};
struct RenderingMesh {
int meshIndex;
int colorIndex;
int textureIndex;
// From: Partiview Users Guide
// Brian Abbott
// Hayden Planetarium American Museum of Natural History New York, USA
// "Specifies the dimensions of the mesh."
// "If you wish to draw a line between points, then numU will be 1 while
// numV will equal the number of points to connect.
// If you want a square, 4000×4000 grid with lines every 200 units,
// then numU numU will both equal 21
int numU, numV;
MeshType style;
GLuint vao;
GLuint vbo;
std::vector<GLfloat> vertices;
};
void createMeshes();
void renderMeshes(const RenderData& data, const glm::dmat4& modelViewMatrix,
const glm::dmat4& projectionMatrix);
void renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix,
const glm::vec3& orthoRight, const glm::vec3& orthoUp);
bool loadData();
bool readSpeckFile();
bool readLabelFile();
bool loadCachedFile(const std::string& file);
bool saveCachedFile(const std::string& file) const;
bool _hasSpeckFile;
bool _dataIsDirty;
bool _textColorIsDirty;
bool _hasLabel;
bool _labelDataIsDirty;
int _textMinSize;
properties::FloatProperty _alphaValue;
properties::FloatProperty _scaleFactor;
properties::Vec3Property _pointColor;
//properties::Vec3Property _pointColor;
properties::Vec4Property _textColor;
properties::FloatProperty _textSize;
properties::BoolProperty _drawElements;
//properties::OptionProperty _blendMode;
std::unique_ptr<ghoul::opengl::ProgramObject> _program;
std::unique_ptr<ghoul::fontrendering::FontRenderer> _fontRenderer;
std::shared_ptr<ghoul::fontrendering::Font> _font;
std::string _speckFile;
std::string _labelFile;
Unit _unit;
std::vector<double> _slicedData;
std::vector<float> _fullData;
std::vector<std::pair<glm::vec3, std::string>> _labelData;
int _nValuesPerAstronomicalObject;
GLuint _vao;
GLuint _vbo;
glm::dmat4 _transformationMatrix;
std::unordered_map<int, RenderingMesh> _renderingMeshesMap;
};

View File

@@ -50,7 +50,7 @@ namespace ghoul::opengl {
namespace openspace {
// (x, y, z, w, s, t) * 6 = 36
const int VERTEX_DATA_SIZE = 36;
const int PLANES_VERTEX_DATA_SIZE = 36;
namespace documentation { struct Documentation; }
@@ -86,7 +86,7 @@ namespace openspace {
int planeIndex;
GLuint vao;
GLuint vbo;
GLfloat vertexData[VERTEX_DATA_SIZE];
GLfloat vertexData[PLANES_VERTEX_DATA_SIZE];
};
void createPlanes();