- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
首先,我正在尝试编写一个普通的简单 Ray Tracer。在我的 Ray Tracer 中,世界上有多种类型的几何体,它们都派生自一个名为“SceneObject”的基类。我在这里包含了它的标题。
/**
Interface for all objects that will appear in a scene
*/
class SceneObject
{
public:
mat4 M, M_inv;
Color c;
SceneObject();
~SceneObject();
/**
The transformation matrix to be applied to all points
of this object. Identity leaves the object in world frame.
*/
void setMatrix(mat4 M);
void setMatrix(MatrixStack mStack);
void getMatrix(mat4& M);
/**
The color of the object
*/
void setColor(Color c);
void getColor(Color& c);
/**
Alter one portion of the color, leaving
the rest as they were.
*/
void setDiffuse(vec3 rgb);
void setSpecular(vec3 rgb);
void setEmission(vec3 rgb);
void setAmbient(vec3 rgb);
void setShininess(double s);
/**
Fills 'inter' with information regarding an intersection between
this object and 'ray'. Ray should be in world frame.
*/
virtual void intersect(Intersection& inter, Ray ray) = 0;
/**
Returns a copy of this SceneObject
*/
virtual SceneObject* clone() = 0;
/**
Print information regarding this SceneObject for debugging
*/
virtual void print() = 0;
};
如您所见,我包含了几个要在别处实现的虚函数。在本例中,我只有两个派生类——Sphere 和 Triangle,它们都实现了缺少的成员函数。最后,我有一个 Parser 类,它充满了执行实际“光线追踪”部分的静态方法。这是相关部分的几个片段
void Parser::trace(Camera cam, Scene scene, string outputFile, int maxDepth) {
int width = cam.getNumXPixels();
int height = cam.getNumYPixels();
vector<vector<vec3>> colors;
colors.clear();
for (int i = 0; i< width; i++) {
vector<vec3> ys;
for (int j = 0; j<height; j++) {
Intersection intrsct;
Ray ray; cam.getRay(ray, i, j);
vec3 color;
printf("Obtaining color for Ray[%d,%d]\n", i,j);
getColor(color, scene, ray, maxDepth);
ys.push_back(color);
}
colors.push_back(ys);
}
printImage(colors, width, height, outputFile);
}
void Parser::getColor(vec3& color, Scene scene, Ray ray, int numBounces)
{
Intersection inter; scene.intersect(inter,ray);
if(inter.isIntersecting()){
Color c; inter.getColor(c);
c.getAmbient(color);
} else {
color = vec3(0,0,0);
}
}
现在,我放弃了真正的光线追踪部分,而是简单地返回第一个物体命中的颜色(如果有的话)。毫无疑问,您已经注意到,计算机知道光线与对象相交的唯一方法是通过 Scene.intersect(),我也将其包括在内。使用的成员变量是“vector objects” see end
好了,现在进入正题。我首先创建一个场景并用 Parser::trace() 方法之外的对象填充它。现在出于一些奇怪的原因,我为 i=j=0 施放了 Ray,一切都很好。然而,当第二条光线转换时,我场景中存储的所有对象都不再识别它们的 vfptr(也就是说,我仍然可以访问除虚拟方法之外的所有 SceneObject 方法)!我用调试器逐步检查代码,发现所有 vfptr 的信息都在 getColor() 结束和循环继续之间的某个地方丢失了。但是,如果我将 getColor() 的参数更改为使用 Scene& 而不是 Scene,则不会发生丢失。这是什么疯狂的巫术?
场景代码,按要求:
#include <vector>
#include <limits>
#include "Intersection.h"
#include "LightSource.h"
#include "SceneObject.h"
using namespace std;
/**
Contains a list of scene objects. A ray can be
intersected with a scene to find its color
*/
class Scene
{
public:
vector<SceneObject*> objects;
vector<LightSource*> lights;
Scene(void);
~Scene(void);
/**
Add an object to the scene
*/
void addObject(SceneObject& o);
/**
Add a light source to the scene
*/
void addLight(LightSource& l);
/**
Fill 'l' with all light sources in the scene
*/
void getLightSources(vector<LightSource*>& l);
/**
Fills 'i' with information regarding an
intersection with the closest object in the scene
IF there is an intersection. Check i.isIntersecting()
to see if an intersection was actually found.
*/
void intersect(Intersection& i, Ray r);
void print();
};
#include "Scene.h"
Scene::Scene(void)
{
}
Scene::~Scene(void)
{
for(int i=0;i<objects.size();i++){
delete objects[i];
}
for(int i=0;i<lights.size();i++){
delete lights[i];
}
}
void Scene::addObject(SceneObject& o)
{
objects.push_back(o.clone());
}
void Scene::addLight(LightSource& l)
{
lights.push_back(l.clone());
}
void Scene::getLightSources(vector<LightSource*>& l)
{
l = lights;
}
void Scene::intersect(Intersection& i, Ray r)
{
Intersection result;
result.setDistance(numeric_limits<double>::infinity());
result.setIsIntersecting(false);
double oldDist; result.getDistance(oldDist);
/* Cycle through all objects, making result
the closest one */
for(int ind=0; ind<objects.size(); ind++){
SceneObject* thisObj = objects[ind];
Intersection betterIntersect;
thisObj->intersect(betterIntersect, r);
double newDist; betterIntersect.getDistance(newDist);
if (newDist < oldDist){
result = betterIntersect;
oldDist = newDist;
}
}
i = result;
}
void Scene::print()
{
printf("%d Objects:\n", objects.size());
for(int i=0;i<objects.size();i++){
objects[i]->print();
}
}
最佳答案
问题是您在 Scene
的析构函数中删除了您的 SceneObjects
并且您使用默认的复制构造函数,它使用指针 vector 进行平面复制。这意味着,Scene
的每个拷贝都引用相同的 SceneObjects
。如果这些 Scene
中的一个被破坏,它们都会丢失它们所引用的对象。如果您通过引用传递场景,这没有问题,因为在这种情况下,不会创建拷贝并随后销毁。
关于c++ - 指向派生类对象的指针丢失 vfptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2707817/
有人能给我解释一下我下面程序中的一点吗我编写的以下程序是为了理解 int * const * var 的含义; #include "iostream" using namespace std ; in
我正在摆弄 C 中的指针,但仍然不确定一些非常基础的知识。我想出了以下示例代码: #include int main(void) { int num = 42; /
以下代码产生警告: const char * mystr = "\r\nHello"; void send_str(char * str); void main(void){ send_str
我正在尝试在我的 Linux 计算机上升级 cmake。这是我使用的命令。 删除旧的 cmake: sudo apt purge --auto-remove cmake 从 https://cmake
我试图借助 char 指针来追踪 union 第一个字节的值。我假设 byte1 的输出应该是 ff,但实际上是 ffffffff。如果我错了请纠正我。 #include #include #in
我正在使用微 Controller 进行一些 ADC 测量。当我尝试使用 -O2 优化编译以下代码时遇到问题,当代码中存在 PrintVal() 函数时,MCU 卡住。我做了一些调试,结果发现,当我添
#include #include using namespace std; int main () { vector qwerty; qwerty.push_back(5);
我有我的 woking setup.py 文件;其中包含以下行: home = os.environ["HOME"] # home = /home/dr in my machine; distu
这段代码 #include #include static_assert(std::is_same_v::value_type, volatile int>); 在最新的 GCC 和 clang
我对 C 中的前向声明有疑问。 代码 typedef struct yhash_s t_yhash;// forward declaration struct yhash_s { size_t
我想提取成员指针指向的成员的类型。 template void demo(myClass& instance, void* ptr) { instance.*member = *reinter
我正在尝试使用指针将一段 C 代码转换为 Swift 3。这是 C 代码中的相关部分。 Float32 sampleArray[256] = { // Array is 256 Float value
您可能知道,VLA's haves pros and cons 和它们在 C11 中是可选的。 我想使 VLA 成为可选项的主要原因是:“堆栈可能会爆炸”: int arr[n]; /* where
这段代码有什么错误?为什么我不能按照我尝试的方式取消引用该元素。 #include typedef struct { int value; struct node * left;
有什么方法可以在 JavaScript 中创建\返回指向变量的指针吗? 比如,在 PHP 中: function func() { ..... return &$result; } 我
如果您想使用方法的指针作为参数,则需要将该方法键入作为对象的函数,就像这样好 : type TAcceptor = function(filename:string):boolean of objec
很简单的问题: 我对 C++ 中的智能指针有点陌生。我想我得到了所有权的东西,但我不知道如何访问他们实际指向的内容。当我尝试使用对象的成员函数/变量时,我只是得到了 unique_ptr 类的函数,这
我得到了一个点的方位 Angular 、指南针方向和一个可以将箭头设置到某个方向的 api(0 是顶部,90 是右侧,180 是底部,360 是顶部) 如果我希望箭头指向我采用方位 Angular 形
我正在尝试找到一种方法,从单元格中获取位于当前工作表左侧(托盘下方)的工作表单元格中的数据。 我知道如何通过调用其他工作表 =Sheet1!A1 但现在我需要一些最好的解释 =Sheet[-1]!A1
所以我在 MATLAB 中有一个 for 循环,其中向量 x 将通过一个函数,比如 cos(x).^2,或者不同的选择,比如 sin(x).^2 + 9.*x。用户将在 for 循环之前选择他想使用的
我是一名优秀的程序员,十分优秀!