History

Removed heightfield buffer code.

Andrzej Kapolka committed 12 years ago

Commit 479bea11 parent bba042e2 files · +9 −914Browse files

Showing the changes to interface/src/MetavoxelSystem.cpp (1 of 2 files). Show all

Unified · Split

interface/src/MetavoxelSystem.cpp+9−826
@@ -58,11 +58,6 @@ void MetavoxelSystem::init() { · 57 unmodified lines
58 MetavoxelClientManager::init();58 MetavoxelClientManager::init();
59 DefaultMetavoxelRendererImplementation::init();59 DefaultMetavoxelRendererImplementation::init();
60 60
61 _heightfieldBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(
62 new BufferDataAttribute("heightfieldBuffer"));
63 _heightfieldBufferAttribute->setLODThresholdMultiplier(
64 AttributeRegistry::getInstance()->getHeightfieldAttribute()->getLODThresholdMultiplier());
65
66 _voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(61 _voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(
67 new BufferDataAttribute("voxelBuffer"));62 new BufferDataAttribute("voxelBuffer"));
68 _voxelBufferAttribute->setLODThresholdMultiplier(63 _voxelBufferAttribute->setLODThresholdMultiplier(
@@ -375,12 +370,6 @@ void MetavoxelSystem::renderVoxelCursor(const glm::vec3& position, float radius) · 306 unmodified lines
375 glDepthFunc(GL_LESS);370 glDepthFunc(GL_LESS);
376}371}
377 372
378void MetavoxelSystem::deleteTextures(int heightID, int colorID, int textureID) {
379 glDeleteTextures(1, (GLuint*)&heightID);
380 glDeleteTextures(1, (GLuint*)&colorID);
381 glDeleteTextures(1, (GLuint*)&textureID);
382}
383
384class MaterialEditApplier : public SignalHandler {373class MaterialEditApplier : public SignalHandler {
385public:374public:
386 375
@@ -670,357 +659,12 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) { · 283 unmodified lines
670BufferData::~BufferData() {659BufferData::~BufferData() {
671}660}
672 661
673const int HeightfieldBuffer::HEIGHT_BORDER = 1;
674const int HeightfieldBuffer::SHARED_EDGE = 1;
675const int HeightfieldBuffer::HEIGHT_EXTENSION = 2 * HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE;
676
677HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale,
678 const QByteArray& height, const QByteArray& color, const QByteArray& material,
679 const QVector<SharedObjectPointer>& materials) :
680 _translation(translation),
681 _scale(scale),
682 _heightBounds(translation, translation + glm::vec3(scale, scale, scale)),
683 _colorBounds(_heightBounds),
684 _materialBounds(_heightBounds),
685 _height(height),
686 _color(color),
687 _material(material),
688 _materials(materials),
689 _heightTextureID(0),
690 _colorTextureID(0),
691 _materialTextureID(0),
692 _heightSize(glm::sqrt((float)height.size())),
693 _heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)),
694 _colorSize(glm::sqrt((float)color.size() / DataBlock::COLOR_BYTES)),
695 _colorIncrement(scale / (_colorSize - SHARED_EDGE)),
696 _materialSize(glm::sqrt((float)material.size())),
697 _materialIncrement(scale / (_materialSize - SHARED_EDGE)) {
698
699 _heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER;
700 _heightBounds.minimum.z -= _heightIncrement * HEIGHT_BORDER;
701 _heightBounds.maximum.x += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER);
702 _heightBounds.maximum.z += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER);
703
704 _colorBounds.maximum.x += _colorIncrement * SHARED_EDGE;
705 _colorBounds.maximum.z += _colorIncrement * SHARED_EDGE;
706
707 _materialBounds.maximum.x += _materialIncrement * SHARED_EDGE;
708 _materialBounds.maximum.z += _materialIncrement * SHARED_EDGE;
709}
710
711HeightfieldBuffer::~HeightfieldBuffer() {
712 // the textures have to be deleted on the main thread (for its opengl context)
713 if (QThread::currentThread() != Application::getInstance()->thread()) {
714 QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteTextures",
715 Q_ARG(int, _heightTextureID), Q_ARG(int, _colorTextureID), Q_ARG(int, _materialTextureID));
716 } else {
717 glDeleteTextures(1, &_heightTextureID);
718 glDeleteTextures(1, &_colorTextureID);
719 glDeleteTextures(1, &_materialTextureID);
720 }
721}
722
723QByteArray HeightfieldBuffer::getUnextendedHeight() const {
724 int srcSize = glm::sqrt(float(_height.size()));
725 int destSize = srcSize - 3;
726 QByteArray unextended(destSize * destSize, 0);
727 const char* src = _height.constData() + srcSize + 1;
728 char* dest = unextended.data();
729 for (int z = 0; z < destSize; z++, src += srcSize, dest += destSize) {
730 memcpy(dest, src, destSize);
731 }
732 return unextended;
733}
734
735QByteArray HeightfieldBuffer::getUnextendedColor(int x, int y) const {
736 int unextendedSize = _heightSize - HEIGHT_EXTENSION;
737 QByteArray unextended(unextendedSize * unextendedSize * DataBlock::COLOR_BYTES, 0);
738 char* dest = unextended.data();
739 const char* src = _color.constData() + (y * _colorSize + x) * unextendedSize * DataBlock::COLOR_BYTES;
740 for (int z = 0; z < unextendedSize; z++, dest += unextendedSize * DataBlock::COLOR_BYTES,
741 src += _colorSize * DataBlock::COLOR_BYTES) {
742 memcpy(dest, src, unextendedSize * DataBlock::COLOR_BYTES);
743 }
744 return unextended;
745}
746
747class HeightfieldPoint {
748public:
749 glm::vec2 textureCoord;
750 glm::vec3 vertex;
751};
752
753const int SPLAT_COUNT = 4;662const int SPLAT_COUNT = 4;
754const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 };663const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 };
755 664
756static const int EIGHT_BIT_MAXIMUM = 255;665static const int EIGHT_BIT_MAXIMUM = 255;
757static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM;666static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM;
758 667
759void HeightfieldBuffer::render(bool cursor) {
760 // initialize textures, etc. on first render
761 if (_heightTextureID == 0) {
762 glGenTextures(1, &_heightTextureID);
763 glBindTexture(GL_TEXTURE_2D, _heightTextureID);
764 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
765 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
766 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
767 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
768 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
769 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, _heightSize, _heightSize, 0,
770 GL_LUMINANCE, GL_UNSIGNED_BYTE, _height.constData());
771
772 glGenTextures(1, &_colorTextureID);
773 glBindTexture(GL_TEXTURE_2D, _colorTextureID);
774 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
775 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
776 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
777 if (_color.isEmpty()) {
778 const quint8 WHITE_COLOR[] = { 255, 255, 255 };
779 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, WHITE_COLOR);
780
781 } else {
782 int colorSize = glm::sqrt(float(_color.size() / DataBlock::COLOR_BYTES));
783 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, colorSize, colorSize, 0, GL_RGB, GL_UNSIGNED_BYTE, _color.constData());
784 }
785
786 if (!_material.isEmpty()) {
787 glGenTextures(1, &_materialTextureID);
788 glBindTexture(GL_TEXTURE_2D, _materialTextureID);
789 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
790 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
791 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
792 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
793 int materialSize = glm::sqrt(float(_material.size()));
794 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, materialSize, materialSize, 0,
795 GL_LUMINANCE, GL_UNSIGNED_BYTE, _material.constData());
796
797 _networkTextures.resize(_materials.size());
798 for (int i = 0; i < _materials.size(); i++) {
799 const SharedObjectPointer material = _materials.at(i);
800 if (material) {
801 _networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture(
802 static_cast<MaterialObject*>(material.data())->getDiffuse(), SPLAT_TEXTURE);
803 }
804 }
805 }
806 }
807 // create the buffer objects lazily
808 int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER;
809 int vertexCount = _heightSize * _heightSize;
810 int rows = _heightSize - 1;
811 int indexCount = rows * rows * 3 * 2;
812 BufferPair& bufferPair = _bufferPairs[_heightSize];
813 if (!bufferPair.first.isCreated()) {
814 QVector<HeightfieldPoint> vertices(vertexCount);
815 HeightfieldPoint* point = vertices.data();
816
817 float vertexStep = 1.0f / (innerSize - 1);
818 float z = -vertexStep;
819 float textureStep = 1.0f / _heightSize;
820 float t = textureStep / 2.0f;
821 for (int i = 0; i < _heightSize; i++, z += vertexStep, t += textureStep) {
822 float x = -vertexStep;
823 float s = textureStep / 2.0f;
824 const float SKIRT_LENGTH = 0.25f;
825 float baseY = (i == 0 || i == _heightSize - 1) ? -SKIRT_LENGTH : 0.0f;
826 for (int j = 0; j < _heightSize; j++, point++, x += vertexStep, s += textureStep) {
827 point->vertex = glm::vec3(x, (j == 0 || j == _heightSize - 1) ? -SKIRT_LENGTH : baseY, z);
828 point->textureCoord = glm::vec2(s, t);
829 }
830 }
831
832 bufferPair.first.setUsagePattern(QOpenGLBuffer::StaticDraw);
833 bufferPair.first.create();
834 bufferPair.first.bind();
835 bufferPair.first.allocate(vertices.constData(), vertexCount * sizeof(HeightfieldPoint));
836
837 QVector<int> indices(indexCount);
838 int* index = indices.data();
839 for (int i = 0; i < rows; i++) {
840 int lineIndex = i * _heightSize;
841 int nextLineIndex = (i + 1) * _heightSize;
842 for (int j = 0; j < rows; j++) {
843 *index++ = lineIndex + j;
844 *index++ = nextLineIndex + j;
845 *index++ = nextLineIndex + j + 1;
846
847 *index++ = nextLineIndex + j + 1;
848 *index++ = lineIndex + j + 1;
849 *index++ = lineIndex + j;
850 }
851 }
852
853 bufferPair.second = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
854 bufferPair.second.create();
855 bufferPair.second.bind();
856 bufferPair.second.allocate(indices.constData(), indexCount * sizeof(int));
857
858 } else {
859 bufferPair.first.bind();
860 bufferPair.second.bind();
861 }
862
863 HeightfieldPoint* point = 0;
864 glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex);
865 glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord);
866
867 glPushMatrix();
868 glTranslatef(_translation.x, _translation.y, _translation.z);
869 glScalef(_scale, _scale, _scale);
870
871 glBindTexture(GL_TEXTURE_2D, _heightTextureID);
872
873 if (cursor) {
874 glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
875
876 } else if (!_materials.isEmpty()) {
877 DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue(
878 DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / _heightSize);
879 DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue(
880 DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), (float)_heightSize / innerSize);
881 glActiveTexture(GL_TEXTURE1);
882 glBindTexture(GL_TEXTURE_2D, _colorTextureID);
883
884 glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
885
886 Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
887
888 glDepthFunc(GL_LEQUAL);
889 glDepthMask(false);
890 glEnable(GL_BLEND);
891 glDisable(GL_ALPHA_TEST);
892 glEnable(GL_POLYGON_OFFSET_FILL);
893 glPolygonOffset(-1.0f, -1.0f);
894
895 DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().bind();
896 const DefaultMetavoxelRendererImplementation::SplatLocations& locations =
897 DefaultMetavoxelRendererImplementation::getSplatHeightfieldLocations();
898 DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
899 locations.heightScale, 1.0f / _heightSize);
900 DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
901 locations.textureScale, (float)_heightSize / innerSize);
902 DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
903 locations.splatTextureOffset, _translation.x / _scale, _translation.z / _scale);
904
905 glBindTexture(GL_TEXTURE_2D, _materialTextureID);
906
907 for (int i = 0; i < _materials.size(); i += SPLAT_COUNT) {
908 QVector4D scalesS, scalesT;
909
910 for (int j = 0; j < SPLAT_COUNT; j++) {
911 glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[j]);
912 int index = i + j;
913 if (index < _networkTextures.size()) {
914 const NetworkTexturePointer& texture = _networkTextures.at(index);
915 if (texture) {
916 MaterialObject* material = static_cast<MaterialObject*>(_materials.at(index).data());
917 scalesS[j] = _scale / material->getScaleS();
918 scalesT[j] = _scale / material->getScaleT();
919 glBindTexture(GL_TEXTURE_2D, texture->getID());
920 } else {
921 glBindTexture(GL_TEXTURE_2D, 0);
922 }
923 } else {
924 glBindTexture(GL_TEXTURE_2D, 0);
925 }
926 }
927 const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL;
928 DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
929 locations.splatTextureScalesS, scalesS);
930 DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
931 locations.splatTextureScalesT, scalesT);
932 DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
933 locations.textureValueMinima,
934 (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
935 (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP);
936 DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
937 locations.textureValueMaxima,
938 (i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
939 (i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP);
940 glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
941 }
942
943 for (int i = 0; i < SPLAT_COUNT; i++) {
944 glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);
945 glBindTexture(GL_TEXTURE_2D, 0);
946 }
947
948 glActiveTexture(GL_TEXTURE1);
949 glBindTexture(GL_TEXTURE_2D, 0);
950
951 glActiveTexture(GL_TEXTURE0);
952
953 glDisable(GL_POLYGON_OFFSET_FILL);
954 glEnable(GL_ALPHA_TEST);
955 glDisable(GL_BLEND);
956 glDepthMask(true);
957 glDepthFunc(GL_LESS);
958
959 Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
960
961 DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind();
962
963 } else {
964 DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue(
965 DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / _heightSize);
966 DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue(
967 DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), (float)_heightSize / innerSize);
968 glActiveTexture(GL_TEXTURE1);
969 glBindTexture(GL_TEXTURE_2D, _colorTextureID);
970
971 glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
972
973 glBindTexture(GL_TEXTURE_2D, 0);
974 glActiveTexture(GL_TEXTURE0);
975 }
976
977 glBindTexture(GL_TEXTURE_2D, 0);
978
979 glPopMatrix();
980
981 bufferPair.first.release();
982 bufferPair.second.release();
983}
984
985QHash<int, HeightfieldBuffer::BufferPair> HeightfieldBuffer::_bufferPairs;
986
987void HeightfieldPreview::render(const glm::vec3& translation, float scale) const {
988 Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
989
990 glDisable(GL_BLEND);
991 glEnable(GL_CULL_FACE);
992 glEnable(GL_ALPHA_TEST);
993 glAlphaFunc(GL_EQUAL, 0.0f);
994
995 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
996
997 glEnableClientState(GL_VERTEX_ARRAY);
998 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
999
1000 DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind();
1001
1002 glPushMatrix();
1003 glTranslatef(translation.x, translation.y, translation.z);
1004 glScalef(scale, scale, scale);
1005
1006 foreach (const BufferDataPointer& buffer, _buffers) {
1007 buffer->render();
1008 }
1009
1010 glPopMatrix();
1011
1012 DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().release();
1013
1014 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1015 glDisableClientState(GL_VERTEX_ARRAY);
1016
1017 glDisable(GL_ALPHA_TEST);
1018 glDisable(GL_CULL_FACE);
1019 glEnable(GL_BLEND);
1020
1021 Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
1022}
1023
1024void VoxelPoint::setNormal(const glm::vec3& normal) {668void VoxelPoint::setNormal(const glm::vec3& normal) {
1025 this->normal[0] = (char)(normal.x * 127.0f);669 this->normal[0] = (char)(normal.x * 127.0f);
1026 this->normal[1] = (char)(normal.y * 127.0f);670 this->normal[1] = (char)(normal.y * 127.0f);
@@ -1344,446 +988,6 @@ void DefaultMetavoxelRendererImplementation::init() { · 317 unmodified lines
1344DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() {988DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() {
1345}989}
1346 990
1347class HeightfieldFetchVisitor : public MetavoxelVisitor {
1348public:
1349
1350 HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections);
1351
1352 void init(HeightfieldBuffer* buffer);
1353
1354 virtual int visit(MetavoxelInfo& info);
1355 virtual bool postVisit(MetavoxelInfo& info);
1356
1357private:
1358
1359 const QVector<Box>& _intersections;
1360 HeightfieldBuffer* _buffer;
1361
1362 QVector<int> _depthFlags;
1363};
1364
1365enum DepthFlags { HEIGHT_FLAG = 0x01, COLOR_FLAG = 0x02, MATERIAL_FLAG = 0x04 };
1366
1367HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) :
1368 MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<
1369 AttributeRegistry::getInstance()->getHeightfieldColorAttribute() <<
1370 AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute(), QVector<AttributePointer>(), lod),
1371 _intersections(intersections) {
1372}
1373
1374void HeightfieldFetchVisitor::init(HeightfieldBuffer* buffer) {
1375 _buffer = buffer;
1376}
1377
1378int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {
1379 if (!info.getBounds().intersects(_buffer->getHeightBounds())) {
1380 return STOP_RECURSION;
1381 }
1382 if (_depthFlags.size() > _depth) {
1383 _depthFlags[_depth] = 0;
1384 } else {
1385 _depthFlags.append(0);
1386 }
1387 if (!info.isLeaf) {
1388 return DEFAULT_ORDER;
1389 }
1390 postVisit(info);
1391 return STOP_RECURSION;
1392}
1393
1394bool HeightfieldFetchVisitor::postVisit(MetavoxelInfo& info) {
1395 HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
1396 int flags = _depthFlags.at(_depth);
1397 if (height) {
1398 // to handle borders correctly, make sure we only sample nodes with resolution <= ours
1399 int heightSize = glm::sqrt((float)height->getContents().size());
1400 float heightIncrement = info.size / heightSize;
1401 if (heightIncrement < _buffer->getHeightIncrement() || (flags & HEIGHT_FLAG)) {
1402 height.reset();
1403 } else {
1404 flags |= HEIGHT_FLAG;
1405 }
1406 }
1407 HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
1408 if (color) {
1409 int colorSize = glm::sqrt((float)color->getContents().size() / DataBlock::COLOR_BYTES);
1410 float colorIncrement = info.size / colorSize;
1411 if (colorIncrement < _buffer->getColorIncrement() || (flags & COLOR_FLAG)) {
1412 color.reset();
1413 } else {
1414 flags |= COLOR_FLAG;
1415 }
1416 }
1417 HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>();
1418 if (material) {
1419 int materialSize = glm::sqrt((float)material->getContents().size());
1420 float materialIncrement = info.size / materialSize;
1421 if (materialIncrement < _buffer->getMaterialIncrement() || (flags & MATERIAL_FLAG)) {
1422 material.reset();
1423 } else {
1424 flags |= MATERIAL_FLAG;
1425 }
1426 }
1427 if (_depth > 0) {
1428 _depthFlags[_depth - 1] |= flags;
1429 }
1430 if (!(height || color || material)) {
1431 return false;
1432 }
1433 Box bounds = info.getBounds();
1434 foreach (const Box& intersection, _intersections) {
1435 Box overlap = intersection.getIntersection(bounds);
1436 if (overlap.isEmpty()) {
1437 continue;
1438 }
1439 if (height) {
1440 float heightIncrement = _buffer->getHeightIncrement();
1441 const Box& heightBounds = _buffer->getHeightBounds();
1442 int destX = (overlap.minimum.x - heightBounds.minimum.x) / heightIncrement;
1443 int destY = (overlap.minimum.z - heightBounds.minimum.z) / heightIncrement;
1444 int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / heightIncrement);
1445 int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / heightIncrement);
1446 int heightSize = _buffer->getHeightSize();
1447 char* dest = _buffer->getHeight().data() + destY * heightSize + destX;
1448
1449 const QByteArray& srcHeight = height->getContents();
1450 int srcSize = glm::sqrt((float)srcHeight.size());
1451 float srcIncrement = info.size / srcSize;
1452
1453 if (info.size == _buffer->getScale() && srcSize == (heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)) {
1454 // easy case: same resolution
1455 int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
1456 int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
1457
1458 const char* src = srcHeight.constData() + srcY * srcSize + srcX;
1459 for (int y = 0; y < destHeight; y++, src += srcSize, dest += heightSize) {
1460 memcpy(dest, src, destWidth);
1461 }
1462 } else {
1463 // more difficult: different resolutions
1464 float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
1465 float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
1466 float srcAdvance = heightIncrement / srcIncrement;
1467 int shift = 0;
1468 float size = _buffer->getScale();
1469 while (size < info.size) {
1470 shift++;
1471 size *= 2.0f;
1472 }
1473 int subtract = (_buffer->getTranslation().y - info.minimum.y) * EIGHT_BIT_MAXIMUM / _buffer->getScale();
1474 for (int y = 0; y < destHeight; y++, dest += heightSize, srcY += srcAdvance) {
1475 const uchar* src = (const uchar*)srcHeight.constData() + (int)srcY * srcSize;
1476 float lineSrcX = srcX;
1477 for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) {
1478 *lineDest = qMin(qMax(0, (src[(int)lineSrcX] << shift) - subtract), EIGHT_BIT_MAXIMUM);
1479 }
1480 }
1481 }
1482 }
1483 if (color) {
1484 const Box& colorBounds = _buffer->getColorBounds();
1485 overlap = colorBounds.getIntersection(overlap);
1486 float colorIncrement = _buffer->getColorIncrement();
1487 int destX = (overlap.minimum.x - colorBounds.minimum.x) / colorIncrement;
1488 int destY = (overlap.minimum.z - colorBounds.minimum.z) / colorIncrement;
1489 int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / colorIncrement);
1490 int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / colorIncrement);
1491 int colorSize = _buffer->getColorSize();
1492 char* dest = _buffer->getColor().data() + (destY * colorSize + destX) * DataBlock::COLOR_BYTES;
1493 int destStride = colorSize * DataBlock::COLOR_BYTES;
1494 int destBytes = destWidth * DataBlock::COLOR_BYTES;
1495
1496 const QByteArray& srcColor = color->getContents();
1497 int srcSize = glm::sqrt(float(srcColor.size() / DataBlock::COLOR_BYTES));
1498 int srcStride = srcSize * DataBlock::COLOR_BYTES;
1499 float srcIncrement = info.size / srcSize;
1500
1501 if (srcIncrement == colorIncrement) {
1502 // easy case: same resolution
1503 int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
1504 int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
1505
1506 const char* src = srcColor.constData() + (srcY * srcSize + srcX) * DataBlock::COLOR_BYTES;
1507 for (int y = 0; y < destHeight; y++, src += srcStride, dest += destStride) {
1508 memcpy(dest, src, destBytes);
1509 }
1510 } else {
1511 // more difficult: different resolutions
1512 float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
1513 float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
1514 float srcAdvance = colorIncrement / srcIncrement;
1515 for (int y = 0; y < destHeight; y++, dest += destStride, srcY += srcAdvance) {
1516 const char* src = srcColor.constData() + (int)srcY * srcStride;
1517 float lineSrcX = srcX;
1518 for (char* lineDest = dest, *end = dest + destBytes; lineDest != end; lineDest += DataBlock::COLOR_BYTES,
1519 lineSrcX += srcAdvance) {
1520 const char* lineSrc = src + (int)lineSrcX * DataBlock::COLOR_BYTES;
1521 lineDest[0] = lineSrc[0];
1522 lineDest[1] = lineSrc[1];
1523 lineDest[2] = lineSrc[2];
1524 }
1525 }
1526 }
1527 }
1528 if (material) {
1529 const Box& materialBounds = _buffer->getMaterialBounds();
1530 overlap = materialBounds.getIntersection(overlap);
1531 float materialIncrement = _buffer->getMaterialIncrement();
1532 int destX = (overlap.minimum.x - materialBounds.minimum.x) / materialIncrement;
1533 int destY = (overlap.minimum.z - materialBounds.minimum.z) / materialIncrement;
1534 int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / materialIncrement);
1535 int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / materialIncrement);
1536 int materialSize = _buffer->getMaterialSize();
1537 char* dest = _buffer->getMaterial().data() + destY * materialSize + destX;
1538
1539 const QByteArray& srcMaterial = material->getContents();
1540 const QVector<SharedObjectPointer> srcMaterials = material->getMaterials();
1541 int srcSize = glm::sqrt((float)srcMaterial.size());
1542 float srcIncrement = info.size / srcSize;
1543 QHash<int, int> materialMappings;
1544
1545 if (srcIncrement == materialIncrement) {
1546 // easy case: same resolution
1547 int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
1548 int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
1549
1550 const uchar* src = (const uchar*)srcMaterial.constData() + srcY * srcSize + srcX;
1551 for (int y = 0; y < destHeight; y++, src += srcSize, dest += materialSize) {
1552 const uchar* lineSrc = src;
1553 for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrc++) {
1554 int value = *lineSrc;
1555 if (value != 0) {
1556 int& mapping = materialMappings[value];
1557 if (mapping == 0) {
1558 mapping = getMaterialIndex(material->getMaterials().at(value - 1),
1559 _buffer->getMaterials(), _buffer->getMaterial());
1560 }
1561 value = mapping;
1562 }
1563 *lineDest = value;
1564 }
1565 }
1566 } else {
1567 // more difficult: different resolutions
1568 float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
1569 float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
1570 float srcAdvance = materialIncrement / srcIncrement;
1571 for (int y = 0; y < destHeight; y++, dest += materialSize, srcY += srcAdvance) {
1572 const uchar* src = (const uchar*)srcMaterial.constData() + (int)srcY * srcSize;
1573 float lineSrcX = srcX;
1574 for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) {
1575 int value = src[(int)lineSrcX];
1576 if (value != 0) {
1577 int& mapping = materialMappings[value];
1578 if (mapping == 0) {
1579 mapping = getMaterialIndex(material->getMaterials().at(value - 1),
1580 _buffer->getMaterials(), _buffer->getMaterial());
1581 }
1582 value = mapping;
1583 }
1584 *lineDest = value;
1585 }
1586 }
1587 }
1588 clearUnusedMaterials(_buffer->getMaterials(), _buffer->getMaterial());
1589 }
1590 }
1591 return false;
1592}
1593
1594class HeightfieldRegionVisitor : public MetavoxelVisitor {
1595public:
1596
1597 QVector<Box> regions;
1598 Box regionBounds;
1599
1600 HeightfieldRegionVisitor(const MetavoxelLOD& lod);
1601
1602 virtual int visit(MetavoxelInfo& info);
1603 virtual bool postVisit(MetavoxelInfo& info);
1604
1605private:
1606
1607 void addRegion(const Box& unextended, const Box& extended);
1608
1609 class DepthInfo {
1610 public:
1611 float minimumColorIncrement;
1612 float minimumMaterialIncrement;
1613
1614 DepthInfo() : minimumColorIncrement(FLT_MAX), minimumMaterialIncrement(FLT_MAX) { }
1615 };
1616
1617 QVector<DepthInfo> _depthInfo;
1618
1619 QVector<Box> _intersections;
1620 HeightfieldFetchVisitor _fetchVisitor;
1621};
1622
1623HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) :
1624 MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<
1625 AttributeRegistry::getInstance()->getHeightfieldColorAttribute() <<
1626 AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute() <<
1627 Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() <<
1628 Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod),
1629 regionBounds(glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX), glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)),
1630 _fetchVisitor(lod, _intersections) {
1631}
1632
1633int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {
1634 DepthInfo depthInfo;
1635 HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
1636 if (color) {
1637 int colorSize = glm::sqrt((float)color->getContents().size() / DataBlock::COLOR_BYTES);
1638 depthInfo.minimumColorIncrement = info.size / colorSize;
1639 }
1640 HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>();
1641 if (material) {
1642 int materialSize = glm::sqrt((float)material->getContents().size());
1643 depthInfo.minimumMaterialIncrement = info.size / materialSize;
1644 }
1645 if (_depth < _depthInfo.size()) {
1646 _depthInfo[_depth] = depthInfo;
1647 } else {
1648 _depthInfo.append(depthInfo);
1649 }
1650 if (!info.isLeaf) {
1651 return _visitations.at(_depth).isInputLeaf(0) ? (DEFAULT_ORDER | ALL_NODES_REST) : DEFAULT_ORDER;
1652 }
1653 postVisit(info);
1654 return STOP_RECURSION;
1655}
1656
1657bool HeightfieldRegionVisitor::postVisit(MetavoxelInfo& info) {
1658 const DepthInfo& depthInfo = _depthInfo.at(_depth);
1659 if (_depth > 0) {
1660 DepthInfo& parentDepthInfo = _depthInfo[_depth - 1];
1661 parentDepthInfo.minimumColorIncrement = qMin(parentDepthInfo.minimumColorIncrement, depthInfo.minimumColorIncrement);
1662 parentDepthInfo.minimumMaterialIncrement = qMin(parentDepthInfo.minimumMaterialIncrement,
1663 depthInfo.minimumMaterialIncrement);
1664 }
1665 if (_visitations.at(_depth).isInputLeaf(0)) {
1666 HeightfieldBuffer* buffer = NULL;
1667 HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
1668 if (height) {
1669 int heightSize = glm::sqrt((float)height->getContents().size());
1670 int extendedHeightSize = heightSize + HeightfieldBuffer::HEIGHT_EXTENSION;
1671 int heightContentsSize = extendedHeightSize * extendedHeightSize;
1672 float minimumColorIncrement = depthInfo.minimumColorIncrement;
1673 float minimumMaterialIncrement = depthInfo.minimumMaterialIncrement;
1674 for (int i = _depth - 1; i >= 0 && qMax(minimumColorIncrement, minimumMaterialIncrement) == FLT_MAX; i--) {
1675 const DepthInfo& ancestorDepthInfo = _depthInfo.at(i);
1676 minimumColorIncrement = qMin(minimumColorIncrement, ancestorDepthInfo.minimumColorIncrement);
1677 minimumMaterialIncrement = qMin(minimumMaterialIncrement, ancestorDepthInfo.minimumMaterialIncrement);
1678 }
1679 int colorContentsSize = 0;
1680 if (minimumColorIncrement != FLT_MAX) {
1681 int colorSize = (int)glm::round(info.size / minimumColorIncrement) + HeightfieldBuffer::SHARED_EDGE;
1682 colorContentsSize = colorSize * colorSize * DataBlock::COLOR_BYTES;
1683 }
1684 int materialContentsSize = 0;
1685 if (minimumMaterialIncrement != FLT_MAX) {
1686 int materialSize = (int)glm::round(info.size / minimumMaterialIncrement) + HeightfieldBuffer::SHARED_EDGE;
1687 materialContentsSize = materialSize * materialSize;
1688 }
1689 const HeightfieldBuffer* existingBuffer = static_cast<const HeightfieldBuffer*>(
1690 info.inputValues.at(3).getInlineValue<BufferDataPointer>().data());
1691 Box bounds = info.getBounds();
1692 if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize &&
1693 existingBuffer->getColor().size() == colorContentsSize &&
1694 existingBuffer->getMaterial().size() == materialContentsSize) {
1695 // we already have a buffer of the correct resolution
1696 addRegion(bounds, existingBuffer->getHeightBounds());
1697 buffer = new HeightfieldBuffer(info.minimum, info.size, existingBuffer->getHeight(),
1698 existingBuffer->getColor(), existingBuffer->getMaterial(), existingBuffer->getMaterials());
1699
1700 } else {
1701 // we must create a new buffer and update its borders
1702 buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0),
1703 QByteArray(colorContentsSize, 0), QByteArray(materialContentsSize, 0));
1704 const Box& heightBounds = buffer->getHeightBounds();
1705 addRegion(bounds, heightBounds);
1706
1707 _intersections.clear();
1708 _intersections.append(Box(heightBounds.minimum,
1709 glm::vec3(bounds.maximum.x, heightBounds.maximum.y, bounds.minimum.z)));
1710 _intersections.append(Box(glm::vec3(bounds.maximum.x, heightBounds.minimum.y, heightBounds.minimum.z),
1711 glm::vec3(heightBounds.maximum.x, heightBounds.maximum.y, bounds.maximum.z)));
1712 _intersections.append(Box(glm::vec3(bounds.minimum.x, heightBounds.minimum.y, bounds.maximum.z),
1713 heightBounds.maximum));
1714 _intersections.append(Box(glm::vec3(heightBounds.minimum.x, heightBounds.minimum.y, bounds.minimum.z),
1715 glm::vec3(bounds.minimum.x, heightBounds.maximum.y, heightBounds.maximum.z)));
1716
1717 _fetchVisitor.init(buffer);
1718 _data->guide(_fetchVisitor);
1719 }
1720 }
1721 BufferDataPointer pointer(buffer);
1722 info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));
1723 }
1724 return true;
1725}
1726
1727void HeightfieldRegionVisitor::addRegion(const Box& unextended, const Box& extended) {
1728 regions.append(unextended);
1729 regionBounds.add(extended);
1730}
1731
1732class HeightfieldUpdateVisitor : public MetavoxelVisitor {
1733public:
1734
1735 HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions, const Box& regionBounds);
1736
1737 virtual int visit(MetavoxelInfo& info);
1738
1739private:
1740
1741 const QVector<Box>& _regions;
1742 const Box& _regionBounds;
1743 QVector<Box> _intersections;
1744 HeightfieldFetchVisitor _fetchVisitor;
1745};
1746
1747HeightfieldUpdateVisitor::HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions,
1748 const Box& regionBounds) :
1749 MetavoxelVisitor(QVector<AttributePointer>() <<
1750 Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() <<
1751 Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod),
1752 _regions(regions),
1753 _regionBounds(regionBounds),
1754 _fetchVisitor(lod, _intersections) {
1755}
1756
1757int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) {
1758 if (!info.getBounds().intersects(_regionBounds)) {
1759 return STOP_RECURSION;
1760 }
1761 if (!info.isLeaf) {
1762 return DEFAULT_ORDER;
1763 }
1764 const HeightfieldBuffer* buffer = static_cast<const HeightfieldBuffer*>(
1765 info.inputValues.at(0).getInlineValue<BufferDataPointer>().data());
1766 if (!buffer) {
1767 return STOP_RECURSION;
1768 }
1769 _intersections.clear();
1770 foreach (const Box& region, _regions) {
1771 if (region.intersects(buffer->getHeightBounds())) {
1772 _intersections.append(region.getIntersection(buffer->getHeightBounds()));
1773 }
1774 }
1775 if (_intersections.isEmpty()) {
1776 return STOP_RECURSION;
1777 }
1778 HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size,
1779 buffer->getHeight(), buffer->getColor(), buffer->getMaterial(), buffer->getMaterials());
1780 _fetchVisitor.init(newBuffer);
1781 _data->guide(_fetchVisitor);
1782 BufferDataPointer pointer(newBuffer);
1783 info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));
1784 return STOP_RECURSION;
1785}
1786
1787class VoxelAugmentVisitor : public MetavoxelVisitor {991class VoxelAugmentVisitor : public MetavoxelVisitor {
1788public:992public:
1789 993
@@ -2392,27 +1596,13 @@ void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const · 602 unmodified lines
2392 while (expandedPrevious.getSize() < data.getSize()) {1596 while (expandedPrevious.getSize() < data.getSize()) {
2393 expandedPrevious.expand();1597 expandedPrevious.expand();
2394 }1598 }
2395 const AttributePointer& heightfieldBufferAttribute =
2396 Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute();
2397 MetavoxelNode* root = expandedPrevious.getRoot(heightfieldBufferAttribute);
2398 if (root) {
2399 data.setRoot(heightfieldBufferAttribute, root);
2400 root->incrementReferenceCount();
2401 }
2402 const AttributePointer& voxelBufferAttribute =1599 const AttributePointer& voxelBufferAttribute =
2403 Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute();1600 Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute();
2404 root = expandedPrevious.getRoot(voxelBufferAttribute);1601 MetavoxelNode* root = expandedPrevious.getRoot(voxelBufferAttribute);
2405 if (root) {1602 if (root) {
2406 data.setRoot(voxelBufferAttribute, root);1603 data.setRoot(voxelBufferAttribute, root);
2407 root->incrementReferenceCount();1604 root->incrementReferenceCount();
2408 }1605 }
2409 HeightfieldRegionVisitor heightfieldRegionVisitor(lod);
2410 data.guideToDifferent(expandedPrevious, heightfieldRegionVisitor);
2411
2412 HeightfieldUpdateVisitor heightfieldUpdateVisitor(lod, heightfieldRegionVisitor.regions,
2413 heightfieldRegionVisitor.regionBounds);
2414 data.guide(heightfieldUpdateVisitor);
2415
2416 VoxelAugmentVisitor voxelAugmentVisitor(lod);1606 VoxelAugmentVisitor voxelAugmentVisitor(lod);
2417 data.guideToDifferent(expandedPrevious, voxelAugmentVisitor);1607 data.guideToDifferent(expandedPrevious, voxelAugmentVisitor);
2418}1608}
@@ -2535,19 +1725,6 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox · 116 unmodified lines
2535 1725
2536 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);1726 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
2537 1727
2538 if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeightfields)) {
2539 _baseHeightfieldProgram.bind();
2540
2541 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2542
2543 BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute());
2544 data.guide(heightfieldRenderVisitor);
2545
2546 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2547
2548 _baseHeightfieldProgram.release();
2549 }
2550
2551 if (Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) {1728 if (Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) {
2552 glEnableClientState(GL_COLOR_ARRAY);1729 glEnableClientState(GL_COLOR_ARRAY);
2553 glEnableClientState(GL_NORMAL_ARRAY);1730 glEnableClientState(GL_NORMAL_ARRAY);
@@ -2756,6 +1933,12 @@ void HeightfieldRenderer::init(Spanner* spanner) { · 202 unmodified lines
2756 connect(heightfield, &Heightfield::materialChanged, this, &HeightfieldRenderer::applyMaterial);1933 connect(heightfield, &Heightfield::materialChanged, this, &HeightfieldRenderer::applyMaterial);
2757}1934}
2758 1935
1936class HeightfieldPoint {
1937public:
1938 glm::vec3 vertex;
1939 glm::vec2 textureCoord;
1940};
1941
2759void HeightfieldRenderer::render(bool cursor) {1942void HeightfieldRenderer::render(bool cursor) {
2760 // create the buffer objects lazily1943 // create the buffer objects lazily
2761 Heightfield* heightfield = static_cast<Heightfield*>(_spanner);1944 Heightfield* heightfield = static_cast<Heightfield*>(_spanner);
@@ -2765,8 +1948,8 @@ void HeightfieldRenderer::render(bool cursor) { · 3 unmodified lines
2765 int width = heightfield->getHeight()->getWidth();1948 int width = heightfield->getHeight()->getWidth();
2766 int height = heightfield->getHeight()->getContents().size() / width;1949 int height = heightfield->getHeight()->getContents().size() / width;
2767 1950
2768 int innerWidth = width - 2 * HeightfieldBuffer::HEIGHT_BORDER;1951 int innerWidth = width - 2 * HeightfieldHeight::HEIGHT_BORDER;
2769 int innerHeight = height - 2 * HeightfieldBuffer::HEIGHT_BORDER;1952 int innerHeight = height - 2 * HeightfieldHeight::HEIGHT_BORDER;
2770 int vertexCount = width * height;1953 int vertexCount = width * height;
2771 int rows = height - 1;1954 int rows = height - 1;
2772 int columns = width - 1;1955 int columns = width - 1;