2016-06-02 4 views
-1

앰비언트, 확산 및 반사의 세 배열을 저장하는 재질 구조체가 있습니다. 단일 개체의 재질에 대한 정보를 저장하는 데 사용하고 있습니다. 헤더 파일 :배열 멤버가있는 구조체

struct Material 
{ 
    float (&ambient)[4], (&diffuse)[4], (&specular)[4]; 
    Material(float (&ambient)[4], float (&diffuse)[4], float (&specular)[4]); 
    float* Ambient(); 
    float* Diffuse(); 
    float* Specular(); 
} 

소스 파일 :

float random(float min, float max) 
{ 
    return min + static_cast<float> (rand())/static_cast<float> (RAND_MAX/(max - min)); 
} 

void createBall(int) 
{ 
    float ambient[] = {random(0, 1), random(0, 1), random(0, 1), 1}; 
    float diffuse[] = {random(0, 1), random(0, 1), random(0, 1), 1}; 
    float specular[] = {random(0, 1), random(0, 1), random(0, 1), 1}; 
    (...) 
    ballMaterials.push_back(Material(ambient, diffuse, specular)); 
} 

그리고 그리기 기능 :

void drawBall(float radius, Vector3& position, Material material, Rigidbody rigidbody) 
{ 
    (...) 
    glMaterialfv(GL_FRONT,GL_AMBIENT,material.Ambient()); 
    glMaterialfv(GL_FRONT,GL_DIFFUSE,material.Diffuse()); 
    glMaterialfv(GL_FRONT,GL_SPECULAR,material.Specular()); 
    glMaterialfv(GL_FRONT,GL_SHININESS,high_shininess); 
    glPushMatrix(); 
    (...) 
    glScalef(radius, radius, radius); 
    glCallList(index); 
    glPopMatrix(); 
    glutPostRedisplay(); 
} 

뭔가가

Material::Material(float (&_ambient)[4], float (&_diffuse)[4], float (&_specular)[4]): ambient{_ambient}, diffuse{_diffuse}, specular{_specular}{} 

float* Material::Ambient() 
{ 
    return ambient; 
} 

float* Material::Diffuse() 
{ 
    return diffuse; 
} 

float* Material::Specular() 
{ 
    return specular; 
} 

나는 객체 초기화이 기능이 공이 평평하고 붉은 색이어서 무작위 색이 아니기 때문에 매우 잘못되었습니다. 내가 잘못된 방법으로 구조체를 구현 한 것 같아요 (배열 구성원) 그 문제를 해결하는 방법을 잘 모르겠습니다. 당신이 나를 도울 수?

+3

사라질 지역 변수를 참조하는 것이 좋지 않습니다. 참조가있는 대신 배열의 내용을 복사 해보십시오. – MikeCAT

+1

3 개의 배열을 저장하는'Material' 구조체가 없습니다. 배열에 3 개의 * 참조를 저장하는 구조체 만 있습니다. – MikeCAT

+1

dumb float 배열과 float 포인터 대신에'std :: array '을 사용하면 모든 문제가 사라집니다. – PaulMcKenzie

답변

1

원래 구조에는 배열에 대한 참조가 포함되어 있습니다 (즉, 앰퍼샌드가 멤버 선언에서 수행하는 것입니다.) 즉, 배열은 실제로 구조 내부에 존재하지 않습니다. 그것들은 실제 위치에 대한 숨겨진 포인터를 포함합니다 (참조 = 숨겨진 포인터 [아무에게도 말하지 않습니다.).

따라서 실제 배열이 유효한 경우에만 구조가 유효합니다. CreateBall 메서드에서 로컬 변수를 할당하므로이 메서드에서 반환 되 자마자 구조가 더 이상 유효하지 않습니다. 무엇이든이 발생할 수 있습니다.

가장 간단한 해결책은 std::array<float, 4>을 사용하여 멤버를 선언하는 것입니다. 그것은 당신을 위해 모든 지저분한 세부 사항을 처리합니다. 이 방법을 사용하지 않으려면 앰퍼샌드없이 멤버 배열을 선언해야하며 실제로 인수의 생성자를 생성자로 멤버 배열의 항목으로 복사해야합니다.

참고 :

다른 사람들은 의견에 지적했습니다. 나는 이것을 대답으로 통합하고있다. (만약 당신이 의견 중 하나를 작성하고 담당자를 원한다면, 답변을 게시하고 나는 내 것을 삭제할 것이다.)

2

사용에 관한 나의 의견이 확장된다. 그리고 std::array 당신에게 당신이 뭘 하려는지의 예를 보여 주지만, 대신 std::array를 사용

#include <array> 
#include <vector> 

typedef std::array<float, 4> FloatArray4; 
struct Material 
{ 
    FloatArray4 ambient, diffuse, specular; 
    Material(const FloatArray4& ambient_, const FloatArray4& diffuse_, 
      const FloatArray4& specular_) : ambient(ambient_), diffuse(diffuse_), specular(specular_){} 

    FloatArray4& Ambient() { return ambient; } 
    FloatArray4& Diffuse() { return diffuse; } 
    FloatArray4& Specular() { return specular; } 
}; 

float random(float minVal, float maxVal) 
{ 
    return minVal + static_cast<float> (rand())/static_cast<float> (RAND_MAX/(maxVal - minVal)); 
} 

std::vector<Material> ballMaterials; 

void createBall(int) 
{ 
    FloatArray4 ambient = {{random(0, 1), random(0, 1), random(0, 1), 1}}; 
    FloatArray4 diffuse = {{random(0, 1), random(0, 1), random(0, 1), 1}}; 
    FloatArray4 specular = {{random(0, 1), random(0, 1), random(0, 1), 1}}; 
    ballMaterials.push_back(Material(ambient, diffuse, specular)); 
} 

void drawBall(float radius, Vector3& position, Material material, Rigidbody rigidbody) 
{ 
    glMaterialfv(GL_FRONT,GL_AMBIENT,material.Ambient().data()); 
    glMaterialfv(GL_FRONT,GL_DIFFUSE,material.Diffuse().data()); 
    glMaterialfv(GL_FRONT,GL_SPECULAR,material.Specular().data()); 
} 

int main() 
{ 
    createBall(10); 
} 

Live Example

주를 처리 할 포인터가 없음.

std::array은 참조로 전달되며 배열을 반환하는 함수에는 기존 std::array에 대한 참조가 반환됩니다. 다른 요구 사항 인 경우 std::array 사본을 반환하는 다른 기능을 추가 할 수 있습니다.

또한 기본 배열에 대한 액세스를 제공하는 std::array::data() 함수에 유의하십시오.